Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id: |
| 9 | * |
| 10 | * Copyright (C) 2005 Mark Arigo |
| 11 | * |
Daniel Stenberg | 2acc0ac | 2008-06-28 18:10:04 +0000 | [diff] [blame^] | 12 | * This program is free software; you can redistribute it and/or |
| 13 | * modify it under the terms of the GNU General Public License |
| 14 | * as published by the Free Software Foundation; either version 2 |
| 15 | * of the License, or (at your option) any later version. |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 16 | * |
| 17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 18 | * KIND, either express or implied. |
| 19 | * |
| 20 | ****************************************************************************/ |
| 21 | |
| 22 | #include "codeclib.h" |
| 23 | #include <codecs/libffmpegFLAC/shndec.h> |
| 24 | |
Tomasz Malesinski | 80da8b1 | 2006-11-26 18:31:41 +0000 | [diff] [blame] | 25 | CODEC_HEADER |
| 26 | |
Tomasz Malesinski | 5c54ba4 | 2006-11-09 21:59:27 +0000 | [diff] [blame] | 27 | #ifndef IBSS_ATTR_SHORTEN_DECODED0 |
| 28 | #define IBSS_ATTR_SHORTEN_DECODED0 IBSS_ATTR |
| 29 | #endif |
| 30 | |
Tomasz Malesinski | 5c54ba4 | 2006-11-09 21:59:27 +0000 | [diff] [blame] | 31 | int32_t decoded0[MAX_DECODE_SIZE] IBSS_ATTR_SHORTEN_DECODED0; |
Dave Chapman | 8e46ab8 | 2006-02-07 22:16:35 +0000 | [diff] [blame] | 32 | int32_t decoded1[MAX_DECODE_SIZE] IBSS_ATTR; |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 33 | |
Dave Chapman | 8e46ab8 | 2006-02-07 22:16:35 +0000 | [diff] [blame] | 34 | int32_t offset0[MAX_OFFSET_SIZE] IBSS_ATTR; |
| 35 | int32_t offset1[MAX_OFFSET_SIZE] IBSS_ATTR; |
| 36 | |
| 37 | int8_t ibuf[MAX_BUFFER_SIZE] IBSS_ATTR; |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 38 | |
| 39 | /* this is the codec entry point */ |
Tomasz Malesinski | 80da8b1 | 2006-11-26 18:31:41 +0000 | [diff] [blame] | 40 | enum codec_status codec_main(void) |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 41 | { |
| 42 | ShortenContext sc; |
| 43 | uint32_t samplesdone; |
| 44 | uint32_t elapsedtime; |
| 45 | int8_t *buf; |
Dave Chapman | 8e46ab8 | 2006-02-07 22:16:35 +0000 | [diff] [blame] | 46 | int consumed, res, nsamples; |
Brandon Low | c76904b | 2006-03-24 14:02:27 +0000 | [diff] [blame] | 47 | size_t bytesleft; |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 48 | |
| 49 | /* Generic codec initialisation */ |
Michael Sevakis | 97f369a | 2007-02-10 16:34:16 +0000 | [diff] [blame] | 50 | ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512); |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 51 | |
Michael Sevakis | 97f369a | 2007-02-10 16:34:16 +0000 | [diff] [blame] | 52 | ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); |
| 53 | ci->configure(DSP_SET_SAMPLE_DEPTH, SHN_OUTPUT_DEPTH-1); |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 54 | |
| 55 | next_track: |
| 56 | /* Codec initialization */ |
Tomasz Malesinski | 80da8b1 | 2006-11-26 18:31:41 +0000 | [diff] [blame] | 57 | if (codec_init()) { |
Dave Chapman | 8e46ab8 | 2006-02-07 22:16:35 +0000 | [diff] [blame] | 58 | LOGF("Shorten: codec_init error\n"); |
| 59 | return CODEC_ERROR; |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 60 | } |
| 61 | |
| 62 | while (!*ci->taginfo_ready) |
| 63 | ci->yield(); |
| 64 | |
Michael Sevakis | 9b9e227 | 2007-02-26 17:15:04 +0000 | [diff] [blame] | 65 | codec_set_replaygain(ci->id3); |
| 66 | |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 67 | /* Shorten decoder initialization */ |
| 68 | ci->memset(&sc, 0, sizeof(ShortenContext)); |
| 69 | |
Dave Chapman | c01775f | 2005-11-13 11:04:02 +0000 | [diff] [blame] | 70 | /* Skip id3v2 tags */ |
Brandon Low | b46175c | 2007-11-05 18:16:13 +0000 | [diff] [blame] | 71 | ci->seek_buffer(ci->id3->first_frame_offset); |
Dave Chapman | c01775f | 2005-11-13 11:04:02 +0000 | [diff] [blame] | 72 | |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 73 | /* Read the shorten & wave headers */ |
Dave Chapman | 8e46ab8 | 2006-02-07 22:16:35 +0000 | [diff] [blame] | 74 | buf = ci->request_buffer(&bytesleft, MAX_HEADER_SIZE); |
Daniel Stenberg | 76667e2 | 2005-12-02 08:42:48 +0000 | [diff] [blame] | 75 | res = shorten_init(&sc, (unsigned char *)buf, bytesleft); |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 76 | if (res < 0) { |
Dave Chapman | 8e46ab8 | 2006-02-07 22:16:35 +0000 | [diff] [blame] | 77 | LOGF("Shorten: shorten_init error: %d\n", res); |
| 78 | return CODEC_ERROR; |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 79 | } |
| 80 | |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 81 | ci->id3->frequency = sc.sample_rate; |
Michael Sevakis | 97f369a | 2007-02-10 16:34:16 +0000 | [diff] [blame] | 82 | ci->configure(DSP_SWITCH_FREQUENCY, sc.sample_rate); |
Dave Chapman | c01775f | 2005-11-13 11:04:02 +0000 | [diff] [blame] | 83 | |
| 84 | if (sc.sample_rate) { |
| 85 | ci->id3->length = (sc.totalsamples / sc.sample_rate) * 1000; |
| 86 | } else { |
| 87 | ci->id3->length = 0; |
| 88 | } |
| 89 | |
| 90 | if (ci->id3->length) { |
| 91 | ci->id3->bitrate = (ci->id3->filesize * 8) / ci->id3->length; |
| 92 | } |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 93 | |
| 94 | consumed = sc.gb.index/8; |
| 95 | ci->advance_buffer(consumed); |
| 96 | sc.bitindex = sc.gb.index - 8*consumed; |
| 97 | |
| 98 | seek_start: |
| 99 | /* The main decoding loop */ |
Dave Chapman | 8e46ab8 | 2006-02-07 22:16:35 +0000 | [diff] [blame] | 100 | ci->memset(&decoded0, 0, sizeof(int32_t)*MAX_DECODE_SIZE); |
| 101 | ci->memset(&decoded1, 0, sizeof(int32_t)*MAX_DECODE_SIZE); |
| 102 | ci->memset(&offset0, 0, sizeof(int32_t)*MAX_OFFSET_SIZE); |
| 103 | ci->memset(&offset1, 0, sizeof(int32_t)*MAX_OFFSET_SIZE); |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 104 | |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 105 | samplesdone = 0; |
Dave Chapman | 8e46ab8 | 2006-02-07 22:16:35 +0000 | [diff] [blame] | 106 | buf = ci->request_buffer(&bytesleft, MAX_BUFFER_SIZE); |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 107 | while (bytesleft) { |
| 108 | ci->yield(); |
Brandon Low | ebadcc6 | 2006-04-15 02:03:11 +0000 | [diff] [blame] | 109 | if (ci->stop_codec || ci->new_track) { |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 110 | break; |
| 111 | } |
| 112 | |
| 113 | /* Seek to start of track */ |
| 114 | if (ci->seek_time == 1) { |
Dave Chapman | c01775f | 2005-11-13 11:04:02 +0000 | [diff] [blame] | 115 | if (ci->seek_buffer(sc.header_bits/8 + ci->id3->first_frame_offset)) { |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 116 | sc.bitindex = sc.header_bits - 8*(sc.header_bits/8); |
| 117 | ci->set_elapsed(0); |
| 118 | ci->seek_complete(); |
| 119 | goto seek_start; |
| 120 | } |
| 121 | ci->seek_complete(); |
| 122 | } |
| 123 | |
| 124 | /* Decode a frame */ |
Dave Chapman | 8e46ab8 | 2006-02-07 22:16:35 +0000 | [diff] [blame] | 125 | ci->memcpy(ibuf, buf, bytesleft); /* copy buf to iram */ |
| 126 | res = shorten_decode_frames(&sc, &nsamples, decoded0, decoded1, |
| 127 | offset0, offset1, (unsigned char *)ibuf, |
| 128 | bytesleft, ci->yield); |
| 129 | |
| 130 | if (res == FN_ERROR) { |
Magnus Holmgren | 01a010f | 2007-03-18 09:50:53 +0000 | [diff] [blame] | 131 | LOGF("Shorten: shorten_decode_frames error (%ld)\n", samplesdone); |
Brandon Low | f3bc1ef | 2006-04-22 14:40:13 +0000 | [diff] [blame] | 132 | break; |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 133 | } else { |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 134 | /* Insert decoded samples in pcmbuf */ |
Dave Chapman | 8e46ab8 | 2006-02-07 22:16:35 +0000 | [diff] [blame] | 135 | if (nsamples) { |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 136 | ci->yield(); |
Michael Sevakis | aba6ca0 | 2007-02-07 00:51:50 +0000 | [diff] [blame] | 137 | ci->pcmbuf_insert(decoded0 + sc.nwrap, decoded1 + sc.nwrap, |
| 138 | nsamples); |
Dave Chapman | 8e46ab8 | 2006-02-07 22:16:35 +0000 | [diff] [blame] | 139 | |
| 140 | /* Update the elapsed-time indicator */ |
| 141 | samplesdone += nsamples; |
| 142 | elapsedtime = (samplesdone*10) / (sc.sample_rate/100); |
| 143 | ci->set_elapsed(elapsedtime); |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 144 | } |
| 145 | |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 146 | /* End of shorten stream...go to next track */ |
Dave Chapman | 8e46ab8 | 2006-02-07 22:16:35 +0000 | [diff] [blame] | 147 | if (res == FN_QUIT) |
| 148 | break; |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 149 | } |
| 150 | |
| 151 | consumed = sc.gb.index/8; |
| 152 | ci->advance_buffer(consumed); |
Dave Chapman | 8e46ab8 | 2006-02-07 22:16:35 +0000 | [diff] [blame] | 153 | buf = ci->request_buffer(&bytesleft, MAX_BUFFER_SIZE); |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 154 | sc.bitindex = sc.gb.index - 8*consumed; |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 155 | } |
| 156 | |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 157 | if (ci->request_next_track()) |
| 158 | goto next_track; |
| 159 | |
Dave Chapman | 8e46ab8 | 2006-02-07 22:16:35 +0000 | [diff] [blame] | 160 | return CODEC_OK; |
Dave Chapman | 2bf9be1 | 2005-11-11 19:45:36 +0000 | [diff] [blame] | 161 | } |