Hello List,
I am trying to get our mad decoder in XMMS2 to playback LAME encoded files gapless by reading the decoder delay in the header, but I have some problems to get it working 100%. The test cases I have is confirmed playing gapless in foobar2000 so I guess I just doing something wrong :-)
I parse the LAME tag with more or less the same code as in madplay.c and then I do:
data->samples_to_skip = lame->start_delay; data->samples_to_skip_end = lame->end_padding; data->samples_to_play = (guint64)(((guint64)xmms_xing_get_frames (data->xing) * (guint64)1152) - (guint64)lame->start_delay); XMMS_DBG ("Samples to skip in the beginning: %d, total: %lld", data-
samples_to_skip, data->samples_to_play);
These flags are then used in my decoding function which is attached at the bottom.
Still I get around 1000 samples of silence in the beginning when I watch the output wave in a wave editor. My theories are that:
1) maybe MAD is adding silence to the output, I read something like hinted towards this on the interwebb somewhere. 2) that my find first sync code is not working properly. I feed the first frame (that I find the Xing/LAME tag in) back to the decoding routine found below, can that produce silence also? 3) My math is off somewhere :-)
Any help on getting this play "perfect" gapless would be very appreciated! The full code is available here: http://git.xmms.se/? p=xmms2-devel.git;a=tree;;f=src/plugins/mad
-- Tobias
static gint xmms_mad_read (xmms_xform_t *xform, gpointer buf, gint len, xmms_error_t *err) { xmms_mad_data_t *data; xmms_samples16_t *out = (xmms_samples16_t *)buf; gint ret; gint j; gint read = 0;
data = xmms_xform_private_data_get (xform);
j = 0;
while (read < len) {
/* use already synthetized frame first */ if (data->synthpos < data->synth.pcm.length) { if (data->samples_to_skip <= 0 && data->samples_to_play
= 0) {
out[j++] = scale_linear (data->synth.pcm.samples[0] [data->synthpos]); if (data->channels == 2) { out[j++] = scale_linear (data->synth.pcm.samples [1][data->synthpos]); read += 2 * xmms_sample_size_get (XMMS_SAMPLE_FORMAT_S16); data->samples_to_play -= 2; } else { read += xmms_sample_size_get (XMMS_SAMPLE_FORMAT_S16); data->samples_to_play --; } } else { if (data->channels == 2) { data->samples_to_skip -= 2; } else { data->samples_to_skip --; } } data->synthpos++; continue; }
/* then try to decode another frame */ if (mad_frame_decode (&data->frame, &data->stream) != -1) { mad_synth_frame (&data->synth, &data->frame); data->synthpos = 0; continue; } /* if there is no frame to decode stream more data */ if (data->stream.next_frame) { guchar *buffer = data->buffer; const guchar *nf = data->stream.next_frame; memmove (data->buffer, data->stream.next_frame, data->buffer_length = (&buffer[data-
buffer_length] - nf));
}
ret = xmms_xform_read (xform, (gchar *)data->buffer + data-
buffer_length,
4096 - data->buffer_length, err);
if (ret <= 0) { return ret; }
data->buffer_length += ret; mad_stream_buffer (&data->stream, data->buffer, data-
buffer_length);
}
return read; }