为啥此音频单元 RemoteIO 初始化在 iPhone 上有效,但在模拟器中无效?
Posted
技术标签:
【中文标题】为啥此音频单元 RemoteIO 初始化在 iPhone 上有效,但在模拟器中无效?【英文标题】:Why does this Audio Unit RemoteIO initialisation work on iPhone but not in simulator?为什么此音频单元 RemoteIO 初始化在 iPhone 上有效,但在模拟器中无效? 【发布时间】:2010-09-28 02:59:08 【问题描述】:我正在使用音频单元服务设置输出渲染回调,以便将合成音频混合在一起。我拥有的代码似乎可以在我拥有的设备(iPod Touch、iPhone 3G 和 iPad)上完美运行,但无法在模拟器上运行。
在模拟器上,AudioUnitInitialise 函数失败并返回值 -10851(根据 Apple 文档,kAudioUnitErr_InvalidPropertyValue)。
这是我的初始化代码.. 有没有人比我看到我在这里做的任何错误都更有经验?
#define kOutputBus 0
#define kInputBus 1
...
static OSStatus playbackCallback(void *inRefCon,
AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList* ioData)
// Mix audio here - but it never gets here on the simulator
return noErr;
...
OSStatus status;
// Describe audio component
AudioComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
// Get component
AudioComponent inputComponent = AudioComponentFindNext(NULL, &desc);
// Get audio units
status = AudioComponentInstanceNew(inputComponent, &m_audio_unit);
if(status != noErr)
NSLog(@"Failed to get audio component instance: %d", status);
// Enable IO for playback
UInt32 flag = 1;
status = AudioUnitSetProperty(m_audio_unit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output,
kOutputBus,
&flag,
sizeof(flag));
if(status != noErr)
NSLog(@"Failed to enable audio i/o for playback: %d", status);
// Describe format
AudiostreamBasicDescription audioFormat;
audioFormat.mSampleRate = 44100.00;
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audioFormat.mFramesPerPacket = 1;
audioFormat.mChannelsPerFrame = 2;
audioFormat.mBitsPerChannel = 16;
audioFormat.mBytesPerPacket = 4;
audioFormat.mBytesPerFrame = 4;
// Apply format
status = AudioUnitSetProperty(m_audio_unit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
kOutputBus,
&audioFormat,
sizeof(audioFormat));
if(status != noErr)
NSLog(@"Failed to set format descriptor: %d", status);
// Set output callback
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = playbackCallback;
callbackStruct.inputProcRefCon = self;
status = AudioUnitSetProperty(m_audio_unit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Global,
kOutputBus,
&callbackStruct,
sizeof(callbackStruct));
if(status != noErr)
NSLog(@"Failed to set output callback: %d", status);
// Initialize (This is where it fails on the simulator)
status = AudioUnitInitialize(m_audio_unit);
if(status != noErr)
NSLog(@"Failed to initialise audio unit: %d", status);
我的 XCode 版本是 3.2.2(64 位) 我的模拟器版本是 3.2(虽然同样的问题出现在 3.1.3 Debug 或 Release)
谢谢,非常感谢!
【问题讨论】:
【参考方案1】:为设备编译和为模拟器编译是完全不同的。大多数常见的事情都有相同的预期结果。例如加载它们之间的视图切换播放声音等等。但是,当涉及到其他事情时,例如使用 OpenAL 加载 10 个缓冲区然后在它们之间切换播放声音,模拟器无法处理,但设备可以。
我看到它的方式是只要它在我关心的设备上运行。当应用程序在设备上运行良好时,尽量不要为了让应用程序在模拟器上运行而费尽心思。
希望对你有帮助
PK
【讨论】:
是的,我同意——这让我很恼火,因为我相信一个月前这段代码在模拟器上运行良好。我回来了,现在我得到了这个错误。哦,好吧,我现在要跳过它。谢谢! 至少将此帖子标记为已回答。作为其他用户的参考。感谢PK【参考方案2】:在调用 RemoteIO 初始化代码之前,您是否配置并启用了音频会话?
【讨论】:
是的。我想可能是这样,但音频会话是在播放类别下激活和配置的。 :?【参考方案3】:当您将流属性设置为输入总线时,您使用kOutputBus
作为输入范围。那可能不太好。此外,您可能不需要将渲染回调应用于全局范围,因为您只需要它用于输出。此外,我认为您对kOutputBus
和kInputBus
的定义是错误的......当我查看正在运行的iPhone Audio 代码时,它使用0 作为输入总线,1 作为输出总线。
我还可以想到一些关于 AudioStreamBasicDescription 的小事,尽管我认为这些不会有太大的不同:
-
将
kAudioFormatFlagsNativeEndian
属性添加到您的格式标志中
将mReserved
字段显式设置为0。
【讨论】:
感谢您的回复!根据苹果文档,这些值是正确的(我就是从那里得到它们的)。根据在线示例和苹果文档,输入范围定义显示正确。保留字段仅用于结构对齐,因此它不应该有所作为,但是为了安全起见,我已经继续并将所有结构归零。无论如何,事情仍然不会初始化。那好吧!当我不那么沮丧时,我会稍后再谈。以上是关于为啥此音频单元 RemoteIO 初始化在 iPhone 上有效,但在模拟器中无效?的主要内容,如果未能解决你的问题,请参考以下文章
是否可以列出当前在应用程序中的所有 RemoteIO 音频单元?
设置音频单元的音量 (kAudioUnitSubType_RemoteIO)
具有 kAudioUnitType_Output 和 kAudioUnitSubType_RemoteIO 的音频单元是不是默认使用低切滤波器?