Hi everybody,
I’m working on low-latency record/playback OSX app. I want to be able to start playback immediately after I stop recording. I gather that writing to hdd is high latency and decided to use fixed length buffers that will store recorded data in the memory and never write to hdd while recording. I’m not sure if the above reasoning is correct.
I'm modifying the Play Through example from “Learning Core Audio” book. I’ve created a static buffer while setting up the input unit. It will receive samples that are also passed to CARingBuffer
Static buffer allocation:
UInt32 propSizeStaticBuffer = offsetof(AudioBufferList, mBuffers[0]) + (sizeof(AudioBuffer) * player->streamFormat.mChannelsPerFrame);
player->staticBuffer = (AudioBufferList *)malloc(propSizeStaticBuffer);
player->staticBuffer->mNumberBuffers = player->streamFormat.mChannelsPerFrame;
UInt32 staticBufferSizeBytes = 512000 * sizeof(Float32);
for(UInt32 i = 0; i < player->staticBuffer->mNumberBuffers; i++)
{
player->staticBuffer->mBuffers[i].mNumberChannels = 1;
player->staticBuffer->mBuffers[i].mDataByteSize = staticBufferSizeBytes;
player->staticBuffer->mBuffers[i].mData = malloc(staticBufferSizeBytes);
}
In the InputRenderCallback I copy the samples to the buffer:
if(player->staticBufferNumberOfFrames*4 <= 512000 * 4 - 512 )
{
UInt32 offset = player->staticBufferNumberOfFrames * sizeof(Float32);
printf("Offset %u\n", player->staticBufferNumberOfFrames * sizeof(Float32));
Float32 *bufferL = (Float32*)player->staticBuffer->mBuffers[0].mData;
bufferL = bufferL + offset;
Float32 *bufferR = (Float32*)player->staticBuffer->mBuffers[1].mData;
bufferR = bufferR + offset;
printf("Number of frames to copy: %u\n", inNumberFrames);
if(offset < 512000)
{
printf("**Copying into the static buffer.\n");
memcpy(bufferL, &player->inputBuffer->mBuffers[0], inNumberFrames*sizeof(Float32));
memcpy(bufferR, &player->inputBuffer->mBuffers[1], inNumberFrames*sizeof(Float32));
player->staticBufferNumberOfFrames += inNumberFrames;
}
else
{
printf("***********Reached offset 512000: %u************\n", offset);
player->staticBufferNumberOfFrames = 0;
playFromMemory = YES;
}
printf("Number of frames: %u\n", player->staticBufferNumberOfFrames);
}
Once the buffer is full, in the GraphRender function I switch the sample source from CARingBuffer to the static buffer:
if(playFromMemory != YES)
{
outputProcErr = player->ringBuffer->Fetch(ioData,
inNumberFrames,
inTimeStamp->mSampleTime + player->inToOutSampleTimeOffset);
}
else //play out the memorised sequence
{
stopInputRendering = YES;
printf("Static Buffer Number of Frames For Output: %u\n", player->staticBufferNumberOfFrames);
UInt32 offset = player->staticBufferNumberOfFrames * sizeof(Float32);
printf("Output Offset %u\n", player->staticBufferNumberOfFrames * sizeof(Float32));
Float32 *bufferL = (Float32*)player->staticBuffer->mBuffers[0].mData;
bufferL = bufferL + offset;
Float32 *bufferR = (Float32*)player->staticBuffer->mBuffers[1].mData;
bufferR = bufferR + offset;
printf("Number of frames on output: %u\n", inNumberFrames);
if(offset < 512000)
{
printf("**Copying out of the static buffer.***\n");
memcpy(&ioData->mBuffers[0], bufferL, inNumberFrames*sizeof(Float32));
memcpy(&ioData->mBuffers[1], bufferR, inNumberFrames*sizeof(Float32));
}
player->staticBufferNumberOfFrames += inNumberFrames;
}
However, after the buffers are switched, I can only hear throughput from the input for the duration of the staticBuffer playback, once it runs out input cuts out. I don’t understand why the samples that were being stored in the buffer are not played back. I also don’t understand why I can hear throughput after I’ve stopped filling CARingBuffer after I switch buffers in the GraphRenderProc.
Thanks for your time.
Marcin