应用间录音时点击

Click During Inter-App Audio Recording

我一直在尝试在 iOS 9 上的应用程序间音频会话期间录制我的输入。扬声器输出听起来不错,但录制的文件有节奏的咔哒声。 波形如下所示...

我调整了所有我能想到的设置和参数,但似乎没有任何效果。

这是格式设置(流设置相同)...

    AudioStreamBasicDescription fileFormat;
fileFormat.mSampleRate          = kSessionSampleRate;
fileFormat.mFormatID            = kAudioFormatLinearPCM;
fileFormat.mFormatFlags         = kAudioFormatFlagsNativeFloatPacked;
fileFormat.mFramesPerPacket     = 1;
fileFormat.mChannelsPerFrame    = 1;
fileFormat.mBitsPerChannel      = 32;       //tone is correct but there is still pops
fileFormat.mBytesPerPacket      = sizeof(Float32);
fileFormat.mBytesPerFrame       = sizeof(Float32);

这是流设置...

        //connect instrument to output
AudioComponentDescription componentDescription = unit.componentDescription;
AudioComponent inputComponent = AudioComponentFindNext(NULL, &componentDescription);
OSStatus status = AudioComponentInstanceNew(inputComponent, &_instrumentUnit);
NSLog(@"%d",status);
AudioUnitElement instrumentOutputBus = 0;
AudioUnitElement ioUnitInputElement = 0;

    //connect instrument unit to remoteIO output's input bus
AudioUnitConnection connection;
connection.sourceAudioUnit = _instrumentUnit;
connection.sourceOutputNumber = instrumentOutputBus;
connection.destInputNumber = ioUnitInputElement;
status = AudioUnitSetProperty(_ioUnit,
                              kAudioUnitProperty_MakeConnection,
                              kAudioUnitScope_Output,
                              ioUnitInputElement,
                              &connection,
                              sizeof(connection));
NSLog(@"%d",status);
UInt32 maxFrames = 1024; //I tried setting this to 4096 but it did not help
status = AudioUnitSetProperty(_instrumentUnit,
                                kAudioUnitProperty_MaximumFramesPerSlice,
                                kAudioUnitScope_Output,
                                0,
                                &maxFrames,
                                sizeof(maxFrames));
NSLog(@"%d",status);



_connectedInstrument = YES;
_instrumentIconImageView.image = unit.icon;
NSLog(@"Remote Instrument connected");
status = AudioUnitInitialize(_ioUnit);
NSLog(@"%d",status);
status = AudioOutputUnitStart(_ioUnit);
NSLog(@"%d",status);
status = AudioUnitInitialize(_instrumentUnit);
NSLog(@"%d",status);
[self setupFile];

这是我的回调...

static OSStatus recordingCallback(void                              *inRefCon,
                                 AudioUnitRenderActionFlags         *ioActionFlags,
                                 const AudioTimeStamp               *inTimeStamp,
                                 UInt32                             inBusNumber,
                                 UInt32                             inNumberFrames,
                                 AudioBufferList                    *ioData)
{
    ViewController* This = This = (__bridge ViewController *)inRefCon;
    if (inBusNumber == 0 && !(*ioActionFlags & kAudioUnitRenderAction_PostRenderError))
    {
            ExtAudioFileWriteAsync(This->fileRef, inNumberFrames, ioData);
    }

    return noErr;
}

Full view controller code here

感谢您的帮助。

您正在写入文件预和 post 渲染。在您的渲染回调中,将您的 if 语句更改为仅在 post 渲染上写入。

if (inBusNumber == 0 && *ioActionFlags == kAudioUnitRenderAction_PostRender){
    ExtAudioFileWriteAsync(This->fileRef, inNumberFrames, ioData);
} 

ExtAudioFileWriteAsync 会进行一些内部复制和缓冲,因此只要在第一次写入之前准备好它,就可以在渲染回调中使用它。

您很可能需要检查两者:

  • post-渲染操作标志
  • post 渲染错误

你的回调的关键部分可能看起来像这样:

if (*ioActionFlags & kAudioUnitRenderAction_PostRender){
    static int TEMP_kAudioUnitRenderAction_PostRenderError = (1 << 8);
    if (!(*ioActionFlags & TEMP_kAudioUnitRenderAction_PostRenderError))
    { 
         ExtAudioFileWriteAsync(This->fileRef, inNumberFrames, ioData);
         //whichever additional code needed
         // { … }
    }