Joe Drew wrote:
The revised formula[1] seems to work pretty well. I don't know that it's perfectly accurate - for that, it seems that XMMS has lookup tables and other things in its Input plugin - but it is pretty good, and good enough for me. I will see whether it gives noticable jumps when I test mpg321's new seeking with frontends, possibly tomorrow (more bugs still to work out).
[1] frame(n) = frame(n-1) + (header->bitrate /8 /1000) * mad_timer_count(header->duration, MAD_UNITS_MILLISECONDS);
If you can keep a pointer to struct mad_stream (and I realize the high-level API doesn't make this easy) you can find the frame boundaries at stream->this_frame and stream->next_frame.
A perfectly accurate calculation would need to check for the padding slot, as follows:
unsigned int pad_slot, N;
pad_slot = (header->flags & MAD_FLAG_PADDING) ? 1 : 0;
if (header->layer == MAD_LAYER_I) N = ((12 * header->bitrate / header->samplerate) + pad_slot) * 4; else { unsigned int slots_per_frame;
slots_per_frame = (header->layer == MAD_LAYER_III && (header->flags & MAD_FLAG_LSF_EXT)) ? 72 : 144;
N = (slots_per_frame * header->bitrate / header->samplerate) + pad_slot; }
... then frame(n) = frame(n-1) + N