菜鸟教程小白 发表于 2022-12-13 09:58:11

ios - 停止 AudioUnit 录制后出错


                                            <p><p>我正在尝试使用以下代码从 iPhone 的麦克风中获取音频输入:</p>

<pre><code>@property (nonatomic) AudioUnit rioUnit;
@property (nonatomic) CAStreamBasicDescription outputCASBD;

(...)

// set our required format - LPCM non-interleaved 32 bit floating point
CAStreamBasicDescription outFormat = CAStreamBasicDescription(44100, // sample rate
                                                            kAudioFormatLinearPCM, // format id
                                                            4, // bytes per packet
                                                            1, // frames per packet
                                                            4, // bytes per frame
                                                            1, // channels per frame
                                                            32, // bits per channel
                                                            kAudioFormatFlagIsFloat | kAudioFormatFlagIsNonInterleaved);

try {
    // Open the output unit
    AudioComponentDescription desc;
    desc.componentType = kAudioUnitType_Output;
    desc.componentSubType = kAudioUnitSubType_RemoteIO;
    desc.componentManufacturer = kAudioUnitManufacturer_Apple;
    desc.componentFlags = 0;
    desc.componentFlagsMask = 0;

    AudioComponent comp = AudioComponentFindNext(NULL, &amp;desc);

    AudioComponentInstanceNew(comp, &amp;_rioUnit);

    UInt32 one = 1;
    XThrowIfError(AudioUnitSetProperty(_rioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &amp;one, sizeof(one)), &#34;couldn&#39;t enable input on the remote I/O unit&#34;);

    AURenderCallbackStruct callbackStruct;
    callbackStruct.inputProc = renderInput;
    callbackStruct.inputProcRefCon = (__bridge void*)self;
    XThrowIfError(AudioUnitSetProperty(_rioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &amp;callbackStruct, sizeof(callbackStruct)), &#34;couldn&#39;t set remote i/o render callback&#34;);

    XThrowIfError(AudioUnitSetProperty(_rioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &amp;outFormat, sizeof(outFormat)), &#34;couldn&#39;t set the remote I/O unit&#39;s output client format&#34;);
    XThrowIfError(AudioUnitSetProperty(_rioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &amp;outFormat, sizeof(outFormat)), &#34;couldn&#39;t set the remote I/O unit&#39;s input client format&#34;);

    XThrowIfError(AudioUnitInitialize(_rioUnit), &#34;couldn&#39;t initialize the remote I/O unit&#34;);
    XThrowIfError(AudioOutputUnitStart(_rioUnit), &#34;couldn&#39;t start the remote I/O unit&#34;);
}
catch (CAXException &amp;e) {
    char buf;
    fprintf(stderr, &#34;Error: %s (%s)\n&#34;, e.mOperation, e.FormatError(buf));
}
catch (...) {
    fprintf(stderr, &#34;An unknown error occurred\n&#34;);
}

// Allocate our own buffers (1 channel, 16 bits per sample, thus 16 bits per frame, thus 2 bytes per frame).
// Practice learns the buffers used contain 512 frames, if this changes it will be fixed in processAudio.
// will need float for accellerate fft (input is 16 bit signed integer) so make space...
_tempBuffer.mNumberChannels = outFormat.mChannelsPerFrame;
_tempBuffer.mDataByteSize = 512 * outFormat.mBytesPerFrame * 2;
_tempBuffer.mData = malloc( self.tempBuffer.mDataByteSize );
</code></pre>

<p>一切都很好,直到我想停止收听麦克风输入。</p>

<p>我正在这样做:</p>

<pre><code>    AudioOutputUnitStop(_rioUnit);
    AudioUnitUninitialize(_rioUnit);
    AudioComponentInstanceDispose(_rioUnit);
    _rioUnit = nil;
</code></pre>

<p>但我从为 <code>kAudioOutputUnitProperty_SetInputCallback</code> 定义的回调函数内部得到一个错误。</p>

<p>错误是:<code>AURemoteIO::IOThread (14): EXC_BAD_ACCESS (code=1, address=0x8000000c)</code> </p>

<p>在我看来,AudioUnit 的 InputCallback 仍在被调用,即使我正在停止它、对其实例进行统一化和处置。</p>

<p>为什么会发生这种情况?如何防止 InputCallback 在我停止、统一化和处置其实例后被调用?</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>首先,确保 _rioUnit 在 stop 和 start 中确实具有相同的值。</p>

<p>正在另一个异步线程中调用音频输入回调。因此,在取消初始化或处置音频单元或任何其他所需的数据结构之前,您可能需要等到该线程也停止(这通常发生在少于 2 个音频缓冲区持续时间的时间内,因此这可能是一个合理的等待时间) .</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 停止 AudioUnit 录制后出错,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/27219182/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/27219182/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 停止 AudioUnit 录制后出错