summaryrefslogtreecommitdiffstats
path: root/apps/codecs/a52.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2005-06-22 19:41:30 +0000
committerDaniel Stenberg <daniel@haxx.se>2005-06-22 19:41:30 +0000
commit1dd672fe3226fa77113f35e4d72f50b863484c63 (patch)
tree67b424ab990f160dbc8fb238b9fa3390ceba10ed /apps/codecs/a52.c
parentb7aaa641b864628d76103b8c9d57c15747560ca7 (diff)
downloadrockbox-1dd672fe3226fa77113f35e4d72f50b863484c63.tar.gz
rockbox-1dd672fe3226fa77113f35e4d72f50b863484c63.zip
moved and renamed the codecs, gave the codecs a new extension (.codec),
unified to a single codec-only API, made a new codeclib, disabled the building of the *2wav plugins git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6812 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/a52.c')
-rw-r--r--apps/codecs/a52.c210
1 files changed, 210 insertions, 0 deletions
diff --git a/apps/codecs/a52.c b/apps/codecs/a52.c
new file mode 100644
index 0000000000..d35854e16e
--- /dev/null
+++ b/apps/codecs/a52.c
@@ -0,0 +1,210 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 Dave Chapman
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "codec.h"
+
+#include <inttypes.h> /* Needed by a52.h */
+#include <codecs/liba52/config-a52.h>
+#include <codecs/liba52/a52.h>
+
+#include "playback.h"
+#include "lib/codeclib.h"
+
+#define BUFFER_SIZE 4096
+
+struct codec_api* rb;
+struct codec_api* ci;
+
+static float gain = 1;
+static a52_state_t * state;
+unsigned long samplesdone;
+unsigned long frequency;
+
+/* Two buffers used outside liba52 */
+static uint8_t buf[3840] IDATA_ATTR;
+static int16_t int16_samples[256*2] IDATA_ATTR;
+
+static inline int16_t convert (int32_t i)
+{
+ i >>= 15;
+ return (i > 32767) ? 32767 : ((i < -32768) ? -32768 : i);
+}
+
+void output_audio(sample_t* samples,int flags) {
+ int i;
+
+ flags &= A52_CHANNEL_MASK | A52_LFE;
+
+ /* We may need to check the output format in flags - I'm not sure... */
+ for (i = 0; i < 256; i++) {
+ int16_samples[2*i] = convert (samples[i]);
+ int16_samples[2*i+1] = convert (samples[i+256]);
+ }
+
+ rb->yield();
+ while(!ci->audiobuffer_insert((unsigned char*)int16_samples,256*2*2))
+ rb->yield();
+}
+
+
+void a52_decode_data (uint8_t * start, uint8_t * end)
+{
+ static uint8_t * bufptr = buf;
+ static uint8_t * bufpos = buf + 7;
+
+ /*
+ * sample_rate and flags are static because this routine could
+ * exit between the a52_syncinfo() and the ao_setup(), and we want
+ * to have the same values when we get back !
+ */
+
+ static int sample_rate;
+ static int flags;
+ int bit_rate;
+ int len;
+
+ while (1) {
+ len = end - start;
+ if (!len)
+ break;
+ if (len > bufpos - bufptr)
+ len = bufpos - bufptr;
+ memcpy (bufptr, start, len);
+ bufptr += len;
+ start += len;
+ if (bufptr == bufpos) {
+ if (bufpos == buf + 7) {
+ int length;
+
+ length = a52_syncinfo (buf, &flags, &sample_rate, &bit_rate);
+ if (!length) {
+ DEBUGF("skip\n");
+ for (bufptr = buf; bufptr < buf + 6; bufptr++)
+ bufptr[0] = bufptr[1];
+ continue;
+ }
+ bufpos = buf + length;
+ } else {
+ // The following two defaults are taken from audio_out_oss.c:
+ level_t level;
+ sample_t bias;
+ int i;
+
+ /* This is the configuration for the downmixing: */
+ flags=A52_STEREO|A52_ADJUST_LEVEL|A52_LFE;
+ level=(1 << 26);
+ bias=0;
+
+ level = (level_t) (level * gain);
+
+ if (a52_frame (state, buf, &flags, &level, bias)) {
+ goto error;
+ }
+
+// file_info->frames_decoded++;
+
+// /* We assume this never changes */
+// file_info->samplerate=sample_rate;
+ frequency=sample_rate;
+
+ // An A52 frame consists of 6 blocks of 256 samples
+ // So we decode and output them one block at a time
+ for (i = 0; i < 6; i++) {
+ if (a52_block (state)) {
+ goto error;
+ }
+
+ output_audio(a52_samples (state),flags);
+ samplesdone+=256;
+ }
+ ci->set_elapsed(samplesdone/(frequency/1000));
+ bufptr = buf;
+ bufpos = buf + 7;
+ continue;
+
+ error:
+
+ //logf("Error decoding A52 stream\n");
+ bufptr = buf;
+ bufpos = buf + 7;
+ }
+ }
+ }
+}
+
+#ifndef SIMULATOR
+extern char iramcopy[];
+extern char iramstart[];
+extern char iramend[];
+#endif
+
+/* this is the codec entry point */
+enum codec_status codec_start(struct codec_api* api, void* parm)
+{
+ size_t n;
+ unsigned char* filebuf;
+
+ /* Generic codec initialisation */
+ TEST_CODEC_API(api);
+
+ rb = api;
+ ci = (struct codec_api*)api;
+
+#ifndef SIMULATOR
+ rb->memcpy(iramstart, iramcopy, iramend-iramstart);
+#endif
+
+ ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2));
+ ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*128));
+
+ next_track:
+
+ if (codec_init(api)) {
+ return CODEC_ERROR;
+ }
+
+ /* Intialise the A52 decoder and check for success */
+ state = a52_init (0); // Parameter is "accel"
+
+ /* The main decoding loop */
+
+ samplesdone=0;
+ while (1) {
+ if (ci->stop_codec || ci->reload_codec) {
+ break;
+ }
+
+ filebuf=ci->request_buffer(&n,BUFFER_SIZE);
+
+ if (n==0) { /* End of Stream */
+ break;
+ }
+
+ a52_decode_data(filebuf,filebuf+n);
+
+ ci->advance_buffer(n);
+ }
+
+ if (ci->request_next_track())
+ goto next_track;
+
+//NOT NEEDED??: a52_free (state);
+
+ return CODEC_OK;
+}