On Oct 2, 2011, at 11:05 PM, Donald Ness <email@hidden> wrote:
I've set up a simple audio recorder, but I'm having trouble recording to a file after I reopen the file. As long as I have the audio queue running, I can stop and start the queue, and audio is appended perfectly to the file -- it plays back just fine.
The problem arises when I dispose the queue and close the file, then reopen it and try to resume recording at the last packet:
AudioFileOpenURL((CFURLRef)audioFileURL, kAudioFileReadWritePermission, kAudioFileCAFType, &audioFileID);
UInt32 propertySize = sizeof(currentPacket);
AudioFileGetProperty(audioFileID, kAudioFilePropertyAudioDataPacketCount, &propertySize, ¤tPacket);
First, I got an error stating the file is not optimized. That seemed reasonable, so I added this line:
AudioFileOptimize(audioFileID);
Now, I'm error free and can successfully write packets! My callback looks like this:
static void PSAudioRecorder_Callback(void *audioData, AudioQueueRef audioQueue, AudioQueueBufferRef audioBuffer, const AudioTimeStamp *time, UInt32 numPackets, const AudioStreamPacketDescription *packetDescription) {
PSAudioRecorder *recorder = (PSAudioRecorder *)audioData;
if (numPackets > 0) {
AudioFileWritePackets(recorder.audioFileID, FALSE, audioBuffer->mAudioDataByteSize, packetDescription, recorder.currentPacket, &numPackets, audioBuffer->mAudioData);
recorder.currentPacket += numPackets;
}
if ([recorder isRunning]) {
AudioQueueEnqueueBuffer(audioQueue, audioBuffer, 0, NULL);
}
}
Just a note, as has been discussed elsewhere on this list, the official recommendation is to not call Objective-C methods from within your render callback.
From your naming convention, it looks like this render callback is internal to the PSAudioRecorder class, so it wouldn't be a violation of encapsulation principles to access your ivars directly, though you may need to take care that your main thread isn't reading or writing those ivars while you're trying to update them. As it is, you currently lack that care around your property accesses, so accessing your ivars directly won't be less thread safe. (Unless you used `atomic` when declaring your properties, which means you *really* shouldn't call them from a render callback.)
--Kyle Sluder |