5

我一直在为 iOS 开发一个频率检测应用程序,但在使用来自麦克风的音频样本填充用户定义的 AudioBufferList 时遇到问题。

当我在 InputCallback 方法中调用 AudioUnitRender 时,返回码为 -50。我相信这意味着我的参数之一无效。我猜它是 AudioBufferList,但我无法弄清楚它有什么问题。我想我已经对其进行了设置,使其与我在 ASBD 中指定的数据格式相匹配。

以下是我认为可能不正确的远程 I/O 设置和函数调用:

ASBD:

size_t bytesPerSample = sizeof(AudioUnitSampleType);
AudioStreamBasicDescription localStreamFormat = {0};
localStreamFormat.mFormatID = kAudioFormatLinearPCM;
localStreamFormat.mFormatFlags = kAudioFormatFlagsAudioUnitCanonical;
localStreamFormat.mBytesPerPacket = bytesPerSample;
localStreamFormat.mBytesPerFrame = bytesPerSample;
localStreamFormat.mFramesPerPacket = 1;
localStreamFormat.mBitsPerChannel = 8 * bytesPerSample;
localStreamFormat.mChannelsPerFrame = 2;
localStreamFormat.mSampleRate = sampleRate;

InputCallback 声明:

err = AudioUnitSetProperty(ioUnit, kAudioOutputUnitProperty_SetInputCallback, 
                           kAudioUnitScope_Input, 
                           kOutputBus, &callbackStruct, sizeof(callbackStruct));

AudioBufferList 声明:

// Allocate AudioBuffers
bufferList = (AudioBufferList *)malloc(sizeof(AudioBuffer));
bufferList->mNumberBuffers = 1;
bufferList->mBuffers[0].mNumberChannels = 2;

bufferList->mBuffers[0].mDataByteSize = 1024;
bufferList->mBuffers[0].mData = calloc(256, sizeof(uint32_t));

输入回调函数:

AudioUnit rioUnit = THIS->ioUnit;
OSStatus renderErr;
UInt32 bus1 = 1;
renderErr = AudioUnitRender(rioUnit, ioActionFlags, inTimeStamp, bus1, inNumberFrames, THIS->bufferList);

需要注意的几点:

  • 采样率 = 22050 赫兹
  • 由于远程 I/O 数据的规范格式是 8.24 位定点,我假设每个样本是 32 位(或 4 个字节)。由于 unsigned int 是 4 个字节,我使用它来分配我的音频缓冲区。
  • 如果我将音频数据流实现为 PassThru 而不是仅输入,我可以获得相同的代码来正确呈现音频。
  • 我已经看过Michael Tyson关于远程 I/O的博文。没有看到任何与我正在做的不同的事情。

再次感谢,你们都很棒!

德米特里

4

3 回答 3

6

如果每帧有 2 个通道,则不能具有bytesPerSample帧的大小。由于术语有点混乱:

  • 样本是波形中给定位置的单个值
  • 通道是指与特定音频流相关的数据,即立体声的左/右通道、单声道的单通道等。
  • 包含波形中给定位置的所有通道的样本
  • 一个数据包包含一个或多个帧

所以基本上,你需要使用bytesPerSample * mChannelsPerFrameformBytesPerFrame和使用mBytesPerFrame * mFramesPerPacketfor mBytesPerPacket

我还注意到您使用 32 位作为样本大小。我不确定您是否真的想这样做——通常,您想使用 16 位样本录制音频。16 位和 32 位音频之间的声音差异对于大多数听众来说几乎是不可能听到的(平均 CD 以 44.1kHz、16 位 PCM 进行母带处理),它可以为您节省 50% 的 I/O 和存储成本。

于 2010-12-07T15:42:51.183 回答
0

线bufferList = (AudioBufferList *)malloc(sizeof(AudioBuffer));也是错的。由于 AudioBuffer 比 AudioBufferList 小,它分配的内存不足。

于 2012-06-22T10:12:35.900 回答
0

一个区别是 Tyson 的 RemoteIO 博客文章每个线性 PCM 样本使用 2 个字节。所以这可能是格式不兼容的错误。

于 2010-12-07T08:20:21.780 回答