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/alac.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 lib/rbcodec/codecs/alac.c (limited to 'lib/rbcodec/codecs/alac.c') diff --git a/lib/rbcodec/codecs/alac.c b/lib/rbcodec/codecs/alac.c new file mode 100644 index 0000000000..144d796e5f --- /dev/null +++ b/lib/rbcodec/codecs/alac.c @@ -0,0 +1,146 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2005 Dave Chapman + * + * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "codeclib.h" +#include "libm4a/m4a.h" +#include "libalac/decomp.h" + +CODEC_HEADER + +/* The maximum buffer size handled. This amount of bytes is buffered for each + * frame. */ +#define ALAC_BYTE_BUFFER_SIZE 32768 + +static int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE] IBSS_ATTR; + +/* this is the codec entry point */ +enum codec_status codec_main(enum codec_entry_call_reason reason) +{ + if (reason == CODEC_LOAD) { + /* Generic codec initialisation */ + ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); + ci->configure(DSP_SET_SAMPLE_DEPTH, ALAC_OUTPUT_DEPTH-1); + } + + return CODEC_OK; +} + +/* this is called for each file to process */ +enum codec_status codec_run(void) +{ + size_t n; + demux_res_t demux_res; + stream_t input_stream; + uint32_t samplesdone; + uint32_t elapsedtime = 0; + int samplesdecoded; + unsigned int i; + unsigned char* buffer; + alac_file alac; + intptr_t param; + + /* Clean and initialize decoder structures */ + memset(&demux_res , 0, sizeof(demux_res)); + if (codec_init()) { + LOGF("ALAC: Error initialising codec\n"); + return CODEC_ERROR; + } + + ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); + codec_set_replaygain(ci->id3); + + ci->seek_buffer(0); + + stream_create(&input_stream,ci); + + /* Read from ci->id3->offset before calling qtmovie_read. */ + samplesdone = (uint32_t)(((uint64_t)(ci->id3->offset) * ci->id3->frequency) / + (ci->id3->bitrate*128)); + + /* if qtmovie_read returns successfully, the stream is up to + * the movie data, which can be used directly by the decoder */ + if (!qtmovie_read(&input_stream, &demux_res)) { + LOGF("ALAC: Error initialising file\n"); + return CODEC_ERROR; + } + + /* initialise the sound converter */ + alac_set_info(&alac, demux_res.codecdata); + + /* Set i for first frame, seek to desired sample position for resuming. */ + i=0; + if (samplesdone > 0) { + if (m4a_seek(&demux_res, &input_stream, samplesdone, + &samplesdone, (int*) &i)) { + elapsedtime = (samplesdone * 10) / (ci->id3->frequency / 100); + ci->set_elapsed(elapsedtime); + } else { + samplesdone = 0; + } + } + + ci->set_elapsed(elapsedtime); + + /* The main decoding loop */ + while (i < demux_res.num_sample_byte_sizes) { + enum codec_command_action action = ci->get_command(¶m); + + if (action == CODEC_ACTION_HALT) + break; + + /* Request the required number of bytes from the input buffer */ + buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE); + + /* Deal with any pending seek requests */ + if (action == CODEC_ACTION_SEEK_TIME) { + if (m4a_seek(&demux_res, &input_stream, + (param/10) * (ci->id3->frequency/100), + &samplesdone, (int *)&i)) { + elapsedtime=(samplesdone*10)/(ci->id3->frequency/100); + } + ci->set_elapsed(elapsedtime); + ci->seek_complete(); + } + + /* Request the required number of bytes from the input buffer */ + buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE); + + /* Decode one block - returned samples will be host-endian */ + samplesdecoded=alac_decode_frame(&alac, buffer, outputbuffer, ci->yield); + ci->yield(); + + /* Advance codec buffer by amount of consumed bytes */ + ci->advance_buffer(alac.bytes_consumed); + + /* Output the audio */ + ci->pcmbuf_insert(outputbuffer[0], outputbuffer[1], samplesdecoded); + + /* Update the elapsed-time indicator */ + samplesdone+=samplesdecoded; + elapsedtime=(samplesdone*10)/(ci->id3->frequency/100); + ci->set_elapsed(elapsedtime); + + i++; + } + + LOGF("ALAC: Decoded %lu samples\n",(unsigned long)samplesdone); + return CODEC_OK; +} -- cgit v1.2.3