diff options
author | Alexey Yakovenko <wakeroid@gmail.com> | 2010-08-14 09:34:19 +0200 |
---|---|---|
committer | Alexey Yakovenko <wakeroid@gmail.com> | 2010-08-14 09:34:19 +0200 |
commit | 38b7d3e6b6cd94486f1354cfd514f696a86b1a49 (patch) | |
tree | 1f78f20fda97181bbc1274068889fd3b8fa1c70a /plugins/sndfile | |
parent | 93f6591c6f471c5b0c84abefeb2be2d8034c8855 (diff) |
fixed multichannel decoding in sndfile plugin
Diffstat (limited to 'plugins/sndfile')
-rw-r--r-- | plugins/sndfile/sndfile.c | 54 |
1 files changed, 44 insertions, 10 deletions
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); |