amici smallImplementation Notes

This page includes some details for software developers who may wish to extend the capability of Amnici, or change some of its behavior.

Audio

Amici does not use Core Audio directly. It uses the Audio Library framework, and Amici embeds the framework into the application bundle as described here.

Input.m is associated with the input sound card, and TrackingGenerator.m is associated with the output sound card. All sound card menus and controls are implemented as
Managed Controls of the Audio Library framework.


Bandwidth

The comments at the beginning of Spectrum.m contains some details on effective bandwidths of a Hann window, a Blackman window and a Gaussian window with various variance (sigma). For example, the effective bandwidth of the Hann is the well known factor of 1.5. The factor of the Blackman window is 1.728 and the Gaussian's bandwidth can be controlled by the Gaussian's standard deviation.

To get spectrum using the Hann or Blackman windows, the width of the window is first determined from the required bandwidth. An FFT size (power of 2) that is larger than the window width is then chosen, and the window is zero filled to discard the unwanted samples. As a result, each bin will have a bandwdith that is greater than a
bin width of the resultant transform and also as a consequence, the resultant bins will have overlapping passbands.

Windowing basically trades off the response of far-away bins (e.g., the sin(f)/f response of an unwindowed FFT) by widening the response from the adjacent bins. The "frequency response" of a Hann window, for example, covers 3 bins with a (0.5,1,0.5), i.e., the transfer function overlaps by a factor of 0.5 into adjacent bins.

In addition to that, Amici further shrinks the window width to obtain bandwidths that are perfect 5 dB multiples of 1 Hz.

Because a Gaussian has an infinitely long tail and the values at the ends of a finite window will not be zero, the Gaussian is multiplied by a Hann and used as the "Gaussian window"). This avoids the display from "bouncing" from trace to trace due to boundary value conditions (one of the reasons why practical Fourier windows have zero at the ends). As can be seen in the figures in the Resolution Bandwidth section of the Amici manual, this extra Hann window does not destroy the primary characteristic of the Gaussian, not raise the filter sidelobes to any important degree.

As a result, the computation of the bandwidth of the Gaussian+Hann combination is rather convoluted [sic]., as seen in the
-generateGaussian:length:fraction: in Spectrum.m. From a given variance, the variance (2.25) due to the Hann window is first subtracted (the standard distribution of the Hann contributing to its effective bandwidth is 1.5, and the square of it is subtracted from the desired bandwidth of the combined Gaussian+Hann).

A lot of work had gone into this part of Amici's design. But I wanted a spectrum analyzer that is calibrated for 1 Hz bandwidth (and 5 dB steps from there:, viz. 3.16 Hz, 10 Hz, 31.6 Hz, 100 Hz), not some arbitarry bandwidth that depends on the size of the FFT and the sampling rate.


Test Generator

Amici replaces the input samples (but keeps using the input device's sampling rate) in -
inputReceivedFromSoundcard:buffers:numberOfBuffers:samples: of input.m if you define the string TESTSOURCE in input.h.

In addition to a sinusoid, the test generator adds a noise term from a uniformly distributed random number generator that is scaled by sqrt(3). (Recall that a uniform probability density function between (-1,+1) has a variance of 3). This noise energy is distributed evenly between 0 and N/2 Hertz when the sampling rate is N samples per second.


Tracking Generator

Amici generates a new buffer with the sin() function each time the output sound card requires it. The argument T of sin() is a second order DDA (digital differential analyzer). The first order term dT defines the frequency term and is determined by the instantaneous frequency of the tracking generator and sampling rate of the output sound card. The second order term d
2T is the linear sweep term of the tracking generator.

Both dT and d
2T are defined when the tracking generator is started in the -start: method.

To avoid any potential rounding errors over a sweep, AppDelegate.m calls -
updateFrequency: in TrackingGenerator.m to recompute the value of dT after it finishes gathering the spectrum from Spectrum.h.