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 I

class Audio_port, code for a C++ class which models

real-time input and output



I. Motivation and Background

As stated in Appendix G, most sound processing done in this thesis used AIFF files for both input and output. Nonetheless, some experiments were done as to how much real-time processing of sound signals could be done, at standard CD-quality audio specifications (stereo, 16-bit, 44.1kHz sampling rate). To accomplish this task, an easy-to-use, object-oriented class similar to class Aiff_file (Appendix G) was built to handle real-time input and output of analog and digital samples. The constructors and general programmer interface were designed to closely resemble the constructors and general programmer interface of class Aiff_file, so that audio files and real-time input could be easily substituted in small, experiment-based programs.

Specifically, class Audio_port is a templated C++ class that models the output and input audio ports on the SGI Indy computer. In preparation for the usage of class Audio_port, the user opens the system's audio panel application to select an analog or digital input, select the appropriate analog input and output sampling and playback rates, and select the desired record, meter, monitoring levels. After this has been accomplished, the user can open the input or output audio ports in a C++ program for sample reading and writing using class Audio_port. (Both the input and output audio ports on the Indy can be switched either to analog or digital sources/destinations via the system's audio control panel application.)

II. Specific design issues

A. I/O speed.

The performance of class Audio_port was increased significantly with the use of an internal buffer similar to the one used in classes Aiff_file and WAiff_file. An internal buffer is used to hold a user's requests for input and output samples until a specified number of requests are queued. An operating system call is then made to transfer the entire block of samples to/from the output/input port, thus saving considerable time in system overhead.

B. Templating of class Audio_port.

class Audio_port is a templated class whose only template declaration argument is the type of sample to use in read/write operations for that port. Although templating can be confusing, the decision to make class Audio_port a templated class was based on the need for the flexibility in real-time I/O situations. Although an Audio_port's other, numerical arguments such as sample-rate, number of channels, bit_width are easily specified via constructor arguments, the type of audio samples to send and return is not so easily specified in a single argument; hence, the need for a templated class.

III. General Usage

class Audio_port 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" and "ac2.h" to declare class Audio_port and, 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 H, Part II.C, above. The class definition for class Audio_port has been completely written in the ac2.h file. The output will be output_binary, which can be executed directly at the command line.

A. Template instantiation, constructor and destructor.

A template declaration defines the types of samples to be used in that input or output Audio_port; however, one must also specify that type in the constructor using a pre-defined MACRO as well. The legal constructors for class Audio_port are:

1) for integer sample types

Audio_port(char* _port_name, unsigned _sr,

unsigned _num_channels, unsigned _sample_width,

int _mode,

AC_INT_SAMPLE_VALUES,

AC_THIS_FIELD_NOT_APPLICABLE_FOR_NON_FLOAT_SAMPLES)

where _port_name is an arbitrary, human-readable name used to identify the port, and

_mode is either AC_READ_ONLY or AC_WRITE_ONLY.

2) for floating point sample types

Audio_port(char* _port_name, unsigned _sr,

unsigned _num_channels,

AC_THIS_FIELD_NOT_APPLICABLE_FOR_NON_INT_SAMPLES,

int _mode,

AC_FLOAT_SAMPLE_VALUES, float _floating_point_range)

where _port_name is an arbitrary, human-readable name used to identify the port,

_mode is either AC_READ_ONLY or AC_WRITE_ONLY, and _floating_point_range is the normalized range into which samples values are cast (+_floating_point_range being the highest possible magnitude - both positive and negative - for the port).

For example, the following code opens a stereo, 44.1kHz input port that returns floating_point samples:

#include "ac.h" // provides type information and

// declarations for class Aiff_file

#include "ac2.h" // provides declaration and

// definition

// for class Audio_port

...

template class Audio_port<float_sample>

...

Audio_port real_time_input("real_time_input_port",

44100, STEREO,

AC_THIS_FIELD_NOT_APPLICABLE_FOR_NON_INT_SAMPLES,

AC_READ_ONLY, AC_FLOAT_SAMPLES, 1.0);

Similarly, the following code opens a STEREO, 44.1 kHz output port that returns 16-bit two's complement integer samples:

#include "ac.h" // provides type information and

// declarations for class Aiff_file

#include "ac2.h" // provides declaration and

// definition

// for class Audio_port

...

template class Audio_port<width_16_bit_sample>

...

Audio_port real_time_output("real_time_output_port",

44100,STEREO,

AC_WIDTH_16_BIT_SAMPLE,AC_WRITE_ONLY,

AC_INT_SAMPLE_VALUES,

AC_THIS_FIELD_NOT_APPLICABLE_FOR_NON_FLOAT_SAMPLES);

B. Reading and writing audio samples from/to an Audio_port

Note that one frame of audio is equivalent to x samples of audio, where x is the number of channels of audio in the file. Therefore, in allocating memory that is passed into these functions, allocate (num_channels * desired_size) elements to the buffer you intend to pass to the function. Frames of audio are passed and returned sequentially, with each channel of audio being presented sequentially in each frame of audio (e.g. for a stereo buffer using floating point sample values, the buffer will contain these samples, in order: 0L, 0R, 1L, 1R, 2L, 2R, etc., where 0,1,2 represent the frame number, and L, R represent the channel number).

Receive one frame of audio from an input Audio_port.

void

receive_frame(ElementType* user_buffer)

Receive multiple frames of audio from an input Audio_port.

void

receive_frames(ElementType* user_buffer,

unsigned long num_frames_to_receive)

Send one frame of audio to an output Audio_port.

void

send_frame(ElementType* user_buffer)

Send multiple frames of audio to an output Audio_port.

void

send_frames(ElementType* user_buffer,

unsigned long num_frames_to_send)

IV. Examples

The following table lists some examples that make exclusive use of class Audio_port.
filedescription
audio_port_test.cc demonstration of floating point and integer input and output sample types with a simple monitor-input program.
audio_port_test2.cc example of real-time digital filtering with class Filter (Appendix K).

Table I.1


V. Future directions

The current templated implementation of class Audio_port is not elegant in that the type of the samples sent or retrieved from the port must be specified twice during an Audio_port's instantiation: once in the template declaration, and once in the constructor. A better implementation of this class would eliminate one of these declarations, so that a single line of code could specify a single type of sample handled by a single Audio_port.

Furthermore, although the error-checking is designed in a similar manner to classes Aiff_file and WAiff_file, there are several member functions in class Audio_port which do not robustly handle errors. A significant improvement could be made to improve error handling in these cases.


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