As part of mpg123 emulation, I've got to be able to seek in files and also report where in the file we're currently playing (in verbose mode, at least). Now, seeking isn't difficult: I just get the frame to which the user wants to seek, count the frames mad's passing to the header function, and return MAD_FLOW_IGNORE for every frame up to the one the user wants.
However, the second one is a bit more difficult. I need to know (a) how many frames there are in any given file, and (b) how long the file is, in time. Now there is a solution similar to the above one: do an initial pass, returning MAD_FLOW_IGNORE for all the frames, and counting (a) the frames and (b) the total length of the file. Now that I'm looking in madplay, I notice that's somewhat along the lines of what's done in scan(). and calc() in madtime.c. Is this the only option? I assume it's not horribly inefficient, anyways, as it seems to be in use in madplay.
Thanks again,
Joe Drew wrote:
As part of mpg123 emulation, I've got to be able to seek in files and also report where in the file we're currently playing (in verbose mode, at least). Now, seeking isn't difficult: I just get the frame to which the user wants to seek, count the frames mad's passing to the header function, and return MAD_FLOW_IGNORE for every frame up to the one the user wants.
However, the second one is a bit more difficult. I need to know (a) how many frames there are in any given file, and (b) how long the file is, in time. Now there is a solution similar to the above one: do an initial pass, returning MAD_FLOW_IGNORE for all the frames, and counting (a) the frames and (b) the total length of the file. Now that I'm looking in madplay, I notice that's somewhat along the lines of what's done in scan(). and calc() in madtime.c. Is this the only option? I assume it's not horribly inefficient, anyways, as it seems to be in use in madplay.
This is only used by `madtime' (which isn't built by default), and it's not terribly efficient but it is accurate for all types of files.
There is a faster method you can use in the case of constant bitrate files: divide the file size in bits by the bitrate in bps to get the playing time of the file in seconds:
time = (size * 8) / (bitrate * 1000)
This assumes the entire file consists of MPEG audio frames, ignoring ID3 tags in particular, but it may still produce an acceptable estimate.
From the playing time, and knowing the sample rate and audio layer, you can
compute the number of frames. First, the number of samples per frame:
samples = 32 * MAD_NSBSAMPLES(&header)
Then, the number of frames:
frames = samplerate * time / samples
Note that you need to decode at least one frame header in order to determine the bit rate, sample rate, and layer. Also note that this doesn't work for VBR files, because in those cases the bit rate changes throughout the file.
For VBR, if there is a so-called Xing tag in the first frame, you can compute the playing time and number of frames from that. Otherwise, the only guaranteed method to determine either is to scan the entire file.
You can find some Xing tag-parsing code in the MAD plug-in for Winamp.
Hope this helps.
On Sun, 2001-07-01 at 02:14, Rob Leslie wrote:
For VBR, if there is a so-called Xing tag in the first frame, you can compute the playing time and number of frames from that. Otherwise, the only guaranteed method to determine either is to scan the entire file.
I'm not clear on how this is possible. The Xing tag tells us the number of frames and the length (in bytes) of the file, but we don't have a bitrate, so it's (apparently) not possible to calculate time. Or am I missing something? (I wasn't able to find any documentation on the Xing header anywhere, so I might be.)
Joe Drew wrote:
I'm not clear on how this is possible. The Xing tag tells us the number of frames and the length (in bytes) of the file, but we don't have a bitrate, so it's (apparently) not possible to calculate time. Or am I missing something? (I wasn't able to find any documentation on the Xing header anywhere, so I might be.)
Since each frame contains the same number of output samples, it's possible to calculate playing time from the sampling frequency and number of frames.
This is where the new mad_timer_multiply() routine becomes handy. Just multiply the duration of one frame (frame.header.duration) by the total number of frames indicated by the Xing header.
Cheers, -rob