首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >核心音频-远程IO混淆

核心音频-远程IO混淆
EN

Stack Overflow用户
提问于 2016-02-13 21:55:43
回答 1查看 663关注 0票数 0

我很难理解remoteIO音频回调在iOS中的行为。我正在设置一个带有两个回调的remoteIO单元,一个是输入回调,另一个是“呈现”回调。我遵循的remoteIO设置非常类似于这个美味的像素教程中推荐的设置。这是相当长的设置方法:

代码语言:javascript
复制
- (void)setup {


   AudioUnit ioUnit;

   AudioComponentDescription audioCompDesc;
   audioCompDesc.componentType = kAudioUnitType_Output;
   audioCompDesc.componentSubType = kAudioUnitSubType_RemoteIO;
   audioCompDesc.componentManufacturer = kAudioUnitManufacturer_Apple;
   audioCompDesc.componentFlags = 0;
   audioCompDesc.componentFlagsMask = 0;

   AudioComponent rioComponent = AudioComponentFindNext(NULL, &audioCompDesc);
   CheckError(AudioComponentInstanceNew(rioComponent, &ioUnit), "Couldn't get RIO unit instance");

   // i/o
   UInt32 oneFlag = 1;
   CheckError(AudioUnitSetProperty(ioUnit,
                                   kAudioOutputUnitProperty_EnableIO,
                                   kAudioUnitScope_Output,
                                   kOutputBus,
                                   &oneFlag,
                                   sizeof(oneFlag)), "Couldn't enable RIO output");

   CheckError(AudioUnitSetProperty(ioUnit,
                                   kAudioOutputUnitProperty_EnableIO,
                                   kAudioUnitScope_Input,
                                   kInputBus,
                                   &oneFlag,
                                   sizeof(oneFlag)), "Couldn't enable RIO input");

   AudioStreamBasicDescription myASBD;
   memset (&myASBD, 0, sizeof(myASBD));
   myASBD.mSampleRate = 44100;
   myASBD.mFormatID = kAudioFormatLinearPCM;
   myASBD.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
   myASBD.mFramesPerPacket = 1;
   myASBD.mChannelsPerFrame = 1;
   myASBD.mBitsPerChannel = 16;
   myASBD.mBytesPerPacket = 2 * myASBD.mChannelsPerFrame;
   myASBD.mBytesPerFrame = 2 *  myASBD.mChannelsPerFrame;


   // set stream format for both busses
   CheckError(AudioUnitSetProperty(ioUnit,
                                   kAudioUnitProperty_StreamFormat,
                                   kAudioUnitScope_Input,
                                   kOutputBus,
                                   &myASBD,
                                   sizeof(myASBD)), "Couldn't set ASBD for RIO on input scope / bus 0");

   CheckError(AudioUnitSetProperty(ioUnit,
                                   kAudioUnitProperty_StreamFormat,
                                   kAudioUnitScope_Output,
                                   kInputBus,
                                   &myASBD,
                                   sizeof(myASBD)), "Couldn't set ASBD for RIO on output scope / bus 1");

   // set arbitrarily high for now
   UInt32 bufferSizeBytes = 10000 * sizeof(int);



   int offset = offsetof(AudioBufferList, mBuffers[0]);

   int bufferListSizeInBytes = offset + (sizeof(AudioBuffer) * myASBD.mChannelsPerFrame);

   // why need to cast to audioBufferList * ?
   self.inputBuffer = (AudioBufferList *)malloc(bufferListSizeInBytes);
   self.inputBuffer->mNumberBuffers = myASBD.mChannelsPerFrame;

   for (UInt32 i = 0; i < myASBD.mChannelsPerFrame; i++) {
      self.inputBuffer->mBuffers[i].mNumberChannels = 1;
      self.inputBuffer->mBuffers[i].mDataByteSize = bufferSizeBytes;
      self.inputBuffer->mBuffers[i].mData = malloc(bufferSizeBytes);
   }


   self.remoteIOUnit = ioUnit;


   /////////////////////////////////////////////// callback setup
   AURenderCallbackStruct callbackStruct;
   callbackStruct.inputProc = inputCallback;
   callbackStruct.inputProcRefCon = (__bridge void * _Nullable)self;
   CheckError(AudioUnitSetProperty(ioUnit,
                                   kAudioOutputUnitProperty_SetInputCallback,
                                   kAudioUnitScope_Global,
                                   kInputBus,
                                   &callbackStruct,
                                   sizeof(callbackStruct)), "Couldn't set input callback");


   AURenderCallbackStruct callbackStruct2;
   callbackStruct2.inputProc = playbackCallback;
   callbackStruct2.inputProcRefCon = (__bridge void * _Nullable)self;
   CheckError(AudioUnitSetProperty(ioUnit,
                                   kAudioUnitProperty_SetRenderCallback,
                                   kAudioUnitScope_Global,
                                   kOutputBus,
                                   &callbackStruct,
                                   sizeof(callbackStruct)), "Couldn't set input callback");


   CheckError(AudioUnitInitialize(ioUnit), "Couldn't initialize input unit");
   CheckError(AudioOutputUnitStart(ioUnit), "AudioOutputUnitStart failed");


}

我在回调中经历了奇怪的行为。首先,playbackCallback函数根本没有被调用,尽管它的属性设置的方式与教程中的相同(本教程是由编写Loopy应用程序的人编写的)。

其次,输入回调有一个ioData (audioBufferList)参数,它应该是null (根据文档),但是在null和每个秒回调都有一个非零值之间切换。这对任何人来说都有意义吗?

另外,在输入回调中调用audiounitRender (在API逻辑和生命周期等方面我仍然不理解它的语义)导致一个-50的错误,这是非常通用的“坏参数”。这很可能是由于audiobufferlist的无效“拓扑”,即交织/脱交织,通道的数字等等.然而,我尝试了各种拓扑,没有一个没有导致错误。这也不能解释奇怪的ioData行为。以下是供参考的函数:

代码语言:javascript
复制
OSStatus inputCallback(void *inRefCon,
                       AudioUnitRenderActionFlags *ioActionFlags,
                       const AudioTimeStamp *inTimeStamp,
                       UInt32 inBusNumber,
                       UInt32 inNumberFrames,
                       AudioBufferList * ioData)
{

   MicController *myRefCon = (__bridge MicController *)inRefCon;


   CheckError(AudioUnitRender(myRefCon.remoteIOUnit,
                              ioActionFlags,
                              inTimeStamp,
                              inBusNumber,
                              inNumberFrames,
                              myRefCon.inputBuffer), "audio unit render");



   return noErr;
}

我认为,我的经验可能是由于格式化上的一些简单错误,或者可能在错误的范围上使用了错误的总线,或者其他一些琐碎的错误(并且很容易在核心音频上下文错误中产生)。但是,因为从根本上说,我对语义和生命周期流没有直觉(方案?,我甚至不知道该使用什么词),所以我无法充分地调试它。我非常感谢一个更有经验的核心音频程序员的一些帮助,这可能会为这种情况提供一些启示。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-02-14 17:07:09

您的kAudioUnitProperty_SetRenderCallback属性设置程序使用的是callbackStruct而不是callbackStruct2。因此,您的RemoteIO音频单元将调用inputCallback()两次而不是playbackCallback()。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35385780

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档