Realtime audio processing without output

邮差的信 提交于 2019-12-03 14:21:20

If you want only recording, no playback, simply comment out the line that sets renderCallback:

AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = renderCallback; // Render function
callbackStruct.inputProcRefCon = NULL;
if(AudioUnitSetProperty(*audioUnit, kAudioUnitProperty_SetRenderCallback,
   kAudioUnitScope_Input, 0, &callbackStruct,
   sizeof(AURenderCallbackStruct)) != noErr) {
  return 1;
}

Update after seeing code:

As I suspected, you're missing input callback. Add these lines:

// at top:
#define kInputBus 1

AURenderCallbackStruct callbackStruct;
/**/
callbackStruct.inputProc = &ALAudioUnit::recordingCallback;
callbackStruct.inputProcRefCon = this;
status = AudioUnitSetProperty(audioUnit,
                              kAudioOutputUnitProperty_SetInputCallback,
                              kAudioUnitScope_Global,
                              kInputBus,
                              &callbackStruct,
                              sizeof(callbackStruct));

Now in your recordingCallback:

OSStatus ALAudioUnit::recordingCallback(void *inRefCon,
                                        AudioUnitRenderActionFlags *ioActionFlags,
                                        const AudioTimeStamp *inTimeStamp,
                                        UInt32 inBusNumber,
                                        UInt32 inNumberFrames,
                                        AudioBufferList *ioData)
{
    // TODO: Use inRefCon to access our interface object to do stuff
    // Then, use inNumberFrames to figure out how much data is available, and make
    // that much space available in buffers in an AudioBufferList.

    // Then:
    // Obtain recorded samples

    OSStatus status;

    ALAudioUnit *pThis = reinterpret_cast<ALAudioUnit*>(inRefCon);
    if (!pThis)
        return noErr;

    //assert (pThis->m_nMaxSliceFrames >= inNumberFrames);

    pThis->recorderBufferList->GetBufferList().mBuffers[0].mDataByteSize = inNumberFrames * pThis->m_recorderSBD.mBytesPerFrame;

    status = AudioUnitRender(pThis->audioUnit,
                             ioActionFlags,
                             inTimeStamp,
                             inBusNumber,
                             inNumberFrames,
                             &pThis->recorderBufferList->GetBufferList());
    THROW_EXCEPTION_IF_ERROR(status, "error rendering audio unit");

    // If we're not playing, I don't care about the data, simply discard it
    if (!pThis->playbackState || pThis->isSeeking) return noErr;

    // Now, we have the samples we just read sitting in buffers in bufferList
    pThis->DoStuffWithTheRecordedAudio(inNumberFrames, pThis->recorderBufferList, inTimeStamp);

    return noErr;
}

Btw, I'm allocating my own buffer instead of using the one provided by AudioUnit. You might want to change those parts if you want to use AudioUnit allocated buffer.

Update:

How to allocate own buffer:

recorderBufferList = new AUBufferList();
recorderBufferList->Allocate(m_recorderSBD, m_nMaxSliceFrames);
recorderBufferList->PrepareBuffer(m_recorderSBD, m_nMaxSliceFrames);

Also, if you're doing this, tell AudioUnit to not allocate buffers:

// Disable buffer allocation for the recorder (optional - do this if we want to pass in our own)
flag = 0;
status = AudioUnitSetProperty(audioUnit,
                              kAudioUnitProperty_ShouldAllocateBuffer,
                              kAudioUnitScope_Input,
                              kInputBus,
                              &flag,
                              sizeof(flag));

You'll need to include CoreAudio utility classes

Thanks for @Mar0ux 's answer. Whoever got here looking for complete sample code doing this can take a look here:

https://code.google.com/p/ios-coreaudio-example/

Kyle Griffith

I am doing a similar app working with the same code and I found that you can end playback by changing the enumeration kAudioSessionCategory_PlayAndRecord to RecordAudio

int initAudioStreams(AudioUnit *audioUnit) {
UInt32 audioCategory = kAudioSessionCategory_RecordAudio;
if(AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,
                           sizeof(UInt32), &audioCategory) != noErr) {
    return 1;
}

This stopped the feedback between mic and speaker on my hardware.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!