Re: 2nd Post: Help: Sample accurate playhead positioning?
Re: 2nd Post: Help: Sample accurate playhead positioning?
- Subject: Re: 2nd Post: Help: Sample accurate playhead positioning?
- From: Doug Wyatt <email@hidden>
- Date: Tue, 4 Jan 2005 08:55:48 -0800
On Jan 3, 2005, at 13:48, Stephen Davis wrote:
On Jan 3, 2005, at 11:58 AM, David M. Cotter wrote:
are you returning noErr from the input proc and getting a paramErr
from AudioConverterFillComplexBuffer()?
correct. all i did was change the file offset of what bytes I return
from the callback passed into AudioConverterFillComplexBuffer()
I would guess that the new chunk of bytes you are handing to the audio
converter do not start at a packet boundary and it chokes.
2) how do I position it accurately, or, rather, how do I then
determine how many uncompressed samples *would have* played had I
not skipped forward?
timestamps don't get pushed thru
AudioConverterFillComplexBuffer(), so there's no way to tell where
in the file I should start reading. works fine if you just go
begin to end, but I need to skip around AND know exactly where I
land (either before or after the fact is fine)
These questions can't be answered except in the context of the
methods you're using for making a correlation between the audio
device's hardware times and your playback timeline...
The timestamps tell you what the hardware is doing.
You are in control of what packets/frames you read and convert from
the audio file, and where you place them on that timeline.
I'm trying to sync audio and video, where they are stored separately,
the audio is in an MP3 file, and the video is in another file. the
video is compressed in a manner that the absolute position from the
start of the file deterministically informs the time of that frame.
Not true with MP3. If I say "go to 20%", i can easily do that in the
video, but how can I possibly do that with audio when it's compressed
with VBR? must I decompress the whole song so I'm dealing with
uncompressed audio? it is exacerbated when the audio and video sizes
differ by a bit. when I play back straight thru, if audio finishes
first, I play silence 'till the video finishes. if the video
finishes first I hold the last frame until the audio finishes. if I
say "go to 50%", I need to take the MAX(audio_len, video_len), and
calculate 50% of that to get my "timestamp". that "timestamp" is
referring to samples that are uncompressed, but my MP3 file is
compressed. Can I just take that "timestamp" and linear interpolate
on the size of the compressed MP3 file to get a "compressed"
timestamp? I think you see where this is going. an MP3 file may
have ID3 tags at the end, increasing the size of the file but NOT
adding to the length of the music. if it uses variable bit rate
compression, then 50% of the compressed file is NOT necessarily
exactly 50% of the way thru the song. Do you get what I'm asking? I
need a way to seek to EXACTLY n% of the way thru the song, counting
in uncompressed samples. either that or a way to say get me close to
n%, but then have it tell me the exact percent you're at, or better
the exact sample you're at.
I am not familiar with how the AudioFile API treats MP3 files but you
have run into a difficult problem. Basically, mp3 decoders must
approximate the desired position in the file based on the bit rate and
the desired time and then seek byte-by-byte until they find the next
packet sync header. Then, they start decoding packets from there. As
you have noticed, mp3 packets are not always a uniform size (so your
"max packet size" calculation can't work) so it is not possible to
move to a particular offset in the file and assume that it will be the
beginning of a packet. I believe this is your problem. CBR files
have packets which *try* to be the same size but it's not really
possible. VBR files are even more problematic since their packet
sizes can vary wildly.
I think what you will need to do is calculate your desired position
estimate and then start manually reading bytes from the file until you
find the sync header. You can then use that byte offset to start
reading packets again to feed into the AudioConverter.
You may read that VBR files have a special header (Xing) which
contains an "offset table" which can be used to approximate
time-to-byte offset calculations which will make the above scheme
workable with VBR files. However, the VBR header is not a real
standard and many encoders create them incorrectly.
Having said all that, it seems like the AudioFile API can do what you
need. Are you using AudioFileReadPackets()? You could use your
previous LERP-based calculation to get the right packet number to hand
in as the "inStartingPacket" parameter to AudioFileReadPackets(). Of
course, in order to go to a specific starting packet the AudioFile
implementation may need to parse every frame up until that point so it
might be slow. I don't know how it is implemented.
Steven's approach is the only way to get smooth seeking without a
time-consuming full scan of the file, which is what the AudioFile API
does. (When does it do that? The current implementation may be doing it
on open; I'm working with a "future" one which is lazier and doesn't
scan the whole file until you do something like ask how many packets it
contains or seek into the middle... it builds up a table of packet
offsets...)
If you're willing to wait for that scan, and if the file's
mFramesPerPacket is nonzero, then to get to a given position in a file,
you can divide the desired sample frame by the mFramesPerPacket to get
a packet number, start reading at that packet, then throw away samples
preceding the one you want to start at.
Doug
_______________________________________________
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