diff options
author | Alexey Yakovenko <wakeroid@gmail.com> | 2010-01-31 13:58:35 +0100 |
---|---|---|
committer | Alexey Yakovenko <wakeroid@gmail.com> | 2010-01-31 13:58:35 +0100 |
commit | 6ebbbba3263b075b1685e47e7db2f0f1727ddec3 (patch) | |
tree | c9ae7024c238dd54e3411edebfbbd4ede230493a /plugins/flac | |
parent | c1e21f401913f499c089bf87af0fcdb1ba67c9ec (diff) |
fixed multichannel flac decoding
Diffstat (limited to 'plugins/flac')
-rw-r--r-- | plugins/flac/flac.c | 75 |
1 files changed, 54 insertions, 21 deletions
diff --git a/plugins/flac/flac.c b/plugins/flac/flac.c index d3424831..b45b0205 100644 --- a/plugins/flac/flac.c +++ b/plugins/flac/flac.c @@ -110,20 +110,21 @@ cflac_write_callback (const FLAC__StreamDecoder *decoder, const FLAC__Frame *fra if (bitrate > 0) { deadbeef->streamer_set_bitrate (bitrate/1000); } - int readbytes = frame->header.blocksize * plugin.info.channels * plugin.info.bps / 8; int bufsize = BUFFERSIZE-remaining; int bufsamples = bufsize / (plugin.info.channels * plugin.info.bps / 8); int nsamples = min (bufsamples, frame->header.blocksize); char *bufptr = &buffer[remaining]; float mul = 1.f/ ((1 << (plugin.info.bps-1))-1); + int channels = plugin.info.channels; + if (channels > 2) { + channels = 2; + } + int readbytes = frame->header.blocksize * channels * plugin.info.bps / 8; + for (int i = 0; i < nsamples; i++) { - int32_t sample = inputbuffer[0][i]; - *((float*)bufptr) = sample * mul; - bufptr += sizeof (float); - remaining += sizeof (float); - if (plugin.info.channels > 1) { - int32_t sample = inputbuffer[1][i]; + for (int c = 0; c < channels; c++) { + int32_t sample = inputbuffer[c][i]; *((float*)bufptr) = sample * mul; bufptr += sizeof (float); remaining += sizeof (float); @@ -295,25 +296,39 @@ cflac_read_int16 (char *bytes, int size) { return 0; } } + int n_output_channels = plugin.info.channels; + if (n_output_channels > 2) { + n_output_channels = 2; + } int initsize = size; do { if (remaining) { - int s = size * 2; - int sz = min (remaining, s); + int n_input_frames = remaining / sizeof (float) / n_output_channels; + int n_output_frames = size / n_output_channels / sizeof (int16_t); + int n = min (n_input_frames, n_output_frames); + + trace ("flac: [1] if=%d, of=%d, n=%d, rem=%d, size=%d\n", n_input_frames, n_output_frames, n, remaining, size); // convert from float to int16 float *in = (float *)buffer; - for (int i = 0; i < sz/4; i++) { + for (int i = 0; i < n; i++) { *((int16_t *)bytes) = (int16_t)((*in) * 0x7fff); - size -= 2; - bytes += 2; - in++; + size -= sizeof (int16_t); + bytes += sizeof (int16_t); + if (n_output_channels == 2) { + *((int16_t *)bytes) = (int16_t)((*(in+1)) * 0x7fff); + size -= sizeof (int16_t); + bytes += sizeof (int16_t); + } + in += n_output_channels; } + int sz = n * sizeof (float) * n_output_channels; if (sz < remaining) { memmove (buffer, &buffer[sz], remaining-sz); } remaining -= sz; - currentsample += sz / (4 * plugin.info.channels); - plugin.info.readpos += (float)sz / (plugin.info.channels * plugin.info.samplerate * sizeof (float)); + currentsample += n; + plugin.info.readpos += (float)n / plugin.info.samplerate; + trace ("flac: [2] if=%d, of=%d, n=%d, rem=%d, size=%d\n", n_input_frames, n_output_frames, n, remaining, size); } if (!size) { break; @@ -343,19 +358,36 @@ cflac_read_float32 (char *bytes, int size) { return 0; } } + int n_output_channels = plugin.info.channels; + if (n_output_channels > 2) { + n_output_channels = 2; + } int initsize = size; do { if (remaining) { - int sz = min (remaining, size); - memcpy (bytes, buffer, sz); - size -= sz; - bytes += sz; + int n_input_frames = remaining / sizeof (float) / n_output_channels; + int n_output_frames = size / n_output_channels / sizeof (int16_t); + int n = min (n_input_frames, n_output_frames); + + float *in = (float *)buffer; + for (int i = 0; i < n; i++) { + *((float *)bytes) = *in; + size -= sizeof (float); + bytes += sizeof (float); + if (n_output_channels == 2) { + *((float *)bytes) = *(in+1); + size -= sizeof (float); + bytes += sizeof (float); + } + in += n_output_channels; + } + int sz = n * sizeof (float) * n_output_channels; if (sz < remaining) { memmove (buffer, &buffer[sz], remaining-sz); } remaining -= sz; - currentsample += sz / (4 * plugin.info.channels); - plugin.info.readpos += (float)sz / (plugin.info.channels * plugin.info.samplerate * sizeof (int32_t)); + currentsample += n; + plugin.info.readpos += (float)n / plugin.info.samplerate; } if (!size) { break; @@ -429,6 +461,7 @@ cflac_init_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__Str DB_playItem_t *it = cb->it; //it->tracknum = 0; if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { + trace ("flac: samplerate=%d, channels=%d\n", metadata->data.stream_info.sample_rate, metadata->data.stream_info.channels); cb->samplerate = metadata->data.stream_info.sample_rate; cb->channels = metadata->data.stream_info.channels; cb->totalsamples = metadata->data.stream_info.total_samples; |