4

I am working on understanding Core Audio, or rather: Extended Audio File Services

Here, I want to use ExtAudioFileRead() to read some audio data from a file.
This works fine as long as I use one single huge buffer to store my audio data (that is, one AudioBuffer). As soon as I use more than one AudioBuffer, ExtAudioFileRead() returns the error code -50 ("error in parameter list"). As far as I can figure out, this means that one of the arguments of ExtAudioFileRead() is wrong. Probably the audioBufferList.

I can not use one huge buffer because then, dataByteSize would overflow its UInt32-integer range with huge files.

Here is the code to create the audioBufferList:

AudioBufferList *audioBufferList;
audioBufferList = malloc(sizeof(AudioBufferList) + (numBuffers-1)*sizeof(AudioBuffer));
audioBufferList->mNumberBuffers = numBuffers;
for (int bufferIdx = 0; bufferIdx<numBuffers; bufferIdx++ ) {
    audioBufferList->mBuffers[bufferIdx].mNumberChannels = numChannels;
    audioBufferList->mBuffers[bufferIdx].mDataByteSize = dataByteSize;
    audioBufferList->mBuffers[bufferIdx].mData = malloc(dataByteSize);
}

And here is the working, but overflowing code:

UInt32 dataByteSize = fileLengthInFrames * bytesPerFrame; // this will overflow
AudioBufferList *audioBufferList = malloc(sizeof(audioBufferList));
audioBufferList->mNumberBuffers = 1;
audioBufferList->mBuffers[0].mNumberChannels = numChannels;
audioBufferList->mBuffers[0].mDataByteSize = dataByteSize;
audioBufferList->mBuffers[0].mData = malloc(dataByteSize);

And finally, the call of ExtAudioFileRead() (should work with both versions):

UInt32 numFrames = fileLengthInFrames;
error = ExtAudioFileRead(extAudioFileRef,
                         &numFrames,
                         audioBufferList);

Do you know what I am doing wrong here?

bastibe
  • 16,551
  • 28
  • 95
  • 126

4 Answers4

5

I think you're misunderstanding the purpose of the mNumberBuffers field. It's typically 1 for mono and interleaved stereo data. The only reason you would set it to something else is for multi-track data where each channel is in a separate data buffer.

If you want to read a part of a file, you would set dataByteSize of the buffer to a reasonable size, and when you read the file, tell the API only to give you that many bytes, and loop over it.

lucius
  • 8,665
  • 3
  • 34
  • 41
  • 1
    So, is there are usage scenario in which `mNumberBuffers` is something other than 1? – bastibe Mar 27 '10 at 15:01
  • I am not sure if this argument is correct since in the aurioTouch2 sample, mNumberBuffers is set to be 2, I am wondering if someone know the reason. – user454083 Aug 31 '13 at 21:40
  • And by the way if I want to simultaneously either encode or decode buffer, how I could do this work in separate thread – user454083 Aug 31 '13 at 21:44
1

I also had the same problem with mNumberBuffers > 1,,... My work around involved creating my own internal buffer:

something like:

char buffer1[byteSize]; char buffer2[byteSize]; ......

you could also use pointers to make things easier,..like:

buffer[index][byteSize];

then you would have to iterate through them manually and fill them up on the main thread to avoid glitches in audio.

ExtAudioFileRead will only fill buffer[0] in the AudioBufferList, you could then have that pointing to different manually allocated buffers as the audio plays.

hope this helps.

atnmachine
  • 37
  • 2
  • That was not exactly what I wanted to do, but it certainly helps if you want to fill several different buffers with different data. (My initial thought was that I could fill several buffers with consecutive chunks of data from the same file). – bastibe Apr 06 '10 at 14:36
0

mNumberBuffers == 2 when you're dealing with non-interleaved stereo. It is the number of audio channels when not interleaved.

-3

Cocoa simply seems to not accept mNumberBuffers > 1. Which is a shame as it makes the whole structure useless. (I hope this is right...)

bastibe
  • 16,551
  • 28
  • 95
  • 126
  • That's not true. I believe mNumberBuffers>1 is used for multi-channel audio. Just that the rest of the AudioBufferList structure has to make sense. – notthetup Sep 17 '12 at 08:11