I'm trying to stay in sync with looped playback, and having the devil of a time. I'm using AudioFile (with a dash of ExtAudioFile), and have no problem scheduling a section of a file for playback and using the pre-render callback to update the current playback time in samples as inTimeStamp->mSampleTime - startTime, where I set startTime on the first pre-render callback.
So now I want to start the "current time" over at zero each time the playback loops back to the beginning of the scheduled region. It should be simple, just increment startTime by loopSamples each time the playback time goes larger than loopSamples. I calculate loopSamples from the file duration when I schedule the file. If I have scheduled a portion of the file, it all works fine. However, if I try to use the total duration of the file, it often goes out of sync by something like 1000 samples each time around the loop (for an MP3 file). Here's the code I use to find the length:
propsize = sizeof( fileFrames ); err = ExtAudioFileGetProperty( myExtAudioFile, kExtAudioFileProperty_FileLengthFrames, &propsize, &fileFrames ); fileDuration = fileFrames / fileFormat.mSampleRate;
where I got fileFormat earlier, from the underlying AudioFile.
This error sounds suspiciously like a number of priming samples, so I think I'm asking for a longer loop than the file really has. And indeed, my length is longer than what Amadeus II reports. So I thought I would try reading kExtAudioFileProperty_FileLengthFrames and just using mNumberValidFrames. But no, that property is not defined for MP3s.
I tried using the kAudioFilePropertyEstimatedDuration property, but that gives wildly incorrect numbers, like a 1.3 second file is reported as 1.000 (I checked with afinfo and it also gives the incorrect answer). Apparently the estimate is very approximate.
So, is there some way I can find out the real duration of an MP3 file (among others)? Or alternatively a way to find out what the real loop length is after I schedule it? (I tried reading back the kAudioUnitProperty_ScheduledFileRegion property, but it reports the same mFramesToPlay as I asked for.)
Thanks, Kevin |