diff options
author | Alexey Yakovenko <wakeroid@gmail.com> | 2009-09-06 00:13:12 +0200 |
---|---|---|
committer | Alexey Yakovenko <wakeroid@gmail.com> | 2009-09-06 00:13:12 +0200 |
commit | 84b38bb39ed778e35b37b5119a0732ea48a4b56b (patch) | |
tree | 4c28799db7430afac7ae8ed15dea8320ee776c7d /plugins | |
parent | c489e0f9e117b70c66c128a37b7b0fb4dd1e6bea (diff) |
added 8/16/24bit decoding and float32 output support to libmac decoder
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/ape/ape.c | 73 |
1 files changed, 70 insertions, 3 deletions
diff --git a/plugins/ape/ape.c b/plugins/ape/ape.c index 05c67fa2..96608c73 100644 --- a/plugins/ape/ape.c +++ b/plugins/ape/ape.c @@ -46,6 +46,13 @@ static float timestart; static float timeend; static int samplesdecoded; +// precalc for bps conversion +static int32_t mask; +static float scaler; +static int32_t neg; +static int32_t sign; +static int32_t signshift; + static int ape_seek (float seconds); @@ -78,6 +85,12 @@ ape_init (DB_playItem_t *it) { timeend = it->duration; } + mask = (1<<(plugin.info.bps-1))-1; + scaler = 1.f / ((1<<(plugin.info.bps-1))-1); + neg = 1<<plugin.info.bps; + sign = (1<<31); + signshift = plugin.info.bps-1; + return 0; } @@ -90,11 +103,30 @@ ape_free (void) { } static int -ape_read (char *buffer, int size) { +ape_read_int16 (char *buffer, int size) { int initsize = size; int nblocks = size / plugin.info.channels / 2; nblocks = min (nblocks, ape_blocks_left); - nblocks = ape_decompress_getdata (ape_dec, buffer, nblocks); + nblocks = ape_decompress_getdata (ape_dec, ape_readbuf, nblocks); + + uint8_t *in = ape_readbuf; + for (int i = 0; i < nblocks*plugin.info.channels; i++) { + // convert from bps to int32_t + int32_t sample = 0; + int shift = 0; + while (shift < plugin.info.bps - 8) { + sample |= (*in << shift); + in++; + shift += 8; + } + sample |= ((char)(*in)) << (plugin.info.bps - 8); + in++; + + // now that's convertable to 16 bit + *((int16_t*)buffer) = (int16_t)sample; + buffer += 2; + } + ape_blocks_left -= nblocks; samplesdecoded += nblocks; plugin.info.readpos = samplesdecoded / (float)plugin.info.samplerate - timestart; @@ -105,6 +137,40 @@ ape_read (char *buffer, int size) { } static int +ape_read_float32 (char *buffer, int size) { + int initsize = size; + int nblocks = size / plugin.info.channels / sizeof (float); + nblocks = min (nblocks, ape_blocks_left); + nblocks = ape_decompress_getdata (ape_dec, ape_readbuf, nblocks); + + uint8_t *in = ape_readbuf; + for (int i = 0; i < nblocks*plugin.info.channels; i++) { + // convert from bps to int32_t + int32_t sample = 0; + int shift = 0; + while (shift < plugin.info.bps - 8) { + sample |= (*in << shift); + in++; + shift += 8; + } + sample |= ((char)(*in)) << (plugin.info.bps - 8); + in++; + + // now that's convertable to float32 + *((float*)buffer) = (sample - ((sample&sign)>>signshift)*neg) * scaler; + buffer += sizeof (float); + } + + ape_blocks_left -= nblocks; + samplesdecoded += nblocks; + plugin.info.readpos = samplesdecoded / (float)plugin.info.samplerate - timestart; + if (plugin.info.readpos >= timeend) { + return 0; + } + return nblocks * sizeof (float) * plugin.info.channels; +} + +static int ape_seek (float seconds) { seconds += timestart; int nblock = seconds * plugin.info.samplerate; @@ -176,7 +242,8 @@ static DB_decoder_t plugin = { .plugin.website = "http://deadbeef.sf.net", .init = ape_init, .free = ape_free, - .read_int16 = ape_read, + .read_int16 = ape_read_int16, + .read_float32 = ape_read_float32, .seek = ape_seek, .insert = ape_insert, .exts = exts, |