From 38b7d3e6b6cd94486f1354cfd514f696a86b1a49 Mon Sep 17 00:00:00 2001 From: Alexey Yakovenko Date: Sat, 14 Aug 2010 09:34:19 +0200 Subject: fixed multichannel decoding in sndfile plugin --- plugins/sndfile/sndfile.c | 54 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 10 deletions(-) (limited to 'plugins/sndfile') diff --git a/plugins/sndfile/sndfile.c b/plugins/sndfile/sndfile.c index 0cb48675..90390603 100644 --- a/plugins/sndfile/sndfile.c +++ b/plugins/sndfile/sndfile.c @@ -174,16 +174,34 @@ sndfile_free (DB_fileinfo_t *_info) { static int sndfile_read_int16 (DB_fileinfo_t *_info, char *bytes, int size) { sndfile_info_t *info = (sndfile_info_t*)_info; - if (size / (2 * _info->channels) + info->currentsample > info->endsample) { - size = (info->endsample - info->currentsample + 1) * 2 * _info->channels; - trace ("wv: size truncated to %d bytes, cursample=%d, endsample=%d\n", size, info->currentsample, info->endsample); + int out_ch = min (_info->channels, 2); + if (size / (2 * out_ch) + info->currentsample > info->endsample) { + size = (info->endsample - info->currentsample + 1) * 2 * out_ch; + trace ("sndfile: size truncated to %d bytes, cursample=%d, endsample=%d\n", size, info->currentsample, info->endsample); if (size <= 0) { return 0; } } - int n = sf_readf_short (info->ctx, (short *)bytes, size/(2*_info->channels)); + + int n = 0; + if (out_ch != _info->channels) { + // read into temp buffer, and downmix + int nframes = size / out_ch / 2; + int16_t buf[nframes * _info->channels]; + n = sf_readf_short (info->ctx, buf, nframes); + for (int i = 0; i < n; i++) { + for (int j = 0; j < out_ch; j++) { + ((int16_t *)bytes)[i * out_ch + j] = buf[i * _info->channels + j]; + } + } + } + else { + n = sf_readf_short (info->ctx, (short *)bytes, size/(2*_info->channels)); + } info->currentsample += n; - size = n * 2 * _info->channels; + + + size = n * 2 * out_ch; _info->readpos = (float)(info->currentsample-info->startsample)/_info->samplerate; if (info->bitrate > 0) { deadbeef->streamer_set_bitrate (info->bitrate); @@ -194,16 +212,32 @@ sndfile_read_int16 (DB_fileinfo_t *_info, char *bytes, int size) { static int sndfile_read_float32 (DB_fileinfo_t *_info, char *bytes, int size) { sndfile_info_t *info = (sndfile_info_t*)_info; - if (size / (4 * _info->channels) + info->currentsample > info->endsample) { - size = (info->endsample - info->currentsample + 1) * 4 * _info->channels; - trace ("wv: size truncated to %d bytes, cursample=%d, endsample=%d\n", size, info->currentsample, info->endsample); + int out_ch = min (_info->channels, 2); + if (size / (4 * out_ch) + info->currentsample > info->endsample) { + size = (info->endsample - info->currentsample + 1) * 4 * out_ch; + trace ("sndfile: size truncated to %d bytes, cursample=%d, endsample=%d\n", size, info->currentsample, info->endsample); if (size <= 0) { return 0; } } - int n = sf_readf_float (info->ctx, (float *)bytes, size/(4*_info->channels)); + int n = 0; + if (out_ch != _info->channels) { + // read into temp buffer, and downmix + int nframes = size / out_ch / 4; + float buf[nframes * _info->channels]; + n = sf_readf_float (info->ctx, buf, nframes); + for (int i = 0; i < n; i++) { + for (int j = 0; j < out_ch; j++) { + ((float *)bytes)[i * out_ch + j] = buf[i * _info->channels + j]; + } + } + } + else { + n = sf_readf_float (info->ctx, (float *)bytes, size/(4*_info->channels)); + } + info->currentsample += n; - size = n * 4 * _info->channels; + size = n * 4 * out_ch; _info->readpos = (float)(info->currentsample-info->startsample)/_info->samplerate; if (info->bitrate > 0) { deadbeef->streamer_set_bitrate (info->bitrate); -- cgit v1.2.3