summaryrefslogtreecommitdiff
path: root/plugins/flac
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-01-31 13:58:35 +0100
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-01-31 13:58:35 +0100
commit6ebbbba3263b075b1685e47e7db2f0f1727ddec3 (patch)
treec9ae7024c238dd54e3411edebfbbd4ede230493a /plugins/flac
parentc1e21f401913f499c089bf87af0fcdb1ba67c9ec (diff)
fixed multichannel flac decoding
Diffstat (limited to 'plugins/flac')
-rw-r--r--plugins/flac/flac.c75
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;