Format error setting up AudioQueue for recording, but only happens once in a while

0

So oddly, this error happens only once in a while, when we are setting up the audio queue (even though I'm doing everything the same way). Device iPhone 5, iOS8.3:

mediaserverd[37] <Error>: 15:14:24.594 ERROR:     [0x2883000] >aq> 323: AudioConverterNew from AudioQueueNew returned 'fmt?'
    io:     0 ch,  44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved
    client:    0 ch,  44100 Hz, 'lpcm' (0x0000000C) 16-bit signed integer

Here's the code that triggers it.

        SetupAudioFormat(kAudioFormatLinearPCM);

        // create the queue
        XThrowIfError(AudioQueueNewInput(
                                      &mRecordFormat,
                                      MyInputBufferHandler,
                                      this /* userData */,
                                      NULL /* run loop */, NULL /* run loop mode */,
                                      0 /* flags */, &mQueue), "AudioQueueNewInput failed");

where mRecordFormat is setup like:

void AQRecorder::SetupAudioFormat(UInt32 inFormatID)
{
    memset(&mRecordFormat, 0, sizeof(mRecordFormat));

    UInt32 size = sizeof(mRecordFormat.mSampleRate);
    mRecordFormat.mSampleRate=[AVAudioSession sharedInstance].sampleRate;

    size = sizeof(mRecordFormat.mChannelsPerFrame);
    mRecordFormat.mChannelsPerFrame=(UInt32)[AVAudioSession sharedInstance].inputNumberOfChannels;
    mRecordFormat.mFormatID = inFormatID;

    mRecordFormat.mBytesPerFrame =mRecordFormat.mChannelsPerFrame * sizeof (SInt16);
    if (inFormatID == kAudioFormatLinearPCM)
    {
        // if we want pcm, default to signed 16-bit little-endian
        mRecordFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
        mRecordFormat.mBitsPerChannel = 16;
        mRecordFormat.mBytesPerPacket = mRecordFormat.mBytesPerFrame = (mRecordFormat.mBitsPerChannel / 8) * mRecordFormat.mChannelsPerFrame;
        mRecordFormat.mFramesPerPacket = 1;
    } else if(inFormatID==kAudioFileAIFFType) {
        mRecordFormat.mFramesPerPacket  = 1;
        mRecordFormat.mFormatFlags =
        kLinearPCMFormatFlagIsBigEndian
        | kLinearPCMFormatFlagIsSignedInteger
        | kLinearPCMFormatFlagIsPacked;
    }
}

My interpretation of the error is that the phone is recording as 32-bit little-endian float, deinterleaved and I'm trying to setup a queue with a format that is 16-bit signed integer. But why don't I get the error everytime? How to fix it?

ios
iphone
audio-recording
audioqueueservices
asked on Stack Overflow May 22, 2015 by Fraggle

1 Answer

0

AudioStreamBasicDescriptions are really annoying. Here is what I use. I have typedefed AudioStreamBasicDescription to ASBD

ASBD asbdWithInfo(Boolean isFloat,int numberOfChannels,Boolean interleavedIfStereo){
    ASBD asbd = {0};
    int sampleSize          = isFloat ? sizeof(float) : sizeof(SInt16);
    asbd.mChannelsPerFrame  = (numberOfChannels == 1) ? 1 : 2;
    asbd.mBitsPerChannel    = 8 * sampleSize;
    asbd.mFramesPerPacket   = 1;
    asbd.mSampleRate        = 44100.0;
    asbd.mBytesPerFrame     = interleavedIfStereo ? sampleSize * asbd.mChannelsPerFrame : sampleSize;
    asbd.mBytesPerPacket    = asbd.mBytesPerFrame;
    asbd.mReserved          = 0;
    asbd.mFormatID          = kAudioFormatLinearPCM;
    if (isFloat) {
        asbd.mFormatFlags = kAudioFormatFlagIsFloat;
        if (interleavedIfStereo) {
            if (numberOfChannels == 1) {
                asbd.mFormatFlags = asbd.mFormatFlags | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved;
            }
        }
        else{
            asbd.mFormatFlags = asbd.mFormatFlags | kAudioFormatFlagIsNonInterleaved | kAudioFormatFlagIsPacked ;
        }
    }
    else{
        asbd.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
        if (!interleavedIfStereo) {
            if (numberOfChannels > 1) {
                asbd.mFormatFlags = asbd.mFormatFlags | kAudioFormatFlagIsNonInterleaved;
            }

        }
    }
    return asbd;
}
answered on Stack Overflow May 23, 2015 by dave234

User contributions licensed under CC BY-SA 3.0