And here is how I send audio frames coming from the app:
void NCCommitSamples(Recorder* recorder, float* audioData, int sampleCount, long timestamp)
{
if (!recorder || !recorder->audio || !recorder->audioDesc || recorder->finishing)
return;
NSLog(@"Audio samples @ %ld for %d", timestamp, sampleCount);
long missing = (timestamp - recorder->minNextAudioTimestamp) * recorder->sampleRate * recorder->channelCount / RESOLUTION;
if (missing > 0)
{
void* zeroes = calloc(missing, sizeof(float));
NCCommitSamples(recorder, zeroes, (int)missing, recorder->minNextAudioTimestamp);
free(zeroes);
}
long duration = sampleCount / recorder->channelCount * RESOLUTION / recorder->sampleRate;
recorder->minNextAudioTimestamp += duration;
size_t dataSize = sampleCount * sizeof(float);
CMBlockBufferRef blockBuffer;
OSStatus status = CMBlockBufferCreateWithMemoryBlock(
kCFAllocatorDefault, nil, dataSize, kCFAllocatorDefault,
nil, 0, dataSize, kCMBlockBufferAssureMemoryNowFlag, &blockBuffer);
if (status != kCMBlockBufferNoErr)
{
NSLog(@"Error creating CMBlockBuffer: %d", (int)status);
return;
}
CMBlockBufferReplaceDataBytes(audioData, blockBuffer, 0, dataSize);
CMTime presentationTime = CMTimeMake(timestamp, RESOLUTION);
CMSampleBufferRef sampleBuffer;
status = CMAudioSampleBufferCreateReadyWithPacketDescriptions(
kCFAllocatorDefault, blockBuffer, recorder->audioDesc, sampleCount / recorder->channelCount, presentationTime, nil, &sampleBuffer);
if (status != kCMBlockBufferNoErr)
{
NSLog(@"Error creating CMSampleBuffer: %d", (int)status);
CFRelease(blockBuffer);
return;
}
if (!WaitReady(recorder->audio))
NSLog(@"[%ld] Dropped samples", timestamp);
else if (![recorder->audio appendSampleBuffer:sampleBuffer])
NSLog(@"[%ld] Failed sending audio sample buffer: %@", timestamp, recorder->writer.error);
CFRelease(sampleBuffer);
CFRelease(blockBuffer);
}