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


Appendix K

class Filter, code for a C++ class which models a real-time,

time-domain digital audio filter



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.
CD Track # Audio examplefile description
95k.1 filter_test.cc demonstration of low pass filtering on an existing soundfile. original soundfile (Beethoven)
96k.2 filter_test.cc demonstration of low pass filtering on an existing soundfile. processed soundfile (Beethoven)
N/AN/A filter_test2.cc demonstration of different types of filters (low-pass, high-pass, notch) working on real-time audio input

Table K.1

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