The callback code used in the MixerHost sample code is set up for looping audio files. The loop happens when the current samplenumber reaches the frameTotalForSound value and gets reset to 0.
What is a safe way to exit the callback when the end of the audio file data is reached? Exiting the for..loop or commenting out the code line that resets the samplenumber gives me a digital noise burst at the end of the file that is playing.
any suggestions would be appreciated.
static OSStatus inputRenderCallback (
void *inRefCon, // A pointer to a struct containing the complete audio data
// to play, as well as state information such as the
// first sample to play on this invocation of the callback.
AudioUnitRenderActionFlags *ioActionFlags, // Unused here. When generating audio, use ioActionFlags to indicate silence
// between sounds; for silence, also memset the ioData buffers to 0.
const AudioTimeStamp *inTimeStamp, // Unused here.
UInt32 inBusNumber, // The mixer unit input bus that is requesting some new
// frames of audio data to play.
UInt32 inNumberFrames, // The number of frames of audio to provide to the buffer(s)
// pointed to by the ioData parameter.
AudioBufferList *ioData // On output, the audio data to play. The callback's primary
// responsibility is to fill the buffer(s) in the
// AudioBufferList.
) {
soundStructPtr soundStructPointerArray = (soundStructPtr) inRefCon;
UInt32 frameTotalForSound = soundStructPointerArray[inBusNumber].frameCount;
BOOL isStereo = soundStructPointerArray[inBusNumber].isStereo;
// Declare variables to point to the audio buffers. Their data type must match the buffer data type.
AudioUnitSampleType *dataInLeft;
AudioUnitSampleType *dataInRight;
dataInLeft = soundStructPointerArray[inBusNumber].audioDataLeft;
if (isStereo) dataInRight = soundStructPointerArray[inBusNumber].audioDataRight;
// Establish pointers to the memory into which the audio from the buffers should go. This reflects
// the fact that each Multichannel Mixer unit input bus has two channels, as specified by this app's
// graphStreamFormat variable.
AudioUnitSampleType *outSamplesChannelLeft;
AudioUnitSampleType *outSamplesChannelRight;
outSamplesChannelLeft = (AudioUnitSampleType *) ioData->mBuffers[0].mData;
if (isStereo) outSamplesChannelRight = (AudioUnitSampleType *) ioData->mBuffers[1].mData;
// Get the sample number, as an index into the sound stored in memory,
// to start reading data from.
UInt32 sampleNumber = soundStructPointerArray[inBusNumber].sampleNumber;
// Fill the buffer or buffers pointed at by *ioData with the requested number of samples
// of audio from the sound stored in memory.
for (UInt32 frameNumber = 0; frameNumber < inNumberFrames; ++frameNumber) {
outSamplesChannelLeft[frameNumber] = dataInLeft[sampleNumber];
if (isStereo) outSamplesChannelRight[frameNumber] = dataInRight[sampleNumber];
sampleNumber++;
// After reaching the end of the sound stored in memory--that is, after
// (frameTotalForSound / inNumberFrames) invocations of this callback--loop back to the
// start of the sound so playback resumes from there.
if (sampleNumber >= frameTotalForSound) sampleNumber = 0; //commenting this outremoves loop, but creates noise at end of file
//if (sampleNumber == frameTotalForSound) break; //digital noize !!
}
// Update the stored sample number so, the next time this callback is invoked, playback resumes
// at the correct spot.
soundStructPointerArray[inBusNumber].sampleNumber = sampleNumber;
return noErr;
}