Jim*_*ong 5 audio core-audio ios
我正在尝试AudioBufferList将从音频单元获得的一个转换为一个CMSampleBuffer我可以传递给一个AVAssetWriter以保存来自麦克风的音频。这种转换有效,因为我为执行转换而进行的调用不会失败,但记录最终确实会失败,而且我在日志中看到一些似乎引起关注的输出。
我正在使用的代码如下所示:
- (void)handleAudioSamples:(AudioBufferList*)samples numSamples:(UInt32)numSamples hostTime:(UInt64)hostTime {
// Create a CMSampleBufferRef from the list of samples, which we'll own
AudioStreamBasicDescription monoStreamFormat;
memset(&monoStreamFormat, 0, sizeof(monoStreamFormat));
monoStreamFormat.mSampleRate = 48000;
monoStreamFormat.mFormatID = kAudioFormatLinearPCM;
monoStreamFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved;
monoStreamFormat.mBytesPerPacket = 2;
monoStreamFormat.mFramesPerPacket = 1;
monoStreamFormat.mBytesPerFrame = 2;
monoStreamFormat.mChannelsPerFrame = 1;
monoStreamFormat.mBitsPerChannel = 16;
CMFormatDescriptionRef format = NULL;
OSStatus status = CMAudioFormatDescriptionCreate(kCFAllocatorDefault, &monoStreamFormat, 0, NULL, 0, NULL, NULL, &format);
if (status != noErr) {
// really shouldn't happen
return;
}
CMSampleTimingInfo timing = { CMTimeMake(1, 48000), kCMTimeZero, kCMTimeInvalid };
CMSampleBufferRef sampleBuffer = NULL;
status = CMSampleBufferCreate(kCFAllocatorDefault, NULL, false, NULL, NULL, format, numSamples, 1, &timing, 0, NULL, &sampleBuffer);
if (status != noErr) {
// couldn't create the sample buffer
PTKLogError(@"Failed to create sample buffer");
CFRelease(format);
return;
}
// add the samples to the buffer
status = CMSampleBufferSetDataBufferFromAudioBufferList(sampleBuffer,
kCFAllocatorDefault,
kCFAllocatorDefault,
0,
samples);
if (status != noErr) {
PTKLogError(@"Failed to add samples to sample buffer");
CFRelease(sampleBuffer);
CFRelease(format);
return;
}
NSLog(@"Original sample buf size: %ld for %d samples from %d buffers, first buffer has size %d", CMSampleBufferGetTotalSampleSize(sampleBuffer), numSamples, samples->mNumberBuffers, samples->mBuffers[0].mDataByteSize);
NSLog(@"Original sample buf has %ld samples", CMSampleBufferGetNumSamples(sampleBuffer));
Run Code Online (Sandbox Code Playgroud)
正如我所提到的,代码本身似乎没有失败,但AVAssetWriter不喜欢它,并且CMSampleBuffer我正在创建的代码的大小似乎为 0,基于正在记录以下日志条目的事实:
2015-07-09 19:34:00.710 xxxx[1481:271334] Original sample buf size: 0 for 1024 samples from 1 buffers, first buffer has size 2048
2015-07-09 19:34:00.710 xxxx[1481:271334] Original sample buf has 1024 samples
Run Code Online (Sandbox Code Playgroud)
奇怪的是,样本缓冲区报告它有 1024 个样本,但大小为 0。原始 AudioBufferList 有 2048 个字节的数据,这是我对 1024 个 2 字节样本的期望。
我在初始化和填充CMSampleBuffer.
事实证明,样本量返回为 0 的事实是一个转移注意力的事实。一旦我清理了一些东西——值得注意的是,我正确设置了时间戳,如下所示:
uint64_t timeNS = (uint64_t)(hostTime * _hostTimeToNSFactor);
CMTime presentationTime = CMTimeMake(timeNS, 1000000000);
CMSampleTimingInfo timing = { CMTimeMake(1, 48000), presentationTime, kCMTimeInvalid };
Run Code Online (Sandbox Code Playgroud)
录音开始工作。
因此,如果其他人因报告的 0 样本缓冲区大小而感到困惑,请注意这是可以的,至少在您将数据输入到AVAssetWriter.