Finite Impulse Response Filters#
Finite impulse response (FIR) filters allow the use of arbitrary filters with a finite number of taps. This library does not provide FIR filter design tools, but allows for coefficients to be imported from other design tools, such as SciPy/filter_design.
FIR Direct#
The direct FIR implements the filter as a convolution in the time domain.
This library uses FIR filter_fir_s32
implementation from lib_xcore_math
to run on xcore.
More information on implementation can be found in XCORE Math Library documentation.
- class audio_dsp.dsp.fir.fir_direct(fs: float, n_chans: int, coeffs_path: Path, Q_sig: int = 27)
An FIR filter, implemented in direct form in the time domain.
When the filter coefficients are converted to fixed point, if there will be leading zeros, a left shift is applied to the coefficients in order to use the full dynamic range of the VPU. A subsequent right shift is applied to the accumulator after the convolution to return to the same gain.
- Parameters:
- fsint
Sampling frequency in Hz.
- n_chansint
Number of channels the block runs on.
- coeffs_pathPath
Path to a file containing the coefficients, in a format supported by np.loadtxt.
- Q_sig: int, optional
Q format of the signal, number of bits after the decimal point. Defaults to Q4.27.
- Attributes:
- fsint
Sampling frequency in Hz.
- n_chansint
Number of channels the block runs on.
- Q_sig: int
Q format of the signal, number of bits after the decimal point.
- coeffsnp.ndarray
Array of the FIR coefficients in floating point format.
- coeffs_intlist
Array of the FIR coefficients in fixed point int32 format.
- shiftint
Right shift to be applied to the fixed point convolution result. This compensates for any left shift applied to the coefficients.
- n_tapsint
Number of taps in the filter.
- buffernp.ndarray
Buffer of previous inputs for the convolution in floating point format.
- buffer_intlist
Buffer of previous inputs for the convolution in fixed point format.
- buffer_idxlist
List of the floating point buffer head for each channel.
- buffer_idx_intlist
List of the fixed point point buffer head for each channel.
- process(sample: float, channel: int = 0) float
Update the buffer with the current sample and convolve with the filter coefficients, using floating point math.
- Parameters:
- samplefloat
The input sample to be processed.
- channelint
The channel index to process the sample on.
- Returns:
- float
The processed output sample.
- reset_state() None
Reset all the delay line values to zero.
- check_coeff_scaling()
Check the coefficient scaling is optimal.
If there will be leading zeros, calculate a shift to use the full dynamic range of the VPU
Block Time Domain FIR#
The block time domain FIR implements the filter as a convolution in the time domain, but with a block size optimized for execution on the vector-unit of xcore.ai. The advantage with this one is it is over twice the efficiency of the lib_xcore_math implementation. This block will generate C code for the block time domain FIR filter. More information on implementation can be found in AN02027: Efficient computation of FIR filters on the XCORE.
Note
The block time domain FIR filter is not currently implemented as a DSP Stage, so cannot be used with the DSP pipeline tool yet.
Autogenerator
- audio_dsp.dsp.td_block_fir.generate_td_fir(td_coefs: ndarray, filter_name: str, output_path: Path, frame_advance=8, gain_db=0.0, verbose=False)
Convert the input filter coefficients array into a header with block time domain structures to be included in a C project.
- Parameters:
- td_coefsnp.ndarray
This is a 1D numpy float array of the coefficients of the filter.
- filter_namestr
For use in identification of the filter from within the C code. All structs and defines that pertain to this filter will contain this identifier.
- output_pathstr
Where to output the resulting header file.
- frame_advanceint, optional
The size in samples of a frame, measured in time domain samples, by default 8. Only multiples of 8 are supported.
- gain_dbfloat, optional
A gain applied to the filter’s output, by default 0.0
- verbosebool, optional
Enable verbose printing, by default False
- Raises:
- ValueError: Bad config - Must be fixed
-
void td_block_fir_data_init(td_block_fir_data_t *fir_data, int32_t *data, uint32_t data_buffer_elements)#
Initialise a time domain block FIR data structure.
This manages the input data, rather than the coefficients, for a time domain block convolution. The python filter generator should be run first resulting in a header that defines the parameters for this function.
For example, running the generator with
--name={NAME}
would generate defines prepended with{NAME}
, i.e.{NAME}_DATA_BUFFER_ELEMENTS
,{NAME}_TD_BLOCK_LENGTH
, etc. This function should then be called with:td_block_fir_data_t {NAME}_fir_data; int32_t {NAME}_data[{NAME}_DATA_BUFFER_ELEMENTS]; td_block_fir_data_init(&{NAME}_fir_data, {NAME}_data, {NAME}_DATA_BUFFER_ELEMENTS);
- Parameters:
fir_data – Pointer to struct of type td_block_fir_data_t
data – Pointer to an amount of memory to be used by the struct in order to hold a history of the samples. The define
{NAME}_DATA_BUFFER_ELEMENTS
specifies exactly the number of int32_t elements to allocate for the filter{NAME}
to correctly function.data_buffer_elements – The number of words contained in the data array, this should be
{NAME}_DATA_BUFFER_ELEMENTS
.
-
void td_block_fir_add_data(int32_t samples_in[TD_BLOCK_FIR_LENGTH], td_block_fir_data_t *fir_data)#
Function to add samples to the FIR data structure.
- Parameters:
samples_in – Array of int32_t samples of length TD_BLOCK_FIR_LENGTH.
fir_data – Pointer to struct of type td_block_fir_data_t to which the samples will be added.
-
void td_block_fir_compute(int32_t samples_out[TD_BLOCK_FIR_LENGTH], td_block_fir_data_t *fir_data, td_block_fir_filter_t *fir_filter)#
Function to compute the convolution between fir_data and fir_filter.
- Parameters:
samples_out – Array of length TD_BLOCK_FIR_LENGTH(8), which will be used to return the processed samples.
fir_data – Pointer to struct of type td_block_fir_data_t from which the data samples will be obtained.
fir_filter – Pointer to struct of type td_block_fir_filter_t from which the coefficients will be obtained.
- class audio_dsp.dsp.td_block_fir.fir_block_td(fs: float, n_chans: int, coeffs_path: Path, filter_name: str, output_path: Path, frame_advance=8, gain_db=0.0, Q_sig: int = 27)
An FIR filter, implemented in block form in the time domain.
This will also autogenerate a .c and .h file containing the optimised block filter structures, designed for use in C.
- Parameters:
- fsint
Sampling frequency in Hz.
- n_chansint
Number of channels the block runs on.
- coeffs_pathPath
Path to a file containing the coefficients, in a format supported by np.loadtxt.
- filter_namestr
Name of the filter, used for the autogen struct name
- output_pathPath
Output path for the autogenerated .c and .h files
- frame_advanceint, optional
Number of samples processed by the filter at once. This should be set to the same as the DSP pipeline frame size, and must be a multiple of 8.
- gain_dbfloat, optional
Additional gain applied by the filter
- Q_sig: int, optional
Q format of the signal, number of bits after the decimal point. Defaults to Q4.27.
- Attributes:
- fsint
Sampling frequency in Hz.
- n_chansint
Number of channels the block runs on.
- Q_sig: int
Q format of the signal, number of bits after the decimal point.
- coeffsnp.ndarray
Time domain coefficients
- n_tapsint
Length of time domain filter
- frame_advanceint
The number of new samples between subsequent frames.
- buffernp.ndarray
Buffer of previous inputs for the convolution in floating point format.
- buffer_intlist
Buffer of previous inputs for the convolution in fixed point format.
- process_frame(frame: list)
Update the buffer with the current samples and convolve with the filter coefficients, using floating point math.
- Parameters:
- framelist[float]
The input samples to be processed.
- Returns:
- float
The processed output sample.
- reset_state() None
Reset all the delay line values to zero.
Block Frequency Domain FIR#
This implementation is a frequency-domain implementation resulting in a lower algorithmic complexity than the time-domain versions. This will achieve the highest taps per second possible with the xcore. The main cost to using this implementation is the memory requirements double compared to the previous two time-domain versions. This block will generate C code for the block frequency domain FIR filter. More information on implementation can be found in AN02027: Efficient computation of FIR filters on the XCORE.
Note
The block time domain FIR filter is not currently implemented as a DSP Stage, so cannot be used with the DSP pipeline tool yet.
Autogenerator
- audio_dsp.dsp.fd_block_fir.generate_fd_fir(td_coefs: ndarray, filter_name: str, output_path: Path, frame_advance: int, frame_overlap: int = 0, nfft: Optional[int] = None, gain_db: float = 0.0, verbose=False)
Convert the input filter coefficients array into a header with block frequency domain structures to be included in a C project.
- Parameters:
- td_coefsnp.ndarray
This is a 1D numpy float array of the coefficients of the filter.
- filter_namestr
For use in identification of the filter from within the C code. All structs and defines that pertain to this filter will contain this identifier.
- output_pathstr
Where to output the resulting header file.
- frame_advanceint
The number of new samples between subsequent frames.
- frame_overlapint, optional
The number of additional samples to output per frame. This allows windowing between frames to occur. By default no overlap occurs.
- nfftint, optional
The FFT size in samples of a frame, measured in time domain samples. If this is not set, the FFT size is set automatically. An initial attempt of
nfft = 2**(ceil(log2(frame_advance)) + 1)
is made, but may need to be increased for longer overlaps. If it is set, it must be a power of 2.- gain_dbfloat, optional
A gain applied to the filters output, by default 0.0
- verbosebool, optional
Enable verbose printing, by default False
- Raises:
- ValueError: Bad config - Must be fixed
-
void fd_block_fir_data_init(fd_fir_data_t *fir_data, int32_t *data, uint32_t frame_advance, uint32_t block_length, uint32_t block_count)#
Initialise a frequency domain block FIR data structure.
This manages the input data, rather than the coefficients, for a frequency domain block convolution. The python filter generator should be run first resulting in a header that defines the parameters for this function.
For example, running the generator with
--name={NAME}
would generate defines prepended with{NAME}
, i.e.{NAME}_DATA_BUFFER_ELEMENTS
,{NAME}_TD_BLOCK_LENGTH
, etc. This function should then be called with:fd_fir_data_t {NAME}_fir_data; int32_t {NAME}_data[{NAME}_DATA_BUFFER_ELEMENTS]; fd_block_fir_data_init(&{NAME}_fir_data, {NAME}_data, {NAME}_FRAME_ADVANCE, {NAME}_TD_BLOCK_LENGTH, {NAME}_BLOCK_COUNT);
- Parameters:
fir_data – Pointer to struct of type fd_fir_data_t.
data – An area of memory to be used by the struct in order to hold a history of the samples. The define {NAME}_DATA_BUFFER_ELEMENTS specifies exactly the number of int32_t elements to allocate for the filter {NAME} to correctly function.
frame_advance – The number of samples contained in each frame, i.e. the samples count between updates. This should be initialised to {NAME}_FRAME_ADVANCE.
block_length – The length of the processing block, independent to the frame_advance. Must be a power of two. This should be initialised to {NAME}_TD_BLOCK_LENGTH.
block_count – The count of blocks required to implement the filter. This should be initialised to {NAME}_BLOCK_COUNT.
-
void fd_block_fir_add_data(int32_t *samples_in, fd_fir_data_t *fir_data)#
Function to add samples to the FIR data structure.
- Parameters:
samples_in – Array of int32_t samples of length expected to be fir_data->frame_advance.
fir_data – Pointer to struct of type fd_fir_data_t to which the samples will be added.
-
void fd_block_fir_compute(int32_t *samples_out, fd_fir_data_t *fir_data, fd_fir_filter_t *fir_filter)#
Function to compute the convolution between fir_data and fir_filter.
- Parameters:
samples_out – Array of length fir_data->td_block_length, which will be used to return the processed samples. The samples will be returned from element 0 for
(fir_data-td_block_length + 1 - fir_filter->taps_per_block)
elements. The remaining samples of the array are used as scratch for the processing to be in-place.fir_data – Pointer to struct of type fd_fir_data_t from which the data samples will be obtained.
fir_filter – Pointer to struct of type fd_fir_filter_t from which the coefficients will be obtained.
- class audio_dsp.dsp.fd_block_fir.fir_block_fd(fs: float, n_chans: int, coeffs_path: Path, filter_name: str, output_path: Path, frame_advance: int, frame_overlap: int = 0, nfft: Optional[int] = None, gain_db: float = 0.0, Q_sig: int = 27)
An FIR filter, implemented in block form in the frequency domain.
This will also autogenerate a .c and .h file containing the optimised block filter structures, designed for use in C.
- Parameters:
- fsint
Sampling frequency in Hz.
- n_chansint
Number of channels the block runs on.
- coeffs_pathPath
Path to a file containing the coefficients, in a format supported by np.loadtxt.
- filter_namestr
For use in identification of the filter from within the C code. All structs and defines that pertain to this filter will contain this identifier.
- output_pathstr
Where to output the resulting header file.
- frame_advanceint
The number of new samples between subsequent frames.
- frame_overlapint, optional
The number of additional samples to output per frame. This allows windowing between frames to occur. By default no overlap occurs.
- nfftint, optional
The FFT size in samples of a frame, measured in time domain samples. If this is not set, the FFT size is set automatically. An initial attempt of
nfft = 2**(ceil(log2(frame_advance)) + 1)
is made, but may need to be increased for longer overlaps. If it is set, it must be a power of 2.- gain_dbfloat, optional
A gain applied to the filters output, by default 0.0
- Q_sig: int, optional
Q format of the signal, number of bits after the decimal point. Defaults to Q4.27.
- Attributes:
- fsint
Sampling frequency in Hz.
- n_chansint
Number of channels the block runs on.
- Q_sig: int
Q format of the signal, number of bits after the decimal point.
- coeffsnp.ndarray
Time domain coefficients
- n_tapsint
Length of time domain filter
- frame_advanceint
The number of new samples between subsequent frames.
- frame_overlapint
The number of additional samples to output per frame.
- nfftint, optional
The FFT size in samples of a frame.
- coeffs_fsnp.ndarray
The frequency domain coefficients.
- n_fd_buffersint
The number of frames of frequency domain coefficients, set the number of buffers that need to be saved.
- td_buffernp.ndarray
Buffer of last nfft time domain inputs in floating point format
- td_buffer_intlist
Buffer of last nfft time domain inputs in fixed point format
- fd_buffernp.ndarray
Buffer of last n_fd_buffers of the spectrums of previous td_buffers.
- process_frame(frame: list)
Update the buffer with the current samples and convolve with the filter coefficients, using floating point math.
- Parameters:
- framelist[float]
The input samples to be processed.
- Returns:
- float
The processed output sample.
- reset_state() None
Reset all the delay line values to zero.