3

I have a little issue regarding the use of the AudioQueue services. I have followed the guide that is available on Apple's webiste, but when I got to start and run the Audio Queue, I get the message telling me that "AudioConverterNew returned -50". Now, I know that the -50 error code means that there is a bad parameter. However, what I don't know is which parameter is the bad one (thank you so much Apple...) !


So, here's my code.

Here are the parameters of my class, named cPlayerCocoa

AudioQueueRef                   mQueue;
AudioQueueBufferRef             mBuffers[NUMBER_BUFFERS];    // NUMBER_BUFFERS = 3
uint32                          mBufferByteSize;
AudioStreamBasicDescription     mDataFormat;

Here's the first function :

static void
BuildBuffer( void* iAQData, AudioQueueRef iAQ, AudioQueueBufferRef iBuffer )
{
    cPlayerCocoa* player = (cPlayerCocoa*) iAQData;
    player->HandleOutputBuffer( iAQ, iBuffer );
}

It creates a cPlayerCocoa from the structure containing the AudioQueue and calls the HandleOutputBuffer function, which allocates the audio buffers :

void
cPlayerCocoa::HandleOutputBuffer( AudioQueueRef iAQ, AudioQueueBufferRef iBuffer )
{
    if( mContinue )
    {
        xassert( iBuffer->mAudioDataByteSize == 32768 );
        int startSample = mPlaySampleCurrent;
        int result = 0;

        int samplecount = 32768 / ( mSoundData->BytesPerSample() );    // BytesPerSample, in my case, returns 4
        tErrorCode  error = mSoundData->ReadData( (int16*)(iBuffer->mAudioData), samplecount, &result, startSample );

        AudioQueueEnqueueBuffer( mQueue, iBuffer, 0, 0 );    // I'm using CBR data (PCM), hence the 0 passed into the AudioQueueEnqueueBuffer.
        if( result != samplecount )
            mContinue = false;
        startSample += result;
    }      
    else
    {
        AudioQueueStop( mQueue, false );
    }
}

In this next function, the AudioQueue is created then started. I begin to initialise the parameters of the Data format. Then I create the AudioQueue, and I allocate the 3 buffers. When the buffers are allocated, I start the AudioQueue and then I run the loop.

void
cPlayerCocoa::ThreadEntry()
{
    int samplecount = 32768 / ( mSoundData->BytesPerSample() );
    mDataFormat.mSampleRate = mSoundData->SamplingRate();    // Returns 44100
    mDataFormat.mFormatID = kAudioFormatLinearPCM;
    mDataFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    mDataFormat.mBytesPerPacket = 32768;
    mDataFormat.mFramesPerPacket = samplecount;
    mDataFormat.mBytesPerFrame = mSoundData->BytesPerSample();    // BytesPerSample returns 4.
    mDataFormat.mChannelsPerFrame = 2;
    mDataFormat.mBitsPerChannel = uint32(mSoundData->BitsPerChannel());
    mDataFormat.mReserved = 0;

    AudioQueueNewOutput( &mDataFormat, BuildBuffer, this, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &mQueue );
    for( int i = 0; i < NUMBER_BUFFERS; ++i )
    {
        AudioQueueAllocateBuffer( mQueue, mBufferByteSize, &mBuffers[i] );
        HandleOutputBuffer( mQueue, mBuffers[i] );
    }

    AudioQueueStart( mQueue, NULL );    // I want the queue to start playing immediately, so I pass NULL
    do {
        CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0.25, false );
    } while ( !NeedStopASAP() );

    AudioQueueDispose( mQueue, true );
}

The call to AudioQueueStart returns -50 (bad parameter) and I can't figure what's wrong... I would really appreciate some help, thanks in advance :-)

  • You could start by checking the results of all the calls that return an `OSStatus`. – molbdnilo Sep 05 '13 at 08:46
  • 1
    The title of this question says AudioConverterNew fails, but the body asks about AudioQueueStart. Where is the message from AudioConverterNew generated? – sbooth Sep 05 '13 at 12:03
  • @molbdnilo As I have already explained, -50 returns "Bad parameter". – Thierry Cantet Sep 05 '13 at 12:43
  • @sbooth It is generated when AudioQueueStart is called. – Thierry Cantet Sep 05 '13 at 12:44
  • @ThierryCantet Yes, but you never ensure that everything you did up to that point succeeded. Apple's guide deliberately excludes error handling, but that's only to keep the examples short. – molbdnilo Sep 05 '13 at 12:53

1 Answers1

3

I think your ASBD is suspect. PCM formats have predictable values for mBytesPerPacket, mBytesPerFrame, and mFramesPerPacket. For normal 16-bit interleaved signed 44.1 stereo audio the ASBD would look like

AudioStreamBasicDescription asbd = {
  .mFormatID = kAudioFormatLinearPCM,
  .mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked,
  .mSampleRate = 44100,
  .mChannelsPerFrame = 2,
  .mBitsPerChannel = 16,
  .mBytesPerPacket = 4,
  .mFramesPerPacket = 1,
  .mBytesPerFrame = 4,
  .mReserved = 0
};

AudioConverterNew returns -50 when one of the ASBDs is unsupported. There is no PCM format where mBytesPerPacket should be 32768, which is why you're getting the error.

sbooth
  • 16,646
  • 2
  • 55
  • 81
  • I have similar issue, Can you please check it out? http://stackoverflow.com/questions/18959554/audioqueue-callback-get-empty-buffer-on-ios-7-only – Idan Sep 23 '13 at 15:10