使用Core Audio获取麦克风input和扬声器输出

所以我最近看了一下核心数据,现在还是个新手。 我很难理解我所使用的数据以及它如何影响整个数据stream。 所以对于一些背景,我有一个应用程序,使用webRTC在手机之间进行video/audiostream式传输。 但是,我想通过麦克风和通过扬声器输出的数据检查input到设备中的数据。 我看着AurioTouch演示和核心audio,目前我有这样的:

- (void)setupIOUnit { // Create a new instance of AURemoteIO AudioComponentDescription desc; desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_RemoteIO; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; AudioComponent comp = AudioComponentFindNext(NULL, &desc); AudioComponentInstanceNew(comp, &rioUnit); // Enable input and output on AURemoteIO // Input is enabled on the input scope of the input element // Output is enabled on the output scope of the output element UInt32 one = 1; AudioUnitSetProperty(rioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &one, sizeof(one)); AudioUnitSetProperty(rioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &one, sizeof(one)); // Set the MaximumFramesPerSlice property. This property is used to describe to an audio unit the maximum number // of samples it will be asked to produce on any single given call to AudioUnitRender UInt32 maxFramesPerSlice = 4096; AudioUnitSetProperty(rioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFramesPerSlice, sizeof(UInt32)); // Get the property value back from AURemoteIO. We are going to use this value to allocate buffers accordingly UInt32 propSize = sizeof(UInt32); AudioUnitGetProperty(rioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFramesPerSlice, &propSize); // Set the render callback on AURemoteIO AURenderCallbackStruct renderCallback; renderCallback.inputProc = performRender; renderCallback.inputProcRefCon = NULL; AudioUnitSetProperty(rioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallback, sizeof(renderCallback)); NSLog(@"render set now"); // Initialize the AURemoteIO instance AudioUnitInitialize(rioUnit); [self startIOUnit]; return; } - (OSStatus)startIOUnit { OSStatus err = AudioOutputUnitStart(rioUnit); if (err) NSLog(@"couldn't start AURemoteIO: %d", (int)err); return err; } 

呈现callback函数

 static OSStatus performRender (void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { OSStatus err = noErr; // the data gets rendered here err = AudioUnitRender(rioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData); if (ioData->mBuffers[0].mDataByteSize >= 12) { NSData *myAudioData = [NSData dataWithBytes: ioData->mBuffers[0].mData length:12]; NSLog(@" playback's first 12 bytes: %@", myAudioData); } for (UInt32 i=0; i<ioData->mNumberBuffers; ++i) { memset(ioData->mBuffers[i].mData, 0, ioData->mBuffers[i].mDataByteSize); } return err; } 

这打印出一些数据,我不知道这是麦克风input还是扬声器输出。 令我感到不安的是,即使在清除ioData的缓冲区之后,我仍然在其他手机上播放audio,并可以播放其他手机发送的audio。 这有点暗示我既不接触麦克风input也不接触扬声器输出。

我已经看到这一行的一些不同的参数:

 AudioUnitSetProperty(rioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallback, sizeof(renderCallback)); 

我想知道我是否有这些错误或什么。 另外,这一行是:

 err = AudioUnitRender(rioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData); 

受AudioUnitSetProperty的影响? 在这种情况下设置1做什么?

任何帮助他会很好。 理想情况下,我希望能够采样扬声器输出数据(可能是文件)以及麦克风input。

远程IOaudio单元是核心audio的一部分,它既有input又有输出。 它是一个完整的单元,可以录制/播放audio硬件(麦克风/扬声器)和/或从您的程序。 这有时会让人困惑。 想想这样。

**在远程IO单元上有input和输出。
**远程IO单元上也有软件和硬件。 硬件input是麦克风。 硬件输出是扬声器。 软件input是以编程方式创build的波形。 软件输出是一个已经创build的波形。

——-input————

总线0:从您的应用程序读取(您可以通过编程构buildaudio波形)。 在这里你写一个自动调用的callback函数。 它说“给我下一个audio样本”。 例如,你那里的代码可以给它一个你编程生成的三angular波的audio样本。
所以你生成一个波形来馈入程序。 您也可以从其他audio单元的输出中input此input。

总线1:从麦克风读取。 在这里,您可以从麦克风读取audio样本。 请注意,这些只是原始样本。 您可以select将它们保存到文件(例如录制应用程序),通过networking发送,甚至将它们连接到扬声器(见下文)。 你不会听到从麦克风的audio….它不会保存….除非你做了什么。

———- ———-输出

总线0:电话扬声器。 在这里,您可以编写audio数据,并在扬声器上播放。 所以你会得到另外一个回答,说“给我样品玩”,你用audio填充缓冲区,它播放它。 callback在当前缓冲区结束播放前的某个时间周期进行。

巴士1:写入您的应用程序。 在这里,您可以采用远程IO生成的audio,并在您的应用中使用它。 例如,您可以将输出连接到另一个或将数据写入文件。

所以要回答你的问题:“在这种情况下设置1是做什么的?

这是从AudioUnitRender苹果的规格

 OSStatus AudioUnitRender ( AudioUnit inUnit, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData ); 

1表示您正在读取作为audio帧输出的总线1。 所以你可以在这里做任何你想做的事,这不会影响演讲者的演奏。

如果您想检查麦克风数据,请在input端使用总线1。 如果要检查扬声器数据,请在输出上使用总线0。

请注意,你不能做callback中需要很长时间的事情。 build议不要做任何可能需要很长时间的事情(比如写入networking,写入文件,打印)。 在这种情况下,你可以使用GCD或类似的东西。

RemoteIOaudio单元不会更改任何其他audioAPI使用的audioinput或输出。 它仅将麦克风数据捕获到缓冲区,或者从缓冲区播放audio数据,这些缓冲区与其他audioAPI使用的缓冲区是分开的。