ref: 77360f7193a2ba2e8473bf83609d9462e8cdb617
parent: 0e6972cf5804d39f2db6389fb33c217361c93c54
author: Mans Rullgard <mans@mansr.com>
date: Mon Dec 16 12:20:40 EST 2019
mp3: fix duration calculation Avoid rounding errors as much as possible. It is still possible for the CBR extrapolation to be slightly off.
--- a/src/mp3-util.h
+++ b/src/mp3-util.h
@@ -249,22 +249,16 @@
return 0;
}
-static void mad_timer_mult(mad_timer_t * t, double d)
+static size_t mp3_duration(sox_format_t * ft)
{
- t->seconds = (signed long)(d *= (t->seconds + t->fraction * (1. / MAD_TIMER_RESOLUTION)));
- t->fraction = (unsigned long)((d - t->seconds) * MAD_TIMER_RESOLUTION + .5);
-}
-
-static size_t mp3_duration_ms(sox_format_t * ft)
-{
priv_t * p = (priv_t *) ft->priv;
struct mad_stream mad_stream;
struct mad_header mad_header;
struct mad_frame mad_frame;
- mad_timer_t time = mad_timer_zero;
size_t initial_bitrate = 0; /* Initialised to prevent warning */
size_t tagsize = 0, consumed = 0, frames = 0;
sox_bool vbr = sox_false, depadded = sox_false;
+ size_t num_samples = 0;
p->mad_stream_init(&mad_stream);
p->mad_header_init(&mad_header);
@@ -309,7 +303,7 @@
continue; /* Not an audio frame */
}
- p->mad_timer_add(&time, mad_header.duration);
+ num_samples += MAD_NSBSAMPLES(&mad_header) * 32;
consumed += mad_stream.next_frame - mad_stream.this_frame;
lsx_debug_more("bitrate=%lu", mad_header.bitrate);
@@ -324,7 +318,7 @@
break;
}
if ((frames = xing_frames(p, mad_stream.anc_ptr, mad_stream.anc_bitlen))) {
- p->mad_timer_multiply(&time, (signed long)frames);
+ num_samples *= frames;
lsx_debug("got exact duration from XING frame count (%" PRIuPTR ")", frames);
break;
}
@@ -333,7 +327,9 @@
/* If not VBR, we can time just a few frames then extrapolate */
if (++frames == 25 && !vbr) {
- mad_timer_mult(&time, (double)(lsx_filelength(ft) - tagsize) / consumed);
+ double frame_size = (double) consumed / frames;
+ size_t num_frames = (lsx_filelength(ft) - tagsize) / frame_size;
+ num_samples = num_samples / frames * num_frames;
lsx_debug("got approx. duration by CBR extrapolation");
break;
}
@@ -344,7 +340,8 @@
mad_header_finish(&mad_header);
p->mad_stream_finish(&mad_stream);
lsx_rewind(ft);
- return p->mad_timer_count(time, MAD_UNITS_MILLISECONDS);
+
+ return num_samples;
}
#endif /* HAVE_MAD_H */
--- a/src/mp3.c
+++ b/src/mp3.c
@@ -391,7 +391,7 @@
if (!ft->signal.length)
#endif
if (!ignore_length)
- ft->signal.length = mp3_duration_ms(ft);
+ ft->signal.length = mp3_duration(ft);
}
p->mad_stream_init(&p->Stream);
@@ -466,7 +466,6 @@
if (ignore_length)
ft->signal.length = SOX_UNSPEC;
else {
- ft->signal.length = (uint64_t)(ft->signal.length * .001 * ft->signal.rate + .5);
ft->signal.length *= ft->signal.channels; /* Keep separate from line above! */
}