This page includes some details for software developers who may wish to extend the capability of Amnici, or change some of its behavior.
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.
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 bandwidth 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, nor raise the filter sidelobes to any important degree.
As a result, the computation of the bandwidth of the
Gaussian+Hann combination is rather convoluted, as
seen in the generateGaussian:length:fraction:method 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).
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.
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 d2T is the linear sweep term of the tracking generator.
Both dT and d2T are defined when the tracking
generator is started in the start: method.
To avoid any potential rounding errors over a sweep,
AppDelegate calls updateFrequency: in
TrackingGenerator.m to recompute the value of dT after it
finishes gathering the spectrum from Spectrum.h.