ExtAudioFileSeek bug workaround
ExtAudioFileSeek bug workaround
- Subject: ExtAudioFileSeek bug workaround
- From: Dominic Feira <email@hidden>
- Date: Tue, 14 Sep 2010 14:18:13 -0400
I traced a bug to ExtAudioFileSeek recently and found that many other people have as well. Basically the problem was, if I seek into an apple lossless or AAC file and then read audio to the end of the file I was not getting enough samples. ExtAudioFile thought it was at the end of the file even though my frames counts didn't add up. I was unable to find a workaround for this issue.
I did come up with a workaround today. The usual caveats apply, test it before you use it, etc. I have only tested it with Apple Lossless and AAC audio in both m4a and caf files. Client sample rate must match the file sample rate. Compensating for different sample rates is an exercise I'll leave to others. This should also work for lpcm audio though you could special case for that to avoid the extra method calls. I have only tested this on 10.6.4 so far.
A few observations I've made about ExtAudioFile
1. ExtAudioFileSeek(f) does not seek to f. It seeks to the beginning of the compressed packet that contains f.
2. ExtAudioFileTell() lies.
This is the workaround that I came up with.
1. When seeking, translate the seek frame to the file packet + offset. Seek to the beginning of the file packet. Store the offset for later.
2. When reading throw out the first offset frames.
3. Compensate Tell by adding the offset.
Here is some pseudo code.
MyFileClass::Seek(frames)
{
// translate the frames to the audio packet that contains it + the offset
AudioFrameTranslation translation = AudioFileGetProperty(kAudioFilePropertyFrameToPacket, frames);
// store the offset for later...this is the amount that ExtAudioFileSeek is off by
mSeekOffsetCorrection = translation.mFramesOffsetInPacket;
// translate the packet to frame so we know we're seeking to the beginning of a compressed packet
translation = AudioFileGetProperty(kAudiofilePropertyPacketToFrame, translation.mPacket);
correctedFrame = translation.mFrame;
// seek to the beginning of the compressed packet
ExtAudioFileSeek(correctedFrame);
}
MyFileClass::Tell()
{
// ExtAudioFileTell is lying, we need to compensate for its error
// mFrameOffsetCorrection is from QA1678 http://developer.apple.com/library/mac/#qa/qa2009/qa1678.html
// don't forget about it
return ExtAudioFileTell() + mSeekOffsetCorrection + mFrameOffsetCorrection;
}
MyFileClass::Read(frames)
{
// throw out mSeekOffsetCorrection frames
ExtAudioFileRead(mSeekOffsetCorrection);
// ExtAudioFile should be in agreement with us now, so get rid of the correction
mSeekOffsetCorrection = 0;
// now we proceed with a normal read
ExtAudioFileRead(frames);
}
I hope that somebody else finds this useful. This code should still work even if the bug in ExtAudioFile is fixed.
Dominic Feira / Code Monkey / Ambrosia Software, Inc. -- http://www.AmbrosiaSW.com
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden