使用单声道输入和立体声输出设置音频单元 iOS
Posted
技术标签:
【中文标题】使用单声道输入和立体声输出设置音频单元 iOS【英文标题】:Setting up audio unit iOS with mono input and stereo output 【发布时间】:2014-04-14 21:07:54 【问题描述】:我正在尝试设置一个能够进行单声道输入和立体声输出的音频单元。打算通过左声道输出播放正弦波音调,并通过右声道输出周期性地播放不同的符号波。
我收到错误消息,
'NSInternalInconsistencyException', reason: ' Error initialing unit: -50;
当我尝试在这里初始化我的音频单元时,
// Initialize audio unit
OSErr err = AudioUnitInitialize(self.ioUnit);
NSAssert1(err == noErr, @"Error initializing unit: %hd", err);
我认为这与我设置音频单元的方式有关,
// Audio component description
AudioComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
// Get component
AudioComponent inputComponent = AudioComponentFindNext(NULL, &desc);
// Get Audio units
AudioComponentInstanceNew(inputComponent, &ioUnit);
// Enable input, which disabled by default. Output enable by default
UInt32 enableInput = 1;
AudioUnitSetProperty(ioUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input,
kInputBus,
&enableInput,
sizeof(enableInput));
AudiostreamBasicDescription monoStreamFormat;
monoStreamFormat.mSampleRate = 44100.00;
monoStreamFormat.mFormatID = kAudioFormatLinearPCM;
monoStreamFormat.mFormatFlags = kAudioFormatFlagsAudioUnitCanonical;
monoStreamFormat.mBytesPerPacket = 2;
monoStreamFormat.mBytesPerFrame = 2;
monoStreamFormat.mFramesPerPacket = 1;
monoStreamFormat.mChannelsPerFrame = 1;
monoStreamFormat.mBitsPerChannel = 16;
// Apply format to input of ioUnit
AudioUnitSetProperty(ioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
kInputBus,
&monoStreamFormat,
sizeof(monoStreamFormat));
AudioStreamBasicDescription stereoStreamFormat;
stereoStreamFormat.mSampleRate = 44100.00;
stereoStreamFormat.mFormatID = kAudioFormatLinearPCM;
stereoStreamFormat.mFormatFlags = kAudioFormatFlagsAudioUnitCanonical;
stereoStreamFormat.mBytesPerPacket = 4;
stereoStreamFormat.mBytesPerFrame = 4;
stereoStreamFormat.mFramesPerPacket = 1;
stereoStreamFormat.mChannelsPerFrame = 2;
stereoStreamFormat.mBitsPerChannel = 32;
// Apply format to output of ioUnit
AudioUnitSetProperty(ioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
kOutputBus,
&stereoStreamFormat,
sizeof(stereoStreamFormat));
// Set input callback
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = inputCallback;
callbackStruct.inputProcRefCon = (__bridge void *)(self);
AudioUnitSetProperty(ioUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Global,
kInputBus,
&callbackStruct,
sizeof(callbackStruct));
// Set output callback
callbackStruct.inputProc = outputCallback;
callbackStruct.inputProcRefCon = (__bridge void *)(self);
AudioUnitSetProperty(ioUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Global,
kOutputBus,
&callbackStruct,
sizeof(callbackStruct));
但我在返回的错误代码 -50 上找不到任何内容,所以我不确定它不喜欢什么。我在最后期限,所以非常感谢任何帮助。
【问题讨论】:
-50 isparamErr
: 用户参数列表错误
感谢您的回复,但我看不出我的代码中可能出现的位置,您@sbooth 吗? $ macerror -50
同意你的看法。
你有想过这个吗?
【参考方案1】:
kAudioFormatFlagsAudioUnitCanonical 是 32 位 8.24 定点格式。这意味着 mBytesPerFrame 对于单声道应该是 4,对于立体声应该是 8,对于立体声和单声道 mBitsPerChannel 应该是 32。将其设置为 16 位可能会产生此错误。
也就是说,我怀疑你想要 8.24。您可能希望 kAudioFormatFlagsCanonical 获得标准的 16 位音频。或者,如果您想要 32 位,请使用 32 位浮点数 (kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved)。在处理过程中更容易处理数学。
此外,您正在设置虚拟输入和输出的格式,而不是客户端输入和输出,我认为这不是您想要的。这里的 API 比较混乱,但是要设置客户端输入格式,请使用 kAudioUnitScope_Input、kOutputBus。这里的逻辑是您正在设置内部 Core Audio input 转换器单元的 output 格式,从代码的角度来看,它是输入音频.令人困惑,我知道。有关详细信息,请参阅音频单元文档。同样,要设置客户端输出格式,请使用 kAudioUnitScope_Output、kInputBus。
【讨论】:
感谢您的回复。我将对 IO 格式进行这些更改,看看它是否能解决我的错误(你说得对,命名对于 IO 格式来说是违反直觉的)。 根据您的回复,我假设在设置 IO 回调时,我还需要将kOutputBus
与 kInputBus
切换。
对不起,我弄错了。对于 8.24 的立体声,mBytesPerFrame 应为 8。
我不确定。我认同。我只设置了一个回调,我认为这就是你真正需要的。你得到输入样本,处理它们,然后输出它们,所有这些都在同一个回调中。所以它会是 kAudioUnitProperty_SetRenderCallback、kAudioUnitScope_Input、kOutputBus。
请注意,为了启用输入,您确实使用输入范围和输入总线。【参考方案2】:
每个通道 32 位太多位,无法将 2 个通道放入 4 个字节。试试 16。
【讨论】:
尝试了您的建议,但在初始化调用期间我仍然得到相同的error: -50
(AudioUnitInitialize(self.ioUnit)
)。
@hotpaw2- 还有其他想法吗?以上是关于使用单声道输入和立体声输出设置音频单元 iOS的主要内容,如果未能解决你的问题,请参考以下文章
如何渲染来自远程 I/O 音频单元的系统输入并以立体声播放这些样本
使用音频工具 sox,我如何确定立体声录音是不是实际上是单声道?