Go to: Title Page Chapter 1 Appendix A Appendix J Copyright Chapter 2 Appendix B Appendix K Abstract Chapter 3 Appendix C Appendix L Acknowledgements Chapter 4 Appendix D References Table of Contents Chapter 5 Appendix E List of Figure Conclusions/ Appendix F List of Tables Future Directions Appendix G List of Audio Examples Appendix H List of Programs Appendix I
I. Motivation and background
This appendix documents class Filter, a templated C++ class which models a real-time time-domain digital audio filter. Typically, digital filters process input samples in small chunks, or windows of data. However, this segmentation of data often leads to filter artifacts at the window boundaries which have periodic, audible effects on the processed sound. class Filter tries to eliminate the boundary effects of windowed filtering by using a delay line for sound processing, since the processing of continuous sound with a delayline eliminates the need for data segmentation altogether.
There are two delaylines associated with each
Filter, one for "previous input" samples, and one for
"previous output" samples. Therefore, class Filter can
model both FIR and IIR filters by specifying non-zero filter coefficients
for both previous inputs and outputs. Specifically, for each input
sample, a new sample is enqueued in the "previous input"
delay line, and an old sample is dequeued from the "previous
input" delay line. Next, the "previous input" filter
coefficients (FIR filter coefficients), specified upon the Filter's
construction, are multiplied by their corresponding delayed sample
values, taken from tapping the "previous input" delay
line. The overall summation of these products is, by definition
of the general filter equation, the convolution of the filter
coefficients with the input signal, or simply the output sample
value. This value is set aside while a similar calculation, or
convolution, is processed for the "previous output"
filter coefficients, (IIR filter coefficients) and the "previous
output" delay line. The set aside value, or output value,
is enqueued in the "previous output" delay line, and
a sample is dequeued from the "previous output" delayline.
This same output value is returned to the user.
II. Specific design issues
A. Re-use of class Delayline code.
Since delaylines are used extensively in class
Filter, class Delayline was incorporated into the definition of
class Filter. Specifically, two instantiations of class Delayline
are made within class Filter to model the previous input and previous
output delay lines.
B. Single-line input, processing, and output
Since the filter coefficients, tap locations,
and delayline specifications are all specified in the constructor
for a class, and since the filter coefficients are assumed to
be constant throughout the lifetime of the filter, it was possible
to write a one-line command for the entire processing of a single
sample of audio. This simplification not only handles all of the
operations specified in I. above, but it also the makes the programming
of real-time filtering of audio processing loops (which typically
execute one time per sample) intuitive for each pass of the loop.
C. Use of templates
Since class Delayline is a templated class,
class Filter is also a templated class - the user can select,
through the use of template instantiation, what kinds of samples
the filter will handle.
III. General Usage
class Filter is designed to be as simple as
possible; the best way to learn its usage, therefore, is to refer
to the included examples. The user must #include "ac.h";
"ac2.h"; and "filter.h" to declare and define
class Filter, its member functions and data, and other supporting
macro definitions. All example programs in this section can be
compiled with the following command. The audio libraries libaudio.a
and libaudiofile.a, available in standard releases of the Irix
operating system, are required for compilation:
g++ -o output_binary <filename.cc>
ac.cc ac.error.cc -laudio -laudiofile
ac.cc provides definitions for class Aiff_file's
member functions, and ac.error.cc provides definitions for the
error codes referenced in Appendix G, part II.C. The class definition
for class Filter has been completely written in the filter.h file.
The output will be output_binary, which can be executed directly
at the command line.
A. Construction and destruction, setting up filter coefficients
The construction of a Filter takes the number of filter coefficients, the previous input and output (FIR and IIR, respectively) filter coefficients, and the previous input and output tap locations (associated with the filter coefficients) as input arguments. The maximum number of previous inputs and outputs parameters, along with the oldest possible previous input and output tap location parameters, are provided to allow for future improvements to this class which will allow the number and value of previous input and output filter coefficients to vary over time. In the current implementation, they should just be set equal to the number of previous inputs and outputs parameters, respectively.
class Filter associates the previous input and output filter coefficient arrays with corresponding tap locations stored in the previous input and output tap location arrays. In this manner, the user can specify the coefficients in any order, just as long as the corresponding tap values array contains the appropriately associated tap location values. For reference, a previous input tap location of 0 corresponds to the current input sample; the "previous input gain" value corresponding to tap location zero is therefore the 0th FIR filter coefficient. Similarly, previous input tap location 1's corresponding previous input gain corresponds to filter coefficient 1, which details how much of the previous sample delay is added to the final convolution sum for that particular output sample. Previous output tap location 0 is undefined; the first available previous input is previous output tap location 1, whose corresponding previous output gain is the first FIR filter coefficient.
See the included code examples for demonstrations
of the correct instantiation of several different types of FIR
and IIR filters.
Filter(int _num_previous_inputs,
int _max_possible_previous_inputs,
int _oldest_possible_previous_input_tap_location,
float* _previous_input_tap_locations,
float* _previous_input_gains,
int _num_previous_outputs,
int _max_possible_previous_outputs,
int _oldest_possible_previous_output_tap_location,
float* _previous_output_tap_locations,
float* _previous_output_gains)
B. Processing data
Once the filter has been constructed, one
uses a single command to input a sample, process the sample, and
retrieve a single-sample processed output. The following member
function's only argument is its input, while its return value
is the processed output of the filter.
ElementType process(ElementType input)
IV. Examples
The following table lists some examples that
make exclusive use of class Filter. All audio examples can be
found in the included compact disc.
V. Future Directions
In the current implementation, the filter's previous input and previous output filter coefficients and tap values cannot be changed in real time. A different implementation would allow these real-time alterations.
This filter models real-time input and output;
however, at the expense of boundary artifacts, it would also be
useful to have a member function that could handle chunks of data
as well; this way, the same class could adapt to many different
non-real time applications which require windowing, such as FFT-based
filtering.
Go to: Title Page Chapter 1 Appendix A Appendix J Copyright Chapter 2 Appendix B Appendix K Abstract Chapter 3 Appendix C Appendix L Acknowledgements Chapter 4 Appendix D References Table of Contents Chapter 5 Appendix E List of Figure Conclusions/ Appendix F List of Tables Future Directions Appendix G List of Audio Examples Appendix H List of Programs Appendix I