ioscore-audioexc-bad-accessaudioqueue

Why does the argument ioNumBytes of AudioFileReadPacketData cause a crash?


I have got something really strange (at least for me but I am a noob).

UInt32 numBytesReadFromFile;
OSStatus err = AudioFileReadPacketData(
                                    audioFile, // The audio file whose audio packets you want to read.
                                    NO, // is cache set?
                                    &numBytesReadFromFile, // On output, the number of bytes of audio data that were read from the audio file.
                                    (AudioStreamPacketDescription *)_packetDescriptions, // array of packet descriptions of data that was read from the audio file (for CBR null)
                                    currentPacket, // the next packet to be read into buffer
                                    &numPackets, // number of actually read buffers
                                    _audioQueueBuffer->mAudioData
                                    );

AudioFileReadPacketData reads data from an audio file and places it in a buffer.

So my question is about the argument numBytesReadFromFile. Apple writes

numBytesReadFromFile: On output, the number of bytes of audio data that were read from the audio file.

So far so good. Apple declares numBytesReadFromFile like in the example code above but for me this line of code crashes! I get an EXC BAD ACCESS.

UInt32 numBytesReadFromFile;

I need to declare numBytesReadFromFile like this and everything works fine:

UInt32 numBytesReadFromFile = 2048; // 2048 = size of my buffer

However this crashes too

UInt32 numBytesReadFromFile = 12
UInt32 numBytesReadFromFile = sizeof(UInt32)

but this does not

UInt32 numBytesReadFromFile = 1021; // a random number

I am not a very experienced C programmer but as far as I know I reserve some memory by declaring numBytesReadFromFile and the method audiofilereadpacketdata writes its data to the address of the variable. Please correct me if I am wrong.

So why does it crash? I think I haven't fixed the real problem.

My assumption is that I have some kind of a multithreading issue. When i prepare the queue I call AudioFileReadPacketData on the main thread and declaring

UInt32 numBytesReadFromFile;

works fine. I start playing the audio and a callback is invoked which calls AudioFilereadPacketData on an internal background thread of audio queue and the error described above occurs. If my assumption is right, can someone explain me the issue a bit more in detail as I am not experienced in multithreading.

Thanks.


Solution

  • The parameter ioNumBytes to AudioFileReadPacketData is an in/out parameter. The documentation says:

    On input, the size of the outBuffer parameter, in bytes. On output, the number of bytes actually read.

    You will see a difference in the input and output values if the byte size for the number of packets you request in the ioNumPackets parameter is smaller than the buffer size you pass in the outBuffer parameter. In this case, the output value for this parameter is smaller than its input value.

    The value when the function is called determines how much data will be written to your buffer. If the code you posted is correct, numBytesReadFromFile is never initialized to the size of _audioQueueBuffer->mAudioData and the program crashes because it attempts to write an undetermined amount of data to _audioQueueBuffer->mAudioData. Try setting the parameter before the function call:

    UInt32 numBytesReadFromFile = _audioQueueBuffer->mAudioDataByteSize;
    OSStatus err = AudioFileReadPacketData(
                                        audioFile, // The audio file whose audio packets you want to read.
                                        NO, // is cache set?
                                        &numBytesReadFromFile, // On output, the number of bytes of audio data that were read from the audio file.
                                        (AudioStreamPacketDescription *)_packetDescriptions, // array of packet descriptions of data that was read from the audio file (for CBR null)
                                        currentPacket, // the next packet to be read into buffer
                                        &numPackets, // number of actually read buffers
                                        _audioQueueBuffer->mAudioData
                                        );