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/demac/libdemac/decoder.c | 216 ++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 lib/rbcodec/codecs/demac/libdemac/decoder.c (limited to 'lib/rbcodec/codecs/demac/libdemac/decoder.c') diff --git a/lib/rbcodec/codecs/demac/libdemac/decoder.c b/lib/rbcodec/codecs/demac/libdemac/decoder.c new file mode 100644 index 0000000000..b0339a75d9 --- /dev/null +++ b/lib/rbcodec/codecs/demac/libdemac/decoder.c @@ -0,0 +1,216 @@ +/* + +libdemac - A Monkey's Audio decoder + +$Id$ + +Copyright (C) Dave Chapman 2007 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA + +*/ + +#include +#include + +#include "demac.h" +#include "predictor.h" +#include "entropy.h" +#include "filter.h" +#include "demac_config.h" + +/* Statically allocate the filter buffers */ + +#ifdef FILTER256_IRAM +static filter_int filterbuf32[(32*3 + FILTER_HISTORY_SIZE) * 2] + IBSS_ATTR_DEMAC MEM_ALIGN_ATTR; + /* 2432 or 4864 bytes */ +static filter_int filterbuf256[(256*3 + FILTER_HISTORY_SIZE) * 2] + IBSS_ATTR_DEMAC MEM_ALIGN_ATTR; + /* 5120 or 10240 bytes */ +#define FILTERBUF64 filterbuf256 +#define FILTERBUF32 filterbuf32 +#define FILTERBUF16 filterbuf32 +#else +static filter_int filterbuf64[(64*3 + FILTER_HISTORY_SIZE) * 2] + IBSS_ATTR_DEMAC MEM_ALIGN_ATTR; + /* 2432 or 4864 bytes */ +static filter_int filterbuf256[(256*3 + FILTER_HISTORY_SIZE) * 2] + MEM_ALIGN_ATTR; /* 5120 or 10240 bytes */ +#define FILTERBUF64 filterbuf64 +#define FILTERBUF32 filterbuf64 +#define FILTERBUF16 filterbuf64 +#endif + +/* This is only needed for "insane" files, and no current Rockbox targets + can hope to decode them in realtime, except the Gigabeat S (at 528MHz). */ +static filter_int filterbuf1280[(1280*3 + FILTER_HISTORY_SIZE) * 2] + IBSS_ATTR_DEMAC_INSANEBUF MEM_ALIGN_ATTR; + /* 17408 or 34816 bytes */ + +void init_frame_decoder(struct ape_ctx_t* ape_ctx, + unsigned char* inbuffer, int* firstbyte, + int* bytesconsumed) +{ + init_entropy_decoder(ape_ctx, inbuffer, firstbyte, bytesconsumed); + //printf("CRC=0x%08x\n",ape_ctx->CRC); + //printf("Flags=0x%08x\n",ape_ctx->frameflags); + + init_predictor_decoder(&ape_ctx->predictor); + + switch (ape_ctx->compressiontype) + { + case 2000: + init_filter_16_11(FILTERBUF16); + break; + + case 3000: + init_filter_64_11(FILTERBUF64); + break; + + case 4000: + init_filter_256_13(filterbuf256); + init_filter_32_10(FILTERBUF32); + break; + + case 5000: + init_filter_1280_15(filterbuf1280); + init_filter_256_13(filterbuf256); + init_filter_16_11(FILTERBUF32); + } +} + +int ICODE_ATTR_DEMAC decode_chunk(struct ape_ctx_t* ape_ctx, + unsigned char* inbuffer, int* firstbyte, + int* bytesconsumed, + int32_t* decoded0, int32_t* decoded1, + int count) +{ + int32_t left, right; +#ifdef ROCKBOX + int scale = (APE_OUTPUT_DEPTH - ape_ctx->bps); + #define SCALE(x) ((x) << scale) +#else + #define SCALE(x) (x) +#endif + + if ((ape_ctx->channels==1) || ((ape_ctx->frameflags + & (APE_FRAMECODE_PSEUDO_STEREO|APE_FRAMECODE_STEREO_SILENCE)) + == APE_FRAMECODE_PSEUDO_STEREO)) { + + entropy_decode(ape_ctx, inbuffer, firstbyte, bytesconsumed, + decoded0, NULL, count); + + if (ape_ctx->frameflags & APE_FRAMECODE_MONO_SILENCE) { + /* We are pure silence, so we're done. */ + return 0; + } + + switch (ape_ctx->compressiontype) + { + case 2000: + apply_filter_16_11(ape_ctx->fileversion,0,decoded0,count); + break; + + case 3000: + apply_filter_64_11(ape_ctx->fileversion,0,decoded0,count); + break; + + case 4000: + apply_filter_32_10(ape_ctx->fileversion,0,decoded0,count); + apply_filter_256_13(ape_ctx->fileversion,0,decoded0,count); + break; + + case 5000: + apply_filter_16_11(ape_ctx->fileversion,0,decoded0,count); + apply_filter_256_13(ape_ctx->fileversion,0,decoded0,count); + apply_filter_1280_15(ape_ctx->fileversion,0,decoded0,count); + } + + /* Now apply the predictor decoding */ + predictor_decode_mono(&ape_ctx->predictor,decoded0,count); + + if (ape_ctx->channels==2) { + /* Pseudo-stereo - copy left channel to right channel */ + while (count--) + { + left = *decoded0; + *(decoded1++) = *(decoded0++) = SCALE(left); + } + } +#ifdef ROCKBOX + else { + /* Scale to output depth */ + while (count--) + { + left = *decoded0; + *(decoded0++) = SCALE(left); + } + } +#endif + } else { /* Stereo */ + entropy_decode(ape_ctx, inbuffer, firstbyte, bytesconsumed, + decoded0, decoded1, count); + + if ((ape_ctx->frameflags & APE_FRAMECODE_STEREO_SILENCE) + == APE_FRAMECODE_STEREO_SILENCE) { + /* We are pure silence, so we're done. */ + return 0; + } + + /* Apply filters - compression type 1000 doesn't have any */ + switch (ape_ctx->compressiontype) + { + case 2000: + apply_filter_16_11(ape_ctx->fileversion,0,decoded0,count); + apply_filter_16_11(ape_ctx->fileversion,1,decoded1,count); + break; + + case 3000: + apply_filter_64_11(ape_ctx->fileversion,0,decoded0,count); + apply_filter_64_11(ape_ctx->fileversion,1,decoded1,count); + break; + + case 4000: + apply_filter_32_10(ape_ctx->fileversion,0,decoded0,count); + apply_filter_32_10(ape_ctx->fileversion,1,decoded1,count); + apply_filter_256_13(ape_ctx->fileversion,0,decoded0,count); + apply_filter_256_13(ape_ctx->fileversion,1,decoded1,count); + break; + + case 5000: + apply_filter_16_11(ape_ctx->fileversion,0,decoded0,count); + apply_filter_16_11(ape_ctx->fileversion,1,decoded1,count); + apply_filter_256_13(ape_ctx->fileversion,0,decoded0,count); + apply_filter_256_13(ape_ctx->fileversion,1,decoded1,count); + apply_filter_1280_15(ape_ctx->fileversion,0,decoded0,count); + apply_filter_1280_15(ape_ctx->fileversion,1,decoded1,count); + } + + /* Now apply the predictor decoding */ + predictor_decode_stereo(&ape_ctx->predictor,decoded0,decoded1,count); + + /* Decorrelate and scale to output depth */ + while (count--) + { + left = *decoded1 - (*decoded0 / 2); + right = left + *decoded0; + + *(decoded0++) = SCALE(left); + *(decoded1++) = SCALE(right); + } + } + return 0; +} -- cgit v1.2.3