blob: d2ae7bd6c33a2a4ecb65b5fa660f0761d4274f36 [file] [log] [blame]
Dave Chapman3c2c2f52005-06-10 18:08:08 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 Dave Chapman
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
Daniel Stenberg1dd672f2005-06-22 19:41:30 +000020#include "codec.h"
Dave Chapman3c2c2f52005-06-10 18:08:08 +000021#include "playback.h"
22#include "lib/codeclib.h"
Miika Pekkarinend8cb7032005-06-26 19:41:29 +000023#include "dsp.h"
Dave Chapman3c2c2f52005-06-10 18:08:08 +000024
Dave Chapmanab815022005-06-10 19:12:58 +000025#define BYTESWAP(x) (((x>>8) & 0xff) | ((x<<8) & 0xff00))
26
27/* Number of bytes to process in one iteration */
Miika Pekkarinen7e0b6882005-06-10 19:26:34 +000028#define WAV_CHUNK_SIZE (1024*4)
Dave Chapmanab815022005-06-10 19:12:58 +000029
Dave Chapman3c2c2f52005-06-10 18:08:08 +000030#ifndef SIMULATOR
31extern char iramcopy[];
32extern char iramstart[];
33extern char iramend[];
34#endif
35
Daniel Stenberg1dd672f2005-06-22 19:41:30 +000036/* this is the codec entry point */
Daniel Stenberg31efab42005-06-22 19:55:09 +000037enum codec_status codec_start(struct codec_api* api)
Dave Chapman3c2c2f52005-06-10 18:08:08 +000038{
Daniel Stenberg1dd672f2005-06-22 19:41:30 +000039 struct codec_api* rb = api;
40 struct codec_api* ci = api;
Dave Chapman3c2c2f52005-06-10 18:08:08 +000041 unsigned long samplerate,numbytes,totalsamples,samplesdone,nsamples;
42 int channels,bytespersample,bitspersample;
Dave Chapmanab815022005-06-10 19:12:58 +000043 unsigned int i;
44 size_t n;
Dave Chapman3c2c2f52005-06-10 18:08:08 +000045 int endofstream;
Dave Chapmanab815022005-06-10 19:12:58 +000046 unsigned char* header;
47 unsigned short* wavbuf;
Dave Chapman3c2c2f52005-06-10 18:08:08 +000048
Daniel Stenberg1dd672f2005-06-22 19:41:30 +000049 /* Generic codec initialisation */
50 TEST_CODEC_API(api);
Dave Chapman3c2c2f52005-06-10 18:08:08 +000051
52 /* if you are using a global api pointer, don't forget to copy it!
53 otherwise you will get lovely "I04: IllInstr" errors... :-) */
54 rb = api;
55
56#ifndef SIMULATOR
57 rb->memcpy(iramstart, iramcopy, iramend-iramstart);
58#endif
59
60 ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*10));
61 ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512));
Miika Pekkarinen7e0b6882005-06-10 19:26:34 +000062 ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*256));
Dave Chapman3c2c2f52005-06-10 18:08:08 +000063
Miika Pekkarinend8cb7032005-06-26 19:41:29 +000064 ci->configure(DSP_DITHER, (bool *)false);
65 ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_INTERLEAVED);
66 ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(16));
67
Dave Chapman3c2c2f52005-06-10 18:08:08 +000068 next_track:
69
Daniel Stenberg1dd672f2005-06-22 19:41:30 +000070 if (codec_init(api)) {
71 return CODEC_ERROR;
Dave Chapman3c2c2f52005-06-10 18:08:08 +000072 }
73
Miika Pekkarinen159c52d2005-08-20 11:13:19 +000074 while (!*rb->taginfo_ready)
Miika Pekkarinend8cb7032005-06-26 19:41:29 +000075 rb->yield();
Miika Pekkarinen159c52d2005-08-20 11:13:19 +000076
77 /* Always enable DSP to support voice ui. */
78 rb->configure(CODEC_DSP_ENABLE, (bool *)true);
79 rb->configure(DSP_SET_FREQUENCY, (long *)(rb->id3->frequency));
Miika Pekkarinend8cb7032005-06-26 19:41:29 +000080
Dave Chapman3c2c2f52005-06-10 18:08:08 +000081 /* FIX: Correctly parse WAV header - we assume canonical 44-byte header */
82
Dave Chapmanab815022005-06-10 19:12:58 +000083 header=ci->request_buffer(&n,44);
Dave Chapman3c2c2f52005-06-10 18:08:08 +000084 if (n!=44) {
Daniel Stenberg1dd672f2005-06-22 19:41:30 +000085 return CODEC_ERROR;
Dave Chapman3c2c2f52005-06-10 18:08:08 +000086 }
Dave Chapmanab815022005-06-10 19:12:58 +000087 if ((memcmp(header,"RIFF",4)!=0) || (memcmp(&header[8],"WAVEfmt",7)!=0)) {
Daniel Stenberg1dd672f2005-06-22 19:41:30 +000088 return CODEC_ERROR;
Dave Chapman3c2c2f52005-06-10 18:08:08 +000089 }
90
Dave Chapmanab815022005-06-10 19:12:58 +000091 samplerate=header[24]|(header[25]<<8)|(header[26]<<16)|(header[27]<<24);
92 bitspersample=header[34];
93 channels=header[22];
Dave Chapman3c2c2f52005-06-10 18:08:08 +000094 bytespersample=((bitspersample/8)*channels);
Dave Chapmanab815022005-06-10 19:12:58 +000095 numbytes=(header[40]|(header[41]<<8)|(header[42]<<16)|(header[43]<<24));
Dave Chapman3c2c2f52005-06-10 18:08:08 +000096 totalsamples=numbytes/bytespersample;
97
98 if ((bitspersample!=16) || (channels != 2)) {
Daniel Stenberg1dd672f2005-06-22 19:41:30 +000099 return CODEC_ERROR;
Dave Chapman3c2c2f52005-06-10 18:08:08 +0000100 }
Dave Chapmanab815022005-06-10 19:12:58 +0000101
102 ci->advance_buffer(44);
103
Dave Chapman3c2c2f52005-06-10 18:08:08 +0000104 /* The main decoder loop */
105
106 samplesdone=0;
107 ci->set_elapsed(0);
108 endofstream=0;
109 while (!endofstream) {
Dave Chapman3c2c2f52005-06-10 18:08:08 +0000110 if (ci->stop_codec || ci->reload_codec) {
111 break;
112 }
113
Dave Chapmanab815022005-06-10 19:12:58 +0000114 wavbuf=ci->request_buffer(&n,WAV_CHUNK_SIZE);
Dave Chapman3c2c2f52005-06-10 18:08:08 +0000115
116 if (n==0) break; /* End of stream */
117
118 nsamples=(n/bytespersample);
119
120 /* WAV files can contain extra data at the end - so we can't just
121 process until the end of the file */
122
123 if (samplesdone+nsamples > totalsamples) {
124 nsamples=(totalsamples-samplesdone);
125 n=nsamples*bytespersample;
126 endofstream=1;
127 }
128
129 /* Byte-swap data */
Dave Chapmanab815022005-06-10 19:12:58 +0000130 for (i=0;i<n/2;i++) {
Miika Pekkarinend8cb7032005-06-26 19:41:29 +0000131 wavbuf[i]=SWAB16(wavbuf[i]);
Dave Chapman3c2c2f52005-06-10 18:08:08 +0000132 }
133
134 samplesdone+=nsamples;
135 ci->set_elapsed(samplesdone/(ci->id3->frequency/1000));
136
Miika Pekkarinen7e0b6882005-06-10 19:26:34 +0000137 rb->yield();
Miika Pekkarinen20b38972005-07-13 12:48:22 +0000138 while (!ci->pcmbuf_insert((unsigned char*)wavbuf, n))
Dave Chapman3c2c2f52005-06-10 18:08:08 +0000139 rb->yield();
Dave Chapmanab815022005-06-10 19:12:58 +0000140
141 ci->advance_buffer(n);
Dave Chapman3c2c2f52005-06-10 18:08:08 +0000142 }
143
144 if (ci->request_next_track())
145 goto next_track;
146
Daniel Stenberg1dd672f2005-06-22 19:41:30 +0000147 return CODEC_OK;
Dave Chapman3c2c2f52005-06-10 18:08:08 +0000148}