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?

Fraggle
  • 8,607
  • 7
  • 54
  • 86
  • Is there a reason for not initializing all of the mRecordFormat fields in both inFormatID branches? – Matti Jokipii May 22 '15 at 21:51
  • @MattiJokipii frankly I'm amazed that there is simply no default initializer for these different formats. I don't have a good reference for what is required for each audio format id.The settings above were taken from things like Apple's SpeakHere sample code and other places. Since I'm using the kAudioFormatLinearPCM the other format is not really important for this discussion. If you have a good reference with the correct settings for all different record formats, then please post it. – Fraggle May 23 '15 at 00:04
  • You should make a new question about stream format parameters. – Matti Jokipii May 23 '15 at 05:15

1 Answers1

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;
}
dave234
  • 4,793
  • 1
  • 14
  • 29
  • This doesn't answer the question. – Matti Jokipii May 23 '15 at 05:11
  • @Dave how do you know what parameters to use when calling that method? Or is it just a choice? That's what I don't quite get. The error I'm getting implies that the device is using one format, and I'm using a different format and those aren't compatible. How do we avoid that? – Fraggle May 23 '15 at 21:28
  • It depends. Sometimes you have a choice (In that case I always go float), and sometimes you have to match what's there like hardware and certain effect units. Here's a good [article](http://www.subfurther.com/blog/2009/04/28/an-iphone-core-audio-brain-dump/) explaining things, the author also has a book called [learning core audio](http://www.amazon.com/Learning-Core-Audio-Hands-On-Programming/dp/0321636848) that is worth a read. – dave234 May 23 '15 at 23:15
  • Were you able to get it working consistently or are you still having sporadic crashes? – dave234 May 24 '15 at 16:09