Question

I'm trying to write a bunch of samples to a a TPCircularBuffer, provided Michael Tyson by http://atastypixel.com/blog/a-simple-fast-circular-buffer-implementation-for-audio-processing/comment-page-1/#comment-4988

I am successful in playing back these recorded samples in real time. Something like a monitor.

However, I wish to keep the samples in the TPCircularBuffer for later playback, and so I implemented 2 flags, rio->recording and rio->playing. My idea was that I would activate rio->recording to be YES using a button. Record for a while, and then stop recording by setting the flag to be NO. Theoretically, TPCircularBuffer would have my audio info saved.

However, when I activate rio->playing to be YES in the playback Callback, I simply hear some jittery sound that has no semblance of what I recorded.

Am I using the buffer correctly? Or is this usually done another way?

Thanks.

Pier.

static OSStatus recordingCallback(void *inRefCon, 
                              AudioUnitRenderActionFlags *ioActionFlags, 
                              const AudioTimeStamp *inTimeStamp, 
                              UInt32 inBusNumber, 
                              UInt32 inNumberFrames, 
                              AudioBufferList *ioData) {

RIO *rio = (RIO*)inRefCon;
AudioUnit rioUnit = rio->theAudioUnit;
//ExtAudioFileRef eaf = rio->outEAF;
AudioBufferList abl = rio->audioBufferList;

SInt32 samples[NUMBER_OF_SAMPLES]; // A large enough size to not have to worry about buffer overrun
abl.mNumberBuffers = 1;
abl.mBuffers[0].mData = &samples;
abl.mBuffers[0].mNumberChannels = 1;
abl.mBuffers[0].mDataByteSize = inNumberFrames  * sizeof(SInt16);

OSStatus result;
result = AudioUnitRender(rioUnit, 
                         ioActionFlags, 
                         inTimeStamp,
                         inBusNumber, 
                         inNumberFrames, 
                         &abl);

if (noErr != result) { NSLog(@"Obtain recorded samples error"); }

// React to a recording flag, if recording, save the abl into own buffer, else ignore
if (rio->recording)
{   
    TPCircularBufferProduceBytes(&rio->buffer, abl.mBuffers[0].mData, inNumberFrames  * sizeof(SInt16));
    NSLog(@"Recording!"); 
}
else
{
    NSLog(@"Not Recording!");
}
// once stop recording save the circular buffer to a temp circular buffer

    return noErr;
}

static OSStatus playbackCallback(void *inRefCon, 
                             AudioUnitRenderActionFlags *ioActionFlags, 
                             const AudioTimeStamp *inTimeStamp, 
                             UInt32 inBusNumber, 
                             UInt32 inNumberFrames, 
                             AudioBufferList *ioData) {    

RIO *rio = (RIO*)inRefCon;

int bytesToCopy = ioData->mBuffers[0].mDataByteSize;
SInt16 *targetBuffer = (SInt16*)ioData->mBuffers[0].mData;

// Pull audio from playthrough buffer
int32_t availableBytes;

if (rio->playing)
{
    SInt16 * tempbuffer = TPCircularBufferTail(&rio->buffer, &availableBytes);
    memcpy(targetBuffer, tempbuffer, MIN(bytesToCopy, availableBytes));
    TPCircularBufferConsume(&rio->buffer, MIN(bytesToCopy, availableBytes));
    NSLog(@"Playing!");
}
else
{
   NSLog(@"Playing silence!");

   for (int i = 0 ; i < ioData->mNumberBuffers; i++){
    //get the buffer to be filled
    AudioBuffer buffer = ioData->mBuffers[i];
    UInt32 *frameBuffer = buffer.mData;

    //loop through the buffer and fill the frames
       for (int j = 0; j < inNumberFrames; j++){
           frameBuffer[j] = 0;
       }
   }
}

   return noErr;
}
Was it helpful?

Solution

I will answer this question myself. Basically the rubbish sounds were due to the TPCircularBuffer not being large enough to hold the sounds. The playback callback was simply playing rubbish as the buffer did not contain anymore valid audio data.

Basically, making the TPCircularBuffer larger solved my problem. (duh!)

Pier.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top