7

I'm getting error -50 (invalid parameters) from AudioUnitRender in the following context. I'm using this Pitch Detector sample app as my starting point, and it works fine. The only major difference in my project is that I'm also using the Remote I/O unit for audio output. The audio output works fine. Here is my input callback and my initialization code (with error checking removed for brevity). I know it's a lot but error -50 really gives me very little information as to where the problem might be.

Input callback:

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()

Initialization:

- (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;
}
Luke
  • 7,110
  • 6
  • 45
  • 74
  • 1
    Check to make sure your bus1 and inBusNumber are the same. Also the web site you mention does not have code for a pitch detector, only a mislabeled peak frequency detector, which will often fail at pitch estimation. – hotpaw2 Apr 24 '12 at 02:03
  • They are the same. And I'll definitely take the pitch detection with a grain of salt. – Luke Apr 24 '12 at 15:49
  • Were you able to resolve it? I have the problem that normally the call to AudioUnitRender succeed, but when my app comes back from background it fails, because the input callback requests more bytes. MY first thought was that it has something to do with my buffer sizes, but increasing them didn't help – tomk Jun 22 '12 at 14:31

3 Answers3

0

You are allocating the m_inBufferList as:

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

This should be:

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

Maybe this can solve your problem.

Kurt Pattyn
  • 2,758
  • 2
  • 30
  • 42
0

Error -50 in the develop doc means params error , make sure you have pass the right params in AudioUnitRender。 check the stream format and your unit

0

I agree with Kurt Pattyn that the allocation of m_inBufferList is incorrect, and might be the cause of -50 bad param error.

Except I think that for a single buffer it should be

(AudioBufferList *)malloc(sizeof(AudioBufferList)

My evidence is the following sizes and the code from Adamson & Avila below.

(lldb) sizeof(AudioBufferList) 24

(lldb) po sizeof(AudioBuffer) 16

(lldb) po offsetof(AudioBufferList, mBuffers[0]) 8

According to Chris Adamson & Kevin Avila in Learning Core Audio:

    // Allocate an AudioBufferList plus enough space for 
    // array of AudioBuffers
    UInt32 propsize = offsetof(AudioBufferList, mBuffers[0]) + 
        (sizeof(AudioBuffer) * player->streamFormat.mChannelsPerFrame);

    // malloc buffer lists
    player->inputBuffer = (AudioBufferList *)malloc(propsize); 
    player->inputBuffer->mNumberBuffers = player->streamFormat.mChannelsPerFrame;

    // Pre-malloc buffers for AudioBufferLists
    for(UInt32 i =0; i< player->inputBuffer->mNumberBuffers ; i++) {
        player->inputBuffer->mBuffers[i].mNumberChannels = 1;
        player->inputBuffer->mBuffers[i].mDataByteSize = bufferSizeBytes; 
        player->inputBuffer->mBuffers[i].mData = malloc(bufferSizeBytes);
    }

Last but not least, I just happened upon this code with the following comment : )

//credit to TheAmazingAudioEngine for an illustration of proper audiobufferlist allocation. 
// Google leads to some really really bad allocation code...
[other code]
sampleABL = malloc(sizeof(AudioBufferList) + (bufferCnt-1)*sizeof(AudioBuffer));

https://github.com/zakk4223/CocoaSplit/blob/master/CocoaSplit/CAMultiAudio/CAMultiAudioPCMPlayer.m#L203