2012-04-23 35 views
6

我在以下上下文中收到來自AudioUnitRender的錯誤-50(無效參數)。我使用這個Pitch Detector示例應用程序作爲我的出發點,它工作正常。我的項目唯一的主要區別是我還使用遠程I/O單元進行音頻輸出。音頻輸出正常工作。這裏是我的輸入回調和我的初始化代碼(爲了簡潔,刪除了錯誤檢查)。我知道這很多,但是錯誤-50真的給我提供了關於問題出在哪裏的信息。AudioUnitRender發生錯誤-50

輸入回調:

OSStatus inputCallback(void* inRefCon, 
          AudioUnitRenderActionFlags *ioActionFlags, 
          const AudioTimeStamp  *inTimeStamp, 
          UInt32      inBusNumber, 
          UInt32      inNumberFrames, 
          AudioBufferList    *ioData) { 

    WBAudio* audioObject= (WBAudio*)inRefCon; 

    AudioUnit rioUnit = audioObject->m_audioUnit; 
    OSStatus renderErr; 
    UInt32 bus1 = 1; 

    renderErr = AudioUnitRender(rioUnit, ioActionFlags, 
           inTimeStamp, bus1, inNumberFrames, audioObject->m_inBufferList); 
    if (renderErr < 0) { 
     return renderErr; // breaks here 
    } 

    return noErr; 
} // end inputCallback() 

初始化:

- (id) init { 

    self= [super init]; 
    if(!self) return nil; 

    OSStatus result; 

    //! Initialize a buffer list for rendering input 
    size_t bytesPerSample; 
    bytesPerSample = sizeof(SInt16); 
    m_inBufferList = (AudioBufferList *)malloc(sizeof(AudioBuffer)); 
    m_inBufferList->mNumberBuffers = 1; 
    m_inBufferList->mBuffers[0].mNumberChannels = 1; 
    m_inBufferList->mBuffers[0].mDataByteSize = 512*bytesPerSample; 
    m_inBufferList->mBuffers[0].mData = calloc(512, bytesPerSample); 

    //! Initialize an audio session to get buffer size 
    result = AudioSessionInitialize(NULL, NULL, NULL, NULL); 

    UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord; 
    result = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory); 

    // Set preferred buffer size 
    Float32 preferredBufferSize = static_cast<float>(m_pBoard->m_uBufferSize)/m_pBoard->m_fSampleRate; 
    result = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(preferredBufferSize), &preferredBufferSize); 

    // Get actual buffer size 
    Float32 audioBufferSize; 
    UInt32 size = sizeof (audioBufferSize); 
    result = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, &size, &audioBufferSize); 

    result = AudioSessionSetActive(true); 

    //! Create our Remote I/O component description 
    AudioComponentDescription desc; 
    desc.componentType= kAudioUnitType_Output; 
    desc.componentSubType= kAudioUnitSubType_RemoteIO; 
    desc.componentFlags= 0; 
    desc.componentFlagsMask= 0; 
    desc.componentManufacturer= kAudioUnitManufacturer_Apple; 

    //! Find the corresponding component 
    AudioComponent outputComponent = AudioComponentFindNext(NULL, &desc); 

    //! Create the component instance 
    result = AudioComponentInstanceNew(outputComponent, &m_audioUnit); 

    //! Enable audio output 
    UInt32 flag = 1; 
    result = AudioUnitSetProperty(m_audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &flag, sizeof(flag)); 

    //! Enable audio input 
    result= AudioUnitSetProperty(m_audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag)); 

    //! Create our audio stream description 
    m_audioFormat.mSampleRate= m_pBoard->m_fSampleRate; 
    m_audioFormat.mFormatID= kAudioFormatLinearPCM; 
    m_audioFormat.mFormatFlags= kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; 
    m_audioFormat.mFramesPerPacket= 1; 
    m_audioFormat.mChannelsPerFrame= 1; 
    m_audioFormat.mBitsPerChannel= 16; 
    m_audioFormat.mBytesPerPacket= 2; 
    m_audioFormat.mBytesPerFrame= 2; 

    //! Set the stream format 
    result = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &m_audioFormat, sizeof(m_audioFormat)); 

    result = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_StreamFormat, 
           kAudioUnitScope_Output, 
           kInputBus, &m_audioFormat, sizeof(m_audioFormat)); 

    //! Set the render callback 
    AURenderCallbackStruct renderCallbackStruct= {0}; 
    renderCallbackStruct.inputProc= renderCallback; 
    renderCallbackStruct.inputProcRefCon= m_pBoard; 
    result = AudioUnitSetProperty(m_audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, kOutputBus, &renderCallbackStruct, sizeof(renderCallbackStruct)); 

    //! Set the input callback 
    AURenderCallbackStruct inputCallbackStruct = {0}; 
    inputCallbackStruct.inputProc= inputCallback; 
    inputCallbackStruct.inputProcRefCon= self; 
    result= AudioUnitSetProperty(m_audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Input, kOutputBus, &inputCallbackStruct, sizeof(inputCallbackStruct)); 

    //! Initialize the unit 
    result = AudioUnitInitialize(m_audioUnit); 

    return self; 
} 
+1

檢查,以確保您的BUS1和inBusNumber是相同的。您所提到的網站也沒有音調檢測器的代碼,只有錯誤標記的峯值頻率檢測器,這在音調估計時往往會失敗。 – hotpaw2 2012-04-24 02:03:43

+0

他們是一樣的。我肯定會用一粒鹽來進行球場檢測。 – Luke 2012-04-24 15:49:33

+0

你能解決嗎?我遇到的問題通常是對AudioUnitRender的調用成功,但是當我的應用程序從後臺返回時,它會失敗,因爲輸入回調會請求更多字節。我的第一個想法是,它與我的緩衝區大小有關,但增加它們並沒有幫助 – tomk 2012-06-22 14:31:05

回答

0

您分配m_inBufferList爲:

m_inBufferList = (AudioBufferList *)malloc(sizeof(AudioBuffer)); 

這應該是:

m_inBufferList = (AudioBufferList *)malloc(sizeof(AudioBufferList) + sizeof(AudioBuffer) * numberOfBuffers); //numberOfBuffers in your case is 1 

也許這可以解決你的問題。

+0

您在某處丟失了括號。 – 2012-04-30 11:29:41

+0

好,但錯誤仍然存​​在。 – Luke 2012-05-03 15:12:37

+2

由於他只需要1個緩衝區,所以可以跳過第二個sizeof,因爲AudioBufferList的聲明已經分配了一個mbuffer – tomk 2012-06-22 14:28:25

1

錯誤-50在開發文檔意味着PARAMS錯誤, 請確保您有傳入AudioUnitRender正確PARAMS。 檢查流格式和設備上