From f40bfc9267b13b54e6379dfe7539447662879d24 Mon Sep 17 00:00:00 2001 From: Sean Bartell Date: Sat, 25 Jun 2011 21:32:25 -0400 Subject: Add codecs to librbcodec. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Id7f4717d51ed02d67cb9f9cb3c0ada4a81843f97 Reviewed-on: http://gerrit.rockbox.org/137 Reviewed-by: Nils Wallménius Tested-by: Nils Wallménius --- lib/rbcodec/codecs/libalac/README | 43 ++ lib/rbcodec/codecs/libalac/README.rockbox | 80 ++ lib/rbcodec/codecs/libalac/SOURCES | 1 + lib/rbcodec/codecs/libalac/alac.c | 1148 +++++++++++++++++++++++++++++ lib/rbcodec/codecs/libalac/decomp.h | 54 ++ lib/rbcodec/codecs/libalac/libalac.make | 18 + 6 files changed, 1344 insertions(+) create mode 100644 lib/rbcodec/codecs/libalac/README create mode 100644 lib/rbcodec/codecs/libalac/README.rockbox create mode 100644 lib/rbcodec/codecs/libalac/SOURCES create mode 100644 lib/rbcodec/codecs/libalac/alac.c create mode 100644 lib/rbcodec/codecs/libalac/decomp.h create mode 100644 lib/rbcodec/codecs/libalac/libalac.make (limited to 'lib/rbcodec/codecs/libalac') diff --git a/lib/rbcodec/codecs/libalac/README b/lib/rbcodec/codecs/libalac/README new file mode 100644 index 0000000000..1b304d2d93 --- /dev/null +++ b/lib/rbcodec/codecs/libalac/README @@ -0,0 +1,43 @@ +INSTALLATION: +------------- + +Simply compile by running 'make' + +USAGE: +------ + +Then run the program, it will give you usage instructions. + +It's really quite trivial to use. + +For example, to decode input.m4a to output.wav: +./alac -f output.wav input.m4a + +Or, as another example, say if you wanted to stream play +http://www.mplayerhq.hu/MPlayer/samples/A-codecs/lossless/luckynight.m4a +and you're system uses the ALSA sound system: +wget -O - http://www.mplayerhq.hu/MPlayer/samples/A-codecs/lossless/luckynight.m4a | ./alac - | aplay + +By default the output file is in WAV format. To output as raw PCM, provide the +-r option on the command line. + +MORE INFORMATION: +----------------- + +Please visit http://crazney.net/programs/itunes/alac.html for more information. + +HELP NEEDED: +------------ +I need help to allow myself to continue hacking on various Apple Audio things, please visit +http://crazney.net/programs/itunes/help.html + +AUTHOR: +------- + +David Hammerton + +CONTRIBUTORS: +------------- + +Cody Brocious + diff --git a/lib/rbcodec/codecs/libalac/README.rockbox b/lib/rbcodec/codecs/libalac/README.rockbox new file mode 100644 index 0000000000..891e581cfc --- /dev/null +++ b/lib/rbcodec/codecs/libalac/README.rockbox @@ -0,0 +1,80 @@ +Library: Reverse-engineered ALAC decoder v0.1.0 +Imported: 2005-08-14 by Dave Chapman + + +This directory contains a local version of an ALAC (Apple Lossless Audio +Codec) for use by Rockbox for software decoding of ALAC files. It is +based on the reverse-engineered decoder by David Hamilton. + +LICENSING INFORMATION + +/* + * ALAC (Apple Lossless Audio Codec) decoder + * Copyright (c) 2005 David Hammerton + * All rights reserved. + * + * This is the actual decoder. + * + * http://crazney.net/programs/itunes/alac.html + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +IMPORT DETAILS + +The base version first imported into Rockbox was the first release +(v0.1.0) of the ALAC decoder by David Hammerton. + +Only the files alac.[ch], demux.[ch] and stream.h were used. + +stream.c (the original FILE* based I/O implementation) was replaced with +functions in the ALAC codec - to interface with the Rockbox audio playback +system. + +References to were replaced with and debugging +calls to fprintf were removed. + +The ALAC decoder itself was modified to return samples in host-endian +order, instead of little-endian. + +The run-time detection of CPU endianness was replaced with +compile-time tests of the ROCKBOX_LITTLE_ENDIAN define. + +All malloc calls were removed from alac.c, but some are still present +in the metadata parser in demux.c - to store unbounded data such as +the size in bytes of each compressed block in the file. + +The only changes to demux.c were to remove debugging calls to fprintf. + +The most-used buffers (the temporary 32-bit output buffer) were moved +into IRAM (on the iRiver). This was enough to make the decoder work +in real-time. + +A point of interest - the -O3 gcc option (the setting used in the +original Makefile provided with the alac decoder) gives a significant +speedup compared to -O2. With -O2, the Coldfire runs at a constant +120MHz, but with -O3, it can power-down to 40MHz for a small amount of +time. + +The file alac.c contained some hints from the original author for +places where major optimisations can be made - specifically the +unrolling and optimisation of certain cases of general loops. diff --git a/lib/rbcodec/codecs/libalac/SOURCES b/lib/rbcodec/codecs/libalac/SOURCES new file mode 100644 index 0000000000..854b9e6f88 --- /dev/null +++ b/lib/rbcodec/codecs/libalac/SOURCES @@ -0,0 +1 @@ +alac.c diff --git a/lib/rbcodec/codecs/libalac/alac.c b/lib/rbcodec/codecs/libalac/alac.c new file mode 100644 index 0000000000..fd24656504 --- /dev/null +++ b/lib/rbcodec/codecs/libalac/alac.c @@ -0,0 +1,1148 @@ +/* + * ALAC (Apple Lossless Audio Codec) decoder + * Copyright (c) 2005 David Hammerton + * All rights reserved. + * + * This is the actual decoder. + * + * http://crazney.net/programs/itunes/alac.html + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + + +#include +#include +#include +#include + +#include "codeclib.h" +#include "decomp.h" + +#define SIGNEXTEND24(val) (((signed)val<<8)>>8) + +static int16_t predictor_coef_table[32] IBSS_ATTR; +static int16_t predictor_coef_table_a[32] IBSS_ATTR; +static int16_t predictor_coef_table_b[32] IBSS_ATTR; + + +/* Endian/aligment safe functions - only used in alac_set_info() */ +static uint32_t get_uint32be(unsigned char* p) +{ + return((p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]); +} + +static uint16_t get_uint16be(unsigned char* p) +{ + return((p[0]<<8) | p[1]); +} + +void alac_set_info(alac_file *alac, char *inputbuffer) +{ + unsigned char* ptr = (unsigned char*)inputbuffer; + ptr += 4; /* size */ + ptr += 4; /* frma */ + ptr += 4; /* alac */ + ptr += 4; /* size */ + ptr += 4; /* alac */ + + ptr += 4; /* 0 ? */ + + alac->setinfo_max_samples_per_frame = get_uint32be(ptr); /* buffer size / 2 ? */ + ptr += 4; + alac->setinfo_7a = *ptr++; + alac->setinfo_sample_size = *ptr++; + alac->setinfo_rice_historymult = *ptr++; + alac->setinfo_rice_initialhistory = *ptr++; + alac->setinfo_rice_kmodifier = *ptr++; + alac->setinfo_7f = *ptr++; + ptr += 1; + alac->setinfo_80 = get_uint16be(ptr); + ptr += 2; + alac->setinfo_82 = get_uint32be(ptr); + ptr += 4; + alac->setinfo_86 = get_uint32be(ptr); + ptr += 4; + alac->setinfo_8a_rate = get_uint32be(ptr); + ptr += 4; +} + +/* stream reading */ + +/* supports reading 1 to 16 bits, in big endian format */ +static inline uint32_t readbits_16(alac_file *alac, int bits) +{ + uint32_t result; + int new_accumulator; + + result = (alac->input_buffer[0] << 16) | + (alac->input_buffer[1] << 8) | + (alac->input_buffer[2]); + + /* shift left by the number of bits we've already read, + * so that the top 'n' bits of the 24 bits we read will + * be the return bits */ + result = result << alac->input_buffer_bitaccumulator; + + result = result & 0x00ffffff; + + /* and then only want the top 'n' bits from that, where + * n is 'bits' */ + result = result >> (24 - bits); + + new_accumulator = (alac->input_buffer_bitaccumulator + bits); + + /* increase the buffer pointer if we've read over n bytes. */ + alac->input_buffer += (new_accumulator >> 3); + + /* and the remainder goes back into the bit accumulator */ + alac->input_buffer_bitaccumulator = (new_accumulator & 7); + + return result; +} + +/* supports reading 1 to 32 bits, in big endian format */ +static inline uint32_t readbits(alac_file *alac, int bits) +{ + int32_t result = 0; + + if (bits > 16) + { + bits -= 16; + result = readbits_16(alac, 16) << bits; + } + + result |= readbits_16(alac, bits); + + return result; +} + +/* reads a single bit */ +static inline int readbit(alac_file *alac) +{ + int result; + int new_accumulator; + + result = alac->input_buffer[0]; + + result = result << alac->input_buffer_bitaccumulator; + + result = result >> 7 & 1; + + new_accumulator = (alac->input_buffer_bitaccumulator + 1); + + alac->input_buffer += (new_accumulator / 8); + + alac->input_buffer_bitaccumulator = (new_accumulator % 8); + + return result; +} + +static inline void unreadbits(alac_file *alac, int bits) +{ + int new_accumulator = (alac->input_buffer_bitaccumulator - bits); + + alac->input_buffer += (new_accumulator >> 3); + + alac->input_buffer_bitaccumulator = (new_accumulator & 7); + if (alac->input_buffer_bitaccumulator < 0) + alac->input_buffer_bitaccumulator *= -1; +} + +#define count_leading_zeros(x) bs_generic(x, BS_CLZ|BS_SHORT) + +#define RICE_THRESHOLD 8 // maximum number of bits for a rice prefix. + +static inline int32_t entropy_decode_value(alac_file* alac, + int readsamplesize, + int k) ICODE_ATTR_ALAC; +static inline int32_t entropy_decode_value(alac_file* alac, + int readsamplesize, + int k) +{ + int32_t x = 0; // decoded value + + // read x, number of 1s before 0 represent the rice value. + while (x <= RICE_THRESHOLD && readbit(alac)) + { + x++; + } + + if (x > RICE_THRESHOLD) + { + // read the number from the bit stream (raw value) + int32_t value; + + value = readbits(alac, readsamplesize); + + /* mask value to readsamplesize size */ + if (readsamplesize != 32) + value &= (((uint32_t)0xffffffff) >> (32 - readsamplesize)); + + x = value; + } + else + { + if (k != 1) + { + int extrabits = readbits(alac, k); + + // x = x * (2^k - 1) + x = (x << k) - x; + + if (extrabits > 1) + x += extrabits - 1; + else + unreadbits(alac, 1); + } + } + + return x; +} + +static void entropy_rice_decode(alac_file* alac, + int32_t* output_buffer, + int output_size, + int readsamplesize, + int rice_initialhistory, + int rice_kmodifier, + int rice_historymult, + int rice_kmodifier_mask) ICODE_ATTR_ALAC; +static void entropy_rice_decode(alac_file* alac, + int32_t* output_buffer, + int output_size, + int readsamplesize, + int rice_initialhistory, + int rice_kmodifier, + int rice_historymult, + int rice_kmodifier_mask) +{ + int output_count; + int history = rice_initialhistory; + int sign_modifier = 0; + + for (output_count = 0; output_count < output_size; output_count++) + { + int32_t decoded_value; + int32_t final_value; + int32_t k; + + k = 31 - rice_kmodifier - count_leading_zeros((history >> 9) + 3); + + if (k < 0) k += rice_kmodifier; + else k = rice_kmodifier; + + decoded_value = entropy_decode_value(alac, readsamplesize, k); + + decoded_value += sign_modifier; + final_value = (decoded_value + 1) / 2; // inc by 1 and shift out sign bit + if (decoded_value & 1) // the sign is stored in the low bit + final_value *= -1; + + output_buffer[output_count] = final_value; + + sign_modifier = 0; + + // update history + history += (decoded_value * rice_historymult) + - ((history * rice_historymult) >> 9); + + if (decoded_value > 0xFFFF) + history = 0xFFFF; + + // special case, for compressed blocks of 0 + if ((history < 128) && (output_count + 1 < output_size)) + { + int32_t block_size; + + sign_modifier = 1; + + k = count_leading_zeros(history) + ((history + 16) / 64) - 24; + + // note: block_size is always 16bit + block_size = entropy_decode_value(alac, 16, k) & rice_kmodifier_mask; + + // got block_size 0s + if (block_size > 0) + { + memset(&output_buffer[output_count + 1], 0, + block_size * sizeof(*output_buffer)); + output_count += block_size; + } + + if (block_size > 0xFFFF) + sign_modifier = 0; + + history = 0; + } + } +} + +#define SIGN_EXTENDED32(val, bits) ((val << (32 - bits)) >> (32 - bits)) + +#define SIGN_ONLY(v) \ + ((v < 0) ? (-1) : \ + ((v > 0) ? (1) : \ + (0))) + +static void predictor_decompress_fir_adapt(int32_t *error_buffer, + int32_t *buffer_out, + int output_size, + int readsamplesize, + int16_t *predictor_coef_table, + int predictor_coef_num, + int predictor_quantitization) ICODE_ATTR_ALAC; +static void predictor_decompress_fir_adapt(int32_t *error_buffer, + int32_t *buffer_out, + int output_size, + int readsamplesize, + int16_t *predictor_coef_table, + int predictor_coef_num, + int predictor_quantitization) +{ + int i; + + /* first sample always copies */ + *buffer_out = *error_buffer; + + if (!predictor_coef_num) + { + if (output_size <= 1) return; + memcpy(buffer_out+1, error_buffer+1, (output_size-1) * 4); + return; + } + + if (predictor_coef_num == 0x1f) /* 11111 - max value of predictor_coef_num */ + { /* second-best case scenario for fir decompression, + * error describes a small difference from the previous sample only + */ + if (output_size <= 1) return; + for (i = 0; i < output_size - 1; i++) + { + int32_t prev_value; + int32_t error_value; + + prev_value = buffer_out[i]; + error_value = error_buffer[i+1]; + buffer_out[i+1] = SIGN_EXTENDED32((prev_value + error_value), readsamplesize); + } + return; + } + + /* read warm-up samples */ + if (predictor_coef_num > 0) + { + int i; + for (i = 0; i < predictor_coef_num; i++) + { + int32_t val; + + val = buffer_out[i] + error_buffer[i+1]; + + val = SIGN_EXTENDED32(val, readsamplesize); + + buffer_out[i+1] = val; + } + } + + /* 4 and 8 are very common cases (the only ones i've seen). + + The following code is an initial attempt to unroll and optimise + these two cases by the Rockbox project. More work is needed. + */ + + /* optimised case: 4 */ + if (predictor_coef_num == 4) + { + for (i = 4 + 1; i < output_size; i++) + { + int sum = 0; + int outval; + int error_val = error_buffer[i]; + + sum = (buffer_out[4] - buffer_out[0]) * predictor_coef_table[0] + + (buffer_out[3] - buffer_out[0]) * predictor_coef_table[1] + + (buffer_out[2] - buffer_out[0]) * predictor_coef_table[2] + + (buffer_out[1] - buffer_out[0]) * predictor_coef_table[3]; + + outval = (1 << (predictor_quantitization-1)) + sum; + outval = outval >> predictor_quantitization; + outval = outval + buffer_out[0] + error_val; + outval = SIGN_EXTENDED32(outval, readsamplesize); + + buffer_out[4+1] = outval; + + if (error_val > 0) + { + int predictor_num = 4 - 1; + + while (predictor_num >= 0 && error_val > 0) + { + int val = buffer_out[0] - buffer_out[4 - predictor_num]; + + if (val!=0) { + if (val < 0) { + predictor_coef_table[predictor_num]++; + val=-val; + } else { + predictor_coef_table[predictor_num]--; + } + error_val -= ((val >> predictor_quantitization) * (4 - predictor_num)); + } + predictor_num--; + } + } + else if (error_val < 0) + { + int predictor_num = 4 - 1; + + while (predictor_num >= 0 && error_val < 0) + { + int val = buffer_out[0] - buffer_out[4 - predictor_num]; + + if (val != 0) { + if (val > 0) { + predictor_coef_table[predictor_num]++; + val=-val; /* neg value */ + } else { + predictor_coef_table[predictor_num]--; + } + error_val -= ((val >> predictor_quantitization) * (4 - predictor_num)); + } + predictor_num--; + } + } + + buffer_out++; + } + return; + } + + /* optimised case: 8 */ + if (predictor_coef_num == 8) + { + for (i = 8 + 1; + i < output_size; + i++) + { + int sum; + int outval; + int error_val = error_buffer[i]; + + sum = (buffer_out[8] - buffer_out[0]) * predictor_coef_table[0] + + (buffer_out[7] - buffer_out[0]) * predictor_coef_table[1] + + (buffer_out[6] - buffer_out[0]) * predictor_coef_table[2] + + (buffer_out[5] - buffer_out[0]) * predictor_coef_table[3] + + (buffer_out[4] - buffer_out[0]) * predictor_coef_table[4] + + (buffer_out[3] - buffer_out[0]) * predictor_coef_table[5] + + (buffer_out[2] - buffer_out[0]) * predictor_coef_table[6] + + (buffer_out[1] - buffer_out[0]) * predictor_coef_table[7]; + + outval = (1 << (predictor_quantitization-1)) + sum; + outval = outval >> predictor_quantitization; + outval = outval + buffer_out[0] + error_val; + outval = SIGN_EXTENDED32(outval, readsamplesize); + + buffer_out[8+1] = outval; + + if (error_val > 0) + { + int predictor_num = 8 - 1; + + while (predictor_num >= 0 && error_val > 0) + { + int val = buffer_out[0] - buffer_out[8 - predictor_num]; + + if (val!=0) { + if (val < 0) { + predictor_coef_table[predictor_num]++; + val=-val; + } else { + predictor_coef_table[predictor_num]--; + } + error_val -= ((val >> predictor_quantitization) * (8 - predictor_num)); + } + predictor_num--; + } + } + else if (error_val < 0) + { + int predictor_num = 8 - 1; + + while (predictor_num >= 0 && error_val < 0) + { + int val = buffer_out[0] - buffer_out[8 - predictor_num]; + if (val != 0) { + if (val > 0) { + predictor_coef_table[predictor_num]++; + val=-val; /* neg value */ + } else { + predictor_coef_table[predictor_num]--; + } + error_val -= ((val >> predictor_quantitization) * (8 - predictor_num)); + } + predictor_num--; + } + } + + buffer_out++; + } + return; + } + + /* general case */ + if (predictor_coef_num > 0) + { + for (i = predictor_coef_num + 1; + i < output_size; + i++) + { + int j; + int sum = 0; + int outval; + int error_val = error_buffer[i]; + + for (j = 0; j < predictor_coef_num; j++) + { + sum += (buffer_out[predictor_coef_num-j] - buffer_out[0]) * + predictor_coef_table[j]; + } + + outval = (1 << (predictor_quantitization-1)) + sum; + outval = outval >> predictor_quantitization; + outval = outval + buffer_out[0] + error_val; + outval = SIGN_EXTENDED32(outval, readsamplesize); + + buffer_out[predictor_coef_num+1] = outval; + + if (error_val > 0) + { + int predictor_num = predictor_coef_num - 1; + + while (predictor_num >= 0 && error_val > 0) + { + int val = buffer_out[0] - buffer_out[predictor_coef_num - predictor_num]; + int sign = SIGN_ONLY(val); + + predictor_coef_table[predictor_num] -= sign; + + val *= sign; /* absolute value */ + + error_val -= ((val >> predictor_quantitization) * + (predictor_coef_num - predictor_num)); + + predictor_num--; + } + } + else if (error_val < 0) + { + int predictor_num = predictor_coef_num - 1; + + while (predictor_num >= 0 && error_val < 0) + { + int val = buffer_out[0] - buffer_out[predictor_coef_num - predictor_num]; + int sign = - SIGN_ONLY(val); + + predictor_coef_table[predictor_num] -= sign; + + val *= sign; /* neg value */ + + error_val -= ((val >> predictor_quantitization) * + (predictor_coef_num - predictor_num)); + + predictor_num--; + } + } + + buffer_out++; + } + } +} + +static void deinterlace_16(int32_t* buffer0, + int32_t* buffer1, + int numsamples, + uint8_t interlacing_shift, + uint8_t interlacing_leftweight) ICODE_ATTR_ALAC; +static void deinterlace_16(int32_t* buffer0, + int32_t* buffer1, + int numsamples, + uint8_t interlacing_shift, + uint8_t interlacing_leftweight) +{ + int i; + if (numsamples <= 0) return; + + /* weighted interlacing */ + if (interlacing_leftweight) + { + for (i = 0; i < numsamples; i++) + { + int32_t difference, midright; + + midright = buffer0[i]; + difference = buffer1[i]; + + buffer0[i] = ((midright - ((difference * interlacing_leftweight) + >> interlacing_shift)) + difference) << SCALE16; + buffer1[i] = (midright - ((difference * interlacing_leftweight) + >> interlacing_shift)) << SCALE16; + } + + return; + } + + /* otherwise basic interlacing took place */ + for (i = 0; i < numsamples; i++) + { + buffer0[i] = buffer0[i] << SCALE16; + buffer1[i] = buffer1[i] << SCALE16; + } +} + +static void deinterlace_24(int32_t *buffer0, int32_t *buffer1, + int uncompressed_bytes, + int32_t *uncompressed_bytes_buffer0, + int32_t *uncompressed_bytes_buffer1, + int numsamples, + uint8_t interlacing_shift, + uint8_t interlacing_leftweight) ICODE_ATTR_ALAC; +static void deinterlace_24(int32_t *buffer0, int32_t *buffer1, + int uncompressed_bytes, + int32_t *uncompressed_bytes_buffer0, + int32_t *uncompressed_bytes_buffer1, + int numsamples, + uint8_t interlacing_shift, + uint8_t interlacing_leftweight) +{ + int i; + if (numsamples <= 0) return; + + /* weighted interlacing */ + if (interlacing_leftweight) + { + for (i = 0; i < numsamples; i++) + { + int32_t difference, midright; + + midright = buffer0[i]; + difference = buffer1[i]; + + buffer0[i] = ((midright - ((difference * interlacing_leftweight) + >> interlacing_shift)) + difference) << SCALE24; + buffer1[i] = (midright - ((difference * interlacing_leftweight) + >> interlacing_shift)) << SCALE24; + + if (uncompressed_bytes) + { + uint32_t mask = ~(0xFFFFFFFF << (uncompressed_bytes * 8)); + buffer0[i] <<= (uncompressed_bytes * 8); + buffer1[i] <<= (uncompressed_bytes * 8); + + buffer0[i] |= uncompressed_bytes_buffer0[i] & mask; + buffer1[i] |= uncompressed_bytes_buffer1[i] & mask; + } + + } + + return; + } + + /* otherwise basic interlacing took place */ + for (i = 0; i < numsamples; i++) + { + if (uncompressed_bytes) + { + uint32_t mask = ~(0xFFFFFFFF << (uncompressed_bytes * 8)); + buffer0[i] <<= (uncompressed_bytes * 8); + buffer1[i] <<= (uncompressed_bytes * 8); + + buffer0[i] |= uncompressed_bytes_buffer0[i] & mask; + buffer1[i] |= uncompressed_bytes_buffer1[i] & mask; + } + + buffer0[i] = buffer0[i] << SCALE24; + buffer1[i] = buffer1[i] << SCALE24; + } + +} + +static inline int decode_frame_mono( + alac_file *alac, + int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE], + void (*yield)(void)) +{ + int hassize; + int isnotcompressed; + int readsamplesize; + int infosamplesize = alac->setinfo_sample_size; + int outputsamples = alac->setinfo_max_samples_per_frame; + + int uncompressed_bytes; + int ricemodifier; + + + /* 2^result = something to do with output waiting. + * perhaps matters if we read > 1 frame in a pass? + */ + readbits(alac, 4); + + readbits(alac, 12); /* unknown, skip 12 bits */ + + hassize = readbits(alac, 1); /* the output sample size is stored soon */ + + /* number of bytes in the (compressed) stream that are not compressed */ + uncompressed_bytes = readbits(alac, 2); + + isnotcompressed = readbits(alac, 1); /* whether the frame is compressed */ + + if (hassize) + { + /* now read the number of samples, + * as a 32bit integer */ + outputsamples = readbits(alac, 32); + } + + readsamplesize = infosamplesize - (uncompressed_bytes * 8); + + if (!isnotcompressed) + { /* so it is compressed */ + int predictor_coef_num; + int prediction_type; + int prediction_quantitization; + int i; + + /* skip 16 bits, not sure what they are. seem to be used in + * two channel case */ + readbits(alac, 8); + readbits(alac, 8); + + prediction_type = readbits(alac, 4); + prediction_quantitization = readbits(alac, 4); + + ricemodifier = readbits(alac, 3); + predictor_coef_num = readbits(alac, 5); + + /* read the predictor table */ + for (i = 0; i < predictor_coef_num; i++) + { + predictor_coef_table[i] = (int16_t)readbits(alac, 16); + } + + if (uncompressed_bytes) + { + int i; + for (i = 0; i < outputsamples; i++) + { + outputbuffer[0][i] = readbits(alac, uncompressed_bytes * 8); + outputbuffer[1][i] = outputbuffer[0][i]; + } + } + + yield(); + + entropy_rice_decode(alac, + outputbuffer[0], + outputsamples, + readsamplesize, + alac->setinfo_rice_initialhistory, + alac->setinfo_rice_kmodifier, + ricemodifier * alac->setinfo_rice_historymult / 4, + (1 << alac->setinfo_rice_kmodifier) - 1); + + yield(); + + if (prediction_type == 0) + { /* adaptive fir */ + predictor_decompress_fir_adapt(outputbuffer[0], + outputbuffer[0], + outputsamples, + readsamplesize, + predictor_coef_table, + predictor_coef_num, + prediction_quantitization); + } + else + { + //fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type); + /* i think the only other prediction type (or perhaps this is just a + * boolean?) runs adaptive fir twice.. like: + * predictor_decompress_fir_adapt(predictor_error, tempout, ...) + * predictor_decompress_fir_adapt(predictor_error, outputsamples ...) + * little strange.. + */ + } + + } + else + { /* not compressed, easy case */ + if (infosamplesize <= 16) + { + int i; + for (i = 0; i < outputsamples; i++) + { + int32_t audiobits = readbits(alac, infosamplesize); + + audiobits = SIGN_EXTENDED32(audiobits, infosamplesize); + + outputbuffer[0][i] = audiobits; + } + } + else + { + int i; + for (i = 0; i < outputsamples; i++) + { + int32_t audiobits; + + audiobits = readbits(alac, 16); + /* special case of sign extension.. + * as we'll be ORing the low 16bits into this */ + audiobits = audiobits << (infosamplesize - 16); + audiobits |= readbits(alac, infosamplesize - 16); + audiobits = SIGNEXTEND24(audiobits); + + outputbuffer[0][i] = audiobits; + } + } + uncompressed_bytes = 0; // always 0 for uncompressed + } + + yield(); + + switch(infosamplesize) + { + case 16: + { + int i; + for (i = 0; i < outputsamples; i++) + { + /* Output mono data as stereo */ + outputbuffer[0][i] = outputbuffer[0][i] << SCALE16; + outputbuffer[1][i] = outputbuffer[0][i]; + } + break; + } + case 24: + { + int i; + for (i = 0; i < outputsamples; i++) + { + int32_t sample = outputbuffer[0][i]; + + if (uncompressed_bytes) + { + uint32_t mask; + sample = sample << (uncompressed_bytes * 8); + mask = ~(0xFFFFFFFF << (uncompressed_bytes * 8)); + sample |= outputbuffer[0][i] & mask; + } + + outputbuffer[0][i] = sample << SCALE24; + outputbuffer[1][i] = outputbuffer[0][i]; + } + break; + } + case 20: + case 32: + //fprintf(stderr, "FIXME: unimplemented sample size %i\n", infosamplesize); + break; + default: + break; + } + + return outputsamples; +} + +static inline int decode_frame_stereo( + alac_file *alac, + int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE], + void (*yield)(void)) +{ + int hassize; + int isnotcompressed; + int readsamplesize; + int infosamplesize = alac->setinfo_sample_size; + int outputsamples = alac->setinfo_max_samples_per_frame; + int uncompressed_bytes; + + uint8_t interlacing_shift; + uint8_t interlacing_leftweight; + + /* 2^result = something to do with output waiting. + * perhaps matters if we read > 1 frame in a pass? + */ + readbits(alac, 4); + + readbits(alac, 12); /* unknown, skip 12 bits */ + + hassize = readbits(alac, 1); /* the output sample size is stored soon */ + + /* the number of bytes in the (compressed) stream that are not compressed */ + uncompressed_bytes = readbits(alac, 2); + + isnotcompressed = readbits(alac, 1); /* whether the frame is compressed */ + + if (hassize) + { + /* now read the number of samples, + * as a 32bit integer */ + outputsamples = readbits(alac, 32); + } + + readsamplesize = infosamplesize - (uncompressed_bytes * 8) + 1; + + yield(); + if (!isnotcompressed) + { /* compressed */ + int predictor_coef_num_a; + int prediction_type_a; + int prediction_quantitization_a; + int ricemodifier_a; + + int predictor_coef_num_b; + int prediction_type_b; + int prediction_quantitization_b; + int ricemodifier_b; + + int i; + + interlacing_shift = readbits(alac, 8); + interlacing_leftweight = readbits(alac, 8); + + /******** channel 1 ***********/ + prediction_type_a = readbits(alac, 4); + prediction_quantitization_a = readbits(alac, 4); + + ricemodifier_a = readbits(alac, 3); + predictor_coef_num_a = readbits(alac, 5); + + /* read the predictor table */ + for (i = 0; i < predictor_coef_num_a; i++) + { + predictor_coef_table_a[i] = (int16_t)readbits(alac, 16); + } + + /******** channel 2 *********/ + prediction_type_b = readbits(alac, 4); + prediction_quantitization_b = readbits(alac, 4); + + ricemodifier_b = readbits(alac, 3); + predictor_coef_num_b = readbits(alac, 5); + + /* read the predictor table */ + for (i = 0; i < predictor_coef_num_b; i++) + { + predictor_coef_table_b[i] = (int16_t)readbits(alac, 16); + } + + /*********************/ + if (uncompressed_bytes) + { /* see mono case */ + int i; + for (i = 0; i < outputsamples; i++) + { + outputbuffer[0][i] = readbits(alac, uncompressed_bytes * 8); + outputbuffer[1][i] = readbits(alac, uncompressed_bytes * 8); + } + } + + yield(); + /* channel 1 */ + entropy_rice_decode(alac, + outputbuffer[0], + outputsamples, + readsamplesize, + alac->setinfo_rice_initialhistory, + alac->setinfo_rice_kmodifier, + ricemodifier_a * alac->setinfo_rice_historymult / 4, + (1 << alac->setinfo_rice_kmodifier) - 1); + + yield(); + if (prediction_type_a == 0) + { /* adaptive fir */ + predictor_decompress_fir_adapt(outputbuffer[0], + outputbuffer[0], + outputsamples, + readsamplesize, + predictor_coef_table_a, + predictor_coef_num_a, + prediction_quantitization_a); + } + else + { /* see mono case */ + //fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type_a); + } + + yield(); + + /* channel 2 */ + entropy_rice_decode(alac, + outputbuffer[1], + outputsamples, + readsamplesize, + alac->setinfo_rice_initialhistory, + alac->setinfo_rice_kmodifier, + ricemodifier_b * alac->setinfo_rice_historymult / 4, + (1 << alac->setinfo_rice_kmodifier) - 1); + + yield(); + if (prediction_type_b == 0) + { /* adaptive fir */ + predictor_decompress_fir_adapt(outputbuffer[1], + outputbuffer[1], + outputsamples, + readsamplesize, + predictor_coef_table_b, + predictor_coef_num_b, + prediction_quantitization_b); + } + else + { + //fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type_b); + } + } + else + { /* not compressed, easy case */ + if (infosamplesize <= 16) + { + int i; + for (i = 0; i < outputsamples; i++) + { + int32_t audiobits_a, audiobits_b; + + audiobits_a = readbits(alac, infosamplesize); + audiobits_b = readbits(alac, infosamplesize); + + audiobits_a = SIGN_EXTENDED32(audiobits_a, infosamplesize); + audiobits_b = SIGN_EXTENDED32(audiobits_b, infosamplesize); + + outputbuffer[0][i] = audiobits_a; + outputbuffer[1][i] = audiobits_b; + } + } + else + { + int i; + for (i = 0; i < outputsamples; i++) + { + int32_t audiobits_a, audiobits_b; + + audiobits_a = readbits(alac, 16); + audiobits_a = audiobits_a << (infosamplesize - 16); + audiobits_a |= readbits(alac, infosamplesize - 16); + audiobits_a = SIGNEXTEND24(audiobits_a); + + audiobits_b = readbits(alac, 16); + audiobits_b = audiobits_b << (infosamplesize - 16); + audiobits_b |= readbits(alac, infosamplesize - 16); + audiobits_b = SIGNEXTEND24(audiobits_b); + + outputbuffer[0][i] = audiobits_a; + outputbuffer[1][i] = audiobits_b; + } + } + uncompressed_bytes = 0; // always 0 for uncompressed + interlacing_shift = 0; + interlacing_leftweight = 0; + } + + yield(); + + switch(infosamplesize) + { + case 16: + { + deinterlace_16(outputbuffer[0], + outputbuffer[1], + outputsamples, + interlacing_shift, + interlacing_leftweight); + break; + } + case 24: + { + deinterlace_24(outputbuffer[0], + outputbuffer[1], + uncompressed_bytes, + outputbuffer[0], + outputbuffer[1], + outputsamples, + interlacing_shift, + interlacing_leftweight); + break; + } + case 20: + case 32: + //fprintf(stderr, "FIXME: unimplemented sample size %i\n", infosamplesize); + break; + default: + break; + } + return outputsamples; +} + +int alac_decode_frame(alac_file *alac, + unsigned char *inbuffer, + int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE], + void (*yield)(void)) +{ + int channels; + int outputsamples; + unsigned char *input_buffer_start; + + /* setup the stream */ + alac->input_buffer = inbuffer; + alac->input_buffer_bitaccumulator = 0; + + /* save to gather byte consumption */ + input_buffer_start = alac->input_buffer; + + channels = readbits(alac, 3); + + /* TODO: The mono and stereo functions should be combined. */ + switch(channels) + { + case 0: /* 1 channel */ + outputsamples=decode_frame_mono(alac,outputbuffer,yield); + break; + case 1: /* 2 channels */ + outputsamples=decode_frame_stereo(alac,outputbuffer,yield); + break; + default: /* Unsupported */ + return -1; + } + + /* calculate consumed bytes */ + alac->bytes_consumed = (int)(alac->input_buffer - input_buffer_start); + alac->bytes_consumed += (alac->input_buffer_bitaccumulator>5) ? 2 : 1; + + return outputsamples; +} + +/* rockbox: not used +void create_alac(int samplesize, int numchannels, alac_file* alac) +{ + alac->samplesize = samplesize; + alac->numchannels = numchannels; + alac->bytespersample = (samplesize / 8) * numchannels; +} */ diff --git a/lib/rbcodec/codecs/libalac/decomp.h b/lib/rbcodec/codecs/libalac/decomp.h new file mode 100644 index 0000000000..21dabd86b0 --- /dev/null +++ b/lib/rbcodec/codecs/libalac/decomp.h @@ -0,0 +1,54 @@ +#ifndef __ALAC__DECOMP_H +#define __ALAC__DECOMP_H + +#ifndef ICODE_ATTR_ALAC +#define ICODE_ATTR_ALAC ICODE_ATTR +#endif + +/* Always output samples shifted to 28 bits + sign*/ +#define ALAC_OUTPUT_DEPTH 29 +#define SCALE16 (ALAC_OUTPUT_DEPTH - 16) +#define SCALE24 (ALAC_OUTPUT_DEPTH - 24) +#define ALAC_MAX_CHANNELS 2 +#define ALAC_BLOCKSIZE 4096 /* Number of samples per channel per block */ + +typedef struct +{ + unsigned char *input_buffer; + int input_buffer_bitaccumulator; /* used so we can do arbitary + bit reads */ + + /* rockbox: not used + int samplesize; + int numchannels; + int bytespersample; */ + + int bytes_consumed; + + /* stuff from setinfo */ + uint32_t setinfo_max_samples_per_frame; /* 0x1000 = 4096 */ /* max samples per frame? */ + uint8_t setinfo_7a; /* 0x00 */ + uint8_t setinfo_sample_size; /* 0x10 */ + uint8_t setinfo_rice_historymult; /* 0x28 */ + uint8_t setinfo_rice_initialhistory; /* 0x0a */ + uint8_t setinfo_rice_kmodifier; /* 0x0e */ + uint8_t setinfo_7f; /* 0x02 */ + uint16_t setinfo_80; /* 0x00ff */ + uint32_t setinfo_82; /* 0x000020e7 */ + uint32_t setinfo_86; /* 0x00069fe4 */ + uint32_t setinfo_8a_rate; /* 0x0000ac44 */ + /* end setinfo stuff */ +} alac_file; + +/* rockbox: not used +void create_alac(int samplesize, int numchannels, alac_file* alac) + ICODE_ATTR_ALAC; */ + +int alac_decode_frame(alac_file *alac, + unsigned char *inbuffer, + int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE], + void (*yield)(void)) ICODE_ATTR_ALAC; +void alac_set_info(alac_file *alac, char *inputbuffer) ICODE_ATTR_ALAC; + +#endif /* __ALAC__DECOMP_H */ + diff --git a/lib/rbcodec/codecs/libalac/libalac.make b/lib/rbcodec/codecs/libalac/libalac.make new file mode 100644 index 0000000000..8b8a842f8e --- /dev/null +++ b/lib/rbcodec/codecs/libalac/libalac.make @@ -0,0 +1,18 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id$ +# + +# libalac +ALACLIB := $(CODECDIR)/libalac.a +ALACLIB_SRC := $(call preprocess, $(RBCODECLIB_DIR)/codecs/libalac/SOURCES) +ALACLIB_OBJ := $(call c2obj, $(ALACLIB_SRC)) +OTHER_SRC += $(ALACLIB_SRC) + +$(ALACLIB): $(ALACLIB_OBJ) + $(SILENT)$(shell rm -f $@) + $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null -- cgit v1.2.3