2005-06-10 18:08:08 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2005-06-22 19:41:30 +00:00
|
|
|
#include "codec.h"
|
2005-06-10 18:08:08 +00:00
|
|
|
#include "playback.h"
|
|
|
|
#include "lib/codeclib.h"
|
2005-06-26 19:41:29 +00:00
|
|
|
#include "dsp.h"
|
2005-06-10 18:08:08 +00:00
|
|
|
|
2005-06-10 19:12:58 +00:00
|
|
|
#define BYTESWAP(x) (((x>>8) & 0xff) | ((x<<8) & 0xff00))
|
|
|
|
|
|
|
|
/* Number of bytes to process in one iteration */
|
2005-06-10 19:26:34 +00:00
|
|
|
#define WAV_CHUNK_SIZE (1024*4)
|
2005-06-10 19:12:58 +00:00
|
|
|
|
2005-06-10 18:08:08 +00:00
|
|
|
#ifndef SIMULATOR
|
|
|
|
extern char iramcopy[];
|
|
|
|
extern char iramstart[];
|
|
|
|
extern char iramend[];
|
|
|
|
#endif
|
|
|
|
|
2005-06-22 19:41:30 +00:00
|
|
|
/* this is the codec entry point */
|
2005-06-22 19:55:09 +00:00
|
|
|
enum codec_status codec_start(struct codec_api* api)
|
2005-06-10 18:08:08 +00:00
|
|
|
{
|
2005-06-22 19:41:30 +00:00
|
|
|
struct codec_api* rb = api;
|
|
|
|
struct codec_api* ci = api;
|
2005-06-10 18:08:08 +00:00
|
|
|
unsigned long samplerate,numbytes,totalsamples,samplesdone,nsamples;
|
|
|
|
int channels,bytespersample,bitspersample;
|
2005-06-10 19:12:58 +00:00
|
|
|
unsigned int i;
|
|
|
|
size_t n;
|
2005-06-10 18:08:08 +00:00
|
|
|
int endofstream;
|
2005-06-10 19:12:58 +00:00
|
|
|
unsigned char* header;
|
|
|
|
unsigned short* wavbuf;
|
2005-06-10 18:08:08 +00:00
|
|
|
|
2005-06-22 19:41:30 +00:00
|
|
|
/* Generic codec initialisation */
|
|
|
|
TEST_CODEC_API(api);
|
2005-06-10 18:08:08 +00:00
|
|
|
|
|
|
|
/* if you are using a global api pointer, don't forget to copy it!
|
|
|
|
otherwise you will get lovely "I04: IllInstr" errors... :-) */
|
|
|
|
rb = api;
|
|
|
|
|
|
|
|
#ifndef SIMULATOR
|
|
|
|
rb->memcpy(iramstart, iramcopy, iramend-iramstart);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*10));
|
|
|
|
ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512));
|
2005-06-10 19:26:34 +00:00
|
|
|
ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*256));
|
2005-06-10 18:08:08 +00:00
|
|
|
|
2005-06-26 19:41:29 +00:00
|
|
|
ci->configure(DSP_DITHER, (bool *)false);
|
|
|
|
ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_INTERLEAVED);
|
|
|
|
ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(16));
|
|
|
|
|
2005-06-10 18:08:08 +00:00
|
|
|
next_track:
|
|
|
|
|
2005-06-22 19:41:30 +00:00
|
|
|
if (codec_init(api)) {
|
|
|
|
return CODEC_ERROR;
|
2005-06-10 18:08:08 +00:00
|
|
|
}
|
|
|
|
|
2005-08-20 11:13:19 +00:00
|
|
|
while (!*rb->taginfo_ready)
|
2005-06-26 19:41:29 +00:00
|
|
|
rb->yield();
|
2005-08-20 11:13:19 +00:00
|
|
|
|
|
|
|
/* Always enable DSP to support voice ui. */
|
|
|
|
rb->configure(CODEC_DSP_ENABLE, (bool *)true);
|
|
|
|
rb->configure(DSP_SET_FREQUENCY, (long *)(rb->id3->frequency));
|
2005-06-26 19:41:29 +00:00
|
|
|
|
2005-06-10 18:08:08 +00:00
|
|
|
/* FIX: Correctly parse WAV header - we assume canonical 44-byte header */
|
|
|
|
|
2005-06-10 19:12:58 +00:00
|
|
|
header=ci->request_buffer(&n,44);
|
2005-06-10 18:08:08 +00:00
|
|
|
if (n!=44) {
|
2005-06-22 19:41:30 +00:00
|
|
|
return CODEC_ERROR;
|
2005-06-10 18:08:08 +00:00
|
|
|
}
|
2005-06-10 19:12:58 +00:00
|
|
|
if ((memcmp(header,"RIFF",4)!=0) || (memcmp(&header[8],"WAVEfmt",7)!=0)) {
|
2005-06-22 19:41:30 +00:00
|
|
|
return CODEC_ERROR;
|
2005-06-10 18:08:08 +00:00
|
|
|
}
|
|
|
|
|
2005-06-10 19:12:58 +00:00
|
|
|
samplerate=header[24]|(header[25]<<8)|(header[26]<<16)|(header[27]<<24);
|
|
|
|
bitspersample=header[34];
|
|
|
|
channels=header[22];
|
2005-06-10 18:08:08 +00:00
|
|
|
bytespersample=((bitspersample/8)*channels);
|
2005-06-10 19:12:58 +00:00
|
|
|
numbytes=(header[40]|(header[41]<<8)|(header[42]<<16)|(header[43]<<24));
|
2005-06-10 18:08:08 +00:00
|
|
|
totalsamples=numbytes/bytespersample;
|
|
|
|
|
|
|
|
if ((bitspersample!=16) || (channels != 2)) {
|
2005-06-22 19:41:30 +00:00
|
|
|
return CODEC_ERROR;
|
2005-06-10 18:08:08 +00:00
|
|
|
}
|
2005-06-10 19:12:58 +00:00
|
|
|
|
|
|
|
ci->advance_buffer(44);
|
|
|
|
|
2005-06-10 18:08:08 +00:00
|
|
|
/* The main decoder loop */
|
|
|
|
|
|
|
|
samplesdone=0;
|
|
|
|
ci->set_elapsed(0);
|
|
|
|
endofstream=0;
|
|
|
|
while (!endofstream) {
|
|
|
|
if (ci->stop_codec || ci->reload_codec) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-06-10 19:12:58 +00:00
|
|
|
wavbuf=ci->request_buffer(&n,WAV_CHUNK_SIZE);
|
2005-06-10 18:08:08 +00:00
|
|
|
|
|
|
|
if (n==0) break; /* End of stream */
|
|
|
|
|
|
|
|
nsamples=(n/bytespersample);
|
|
|
|
|
|
|
|
/* WAV files can contain extra data at the end - so we can't just
|
|
|
|
process until the end of the file */
|
|
|
|
|
|
|
|
if (samplesdone+nsamples > totalsamples) {
|
|
|
|
nsamples=(totalsamples-samplesdone);
|
|
|
|
n=nsamples*bytespersample;
|
|
|
|
endofstream=1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Byte-swap data */
|
2005-06-10 19:12:58 +00:00
|
|
|
for (i=0;i<n/2;i++) {
|
2005-06-26 19:41:29 +00:00
|
|
|
wavbuf[i]=SWAB16(wavbuf[i]);
|
2005-06-10 18:08:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
samplesdone+=nsamples;
|
|
|
|
ci->set_elapsed(samplesdone/(ci->id3->frequency/1000));
|
|
|
|
|
2005-06-10 19:26:34 +00:00
|
|
|
rb->yield();
|
2005-07-13 12:48:22 +00:00
|
|
|
while (!ci->pcmbuf_insert((unsigned char*)wavbuf, n))
|
2005-06-10 18:08:08 +00:00
|
|
|
rb->yield();
|
2005-06-10 19:12:58 +00:00
|
|
|
|
|
|
|
ci->advance_buffer(n);
|
2005-06-10 18:08:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ci->request_next_track())
|
|
|
|
goto next_track;
|
|
|
|
|
2005-06-22 19:41:30 +00:00
|
|
|
return CODEC_OK;
|
2005-06-10 18:08:08 +00:00
|
|
|
}
|