Sampling Rates and Resampling Rates
When first initialized, the buffers that are passed between the AFSoundcard and its delegate are sampled at the sampling rate of the physical device. As mentioned in the previous section, the device's sampling rate can be requested with the -samplingRate method of the AFSoundcard.
You can ask AFSoundcard to resample the data so that the sampling rates of the buffers are done at a different rate than the device's sampling rate.
The resampling rate (the sampling rate that the buffers use to transfer data) can be read from and set to the AFSoundcard with
-
(float)resamplingRate ;
- (void)setResamplingRate:(float)rate ;
- (void)setResamplingRate:(float)rate ;
The resampling rate is scaled from nominal sampling rate of the physical device. If the sampling clock in a physical audio device is off from its designed value by 0.1%, you can expect the resampling rate to also be off by the same 0.1%.
Setting the resampling rate to 0 sets the sampling rate of interface with the client to the same as the device's physical sampling rate.
By setting AFSoundcard to a known fixed resampling rate, the delegate is ensured of receiving a constant rate data stream even if some other process has changed the device sampling rate. The only downside of doing this is that the resampling process will incur some distortion. If you wish to have the cleanest input or output, use the sampling rate of the device; in which case you will need to keep track of the actual sampling rate.
The input AFSoundcard uses the Core Audio AudioConverter to perform sample rate conversion. The output AFSoundcard uses the varispeed Core Audio (see below) AudioUnit.
The AudioConverter is capable of higher quality resampling (less harmonic distortion and lower intermodulation distortion) than the varispeed AU (the input is more likely to need a higher quality resampling process than the output since you have less control of the contents of the input signal).
The resampling quality of the AudioConverter in the input AFSoundcard can be read and set with:
-
(int)resamplingQuality
;
- (void)setResamplingQuality:(int)quality ;
- (void)setResamplingQuality:(int)quality ;
The output AFSoundcard does not use the resampling quality property and its -resamplingQuality will return 0.
The resampling quality of an input AFSoundcard is an integer between 0 and 4 and corresponds respectively to the following in Core Audio:
kAudioConverterQuality_Min
kAudioConverterQuality_Low
kAudioConverterQuality_Medium
kAudioConverterQuality_High
kAudioConverterQuality_Max
kAudioConverterQuality_Low
kAudioConverterQuality_Medium
kAudioConverterQuality_High
kAudioConverterQuality_Max
The resampling quality defaults to 3 (kAudioConverterQuality_High) at the time when the input AFSoundcard is initialized. The lower resampling qualities has less processor burden.
The output AFSoundcard uses the varispeed Audio Unit to perform sample rate conversion. This allows an output AFSoundcard to track the hardware sampling clock of the device in an input AFSoundcard. Without this capability, the buffers that are generated from a physical input device will eventually over-run or under-run the output buffers if the hardware sampling clock frequency of the input sound device is different from the hardware sampling clock frequency of the output sound device. Hardware clocks for different devices are almost guaranteed to be different from one another.
The resampling rate of the output AFSoundcard controls the rate the delegate is called with outputNeededForSoundcard (as described earlier).
Pushing Audio Buffers
Audio Library provides a "push" interface in an output AFSoundcard to handle the case where the data for the output AFSoundcard is directly from samples that are clocked from an input AFSoundcard.
The following shows a "playthrough" example that pushes data from an input AFSoundcard to an output AFSoundcard.
-
(void)inputReceivedFromSoundcard:(AFSoundcard*)soundcard
buffers:(float**)buffers numberOfBuffers:(int)n
samples:(int)m
{
{
[
outputSoundcard pushBuffers:buffers numberOfBuffers:n
samples:m rateScalar:[ soundcard rateScalar ] ] ;
}
The -inputReceivedFromSoundcard method is called from an input AFSoundcard when the sound card has a new buffer available. Notice that the -pushBuffers method includes a rateScalar parameter (a 64 bit floating point number) to inform the output AFSoundcard how much the actual input device sampling rate deviates from its nominal sampling rate. The output AFSoundcard uses this to apply a similar deviation to the varispeed unit in the output AFSoundcard. The rateScalar of an input sound device with a perfect hardware clock is 1.0.
To use -pushBuffers in the simple "playthrough" example that is shown above, both the input AFSoundcard and the output AFSoundcard should have an identical resampling rate, the same number of active channels and the same buffer length.