diff options
author | Thom Johansen <thomj@rockbox.org> | 2005-10-10 19:56:40 +0000 |
---|---|---|
committer | Thom Johansen <thomj@rockbox.org> | 2005-10-10 19:56:40 +0000 |
commit | 3d98ecf9519f061cde0fecfca45b2c54a712c1ac (patch) | |
tree | ac6764ebf75ab56bcf3d36e16cfd80bc2351ad03 /apps/codecs | |
parent | 5fd58dc0ef8913f5e59118bbc04c5ee90da490b5 (diff) |
Added DSP support and started passing full precision samples to playback engine. Added dog slow seeking support (thanks to poor seeking support in file format). Some cosmetic changes. Still not realtime.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7613 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs')
-rw-r--r-- | apps/codecs/mpc.c | 131 |
1 files changed, 53 insertions, 78 deletions
diff --git a/apps/codecs/mpc.c b/apps/codecs/mpc.c index d37ac46a4f..eb6ead6979 100644 --- a/apps/codecs/mpc.c +++ b/apps/codecs/mpc.c @@ -18,7 +18,6 @@ ****************************************************************************/ #include "codec.h" -#include "dsp.h" #include "lib/codeclib.h" #include <codecs/libmusepack/musepack.h> @@ -27,14 +26,14 @@ mpc_decoder decoder; /* Our implementations of the mpc_reader callback functions. */ mpc_int32_t read_impl(void *data, void *ptr, mpc_int32_t size) { - struct codec_api *ci = (struct codec_api*)data; + struct codec_api *ci = (struct codec_api *)data; return ((mpc_int32_t)(ci->read_filebuf(ptr, size))); } bool seek_impl(void *data, mpc_int32_t offset) { - struct codec_api *ci = (struct codec_api*)data; + struct codec_api *ci = (struct codec_api *)data; /* WARNING: assumes we don't need to skip too far into the past, this might not be supported by the buffering layer yet */ @@ -43,14 +42,14 @@ bool seek_impl(void *data, mpc_int32_t offset) mpc_int32_t tell_impl(void *data) { - struct codec_api *ci = (struct codec_api*)data; + struct codec_api *ci = (struct codec_api *)data; return ci->curpos; } mpc_int32_t get_size_impl(void *data) { - struct codec_api *ci = (struct codec_api*)data; + struct codec_api *ci = (struct codec_api *)data; return ci->filesize; } @@ -63,22 +62,8 @@ bool canseek_impl(void *data) return true; } -inline int shift_signed(MPC_SAMPLE_FORMAT val, int shift) -{ - if (shift > 0) - val <<= shift; - else if (shift < 0) - val >>= -shift; - return (int)val; -} - -#define OUTPUT_BUFFER_SIZE 65536 /* Must be an integer multiple of 4. */ - -unsigned char OutputBuffer[OUTPUT_BUFFER_SIZE]; /* temporary, we probably have better use for iram than this */ MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH] IDATA_ATTR; -unsigned char *OutputPtr; -const unsigned char *OutputBufferEnd; #ifdef USE_IRAM extern char iramcopy[]; @@ -90,27 +75,25 @@ extern char iramend[]; enum codec_status codec_start(struct codec_api *api) { struct codec_api *ci = api; - unsigned short Sample; - unsigned long samplesdone; + mpc_int64_t samplesdone; unsigned long frequency; unsigned status = 1; - unsigned int i; mpc_reader reader; - - /* Generic codec inititialisation */ + mpc_streaminfo info; + TEST_CODEC_API(api); - - #ifndef SIMULATOR + #ifdef USE_IRAM ci->memcpy(iramstart, iramcopy, iramend - iramstart); #endif - - ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2)); - ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16)); - - next_track: - if (codec_init(api)) - return CODEC_ERROR; - + + ci->configure(CODEC_DSP_ENABLE, (bool *)true); + ci->configure(DSP_DITHER, (bool *)false); + ci->configure(DSP_SET_SAMPLE_DEPTH, (long *)(MPC_FIXED_POINT_SCALE_SHIFT - 1)); + ci->configure(DSP_SET_CLIP_MAX, (long *)MPC_FIXED_POINT_SCALE); + ci->configure(DSP_SET_CLIP_MIN, (long *)-MPC_FIXED_POINT_SCALE); + ci->configure(CODEC_SET_FILEBUF_LIMIT, (long *)(1024*1024*2)); + ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (long *)(1024*16)); + /* Create a decoder instance */ reader.read = read_impl; reader.seek = seek_impl; @@ -119,72 +102,64 @@ enum codec_status codec_start(struct codec_api *api) reader.canseek = canseek_impl; reader.data = ci; +next_track: + if (codec_init(api)) + return CODEC_ERROR; + /* read file's streaminfo data */ - mpc_streaminfo info; mpc_streaminfo_init(&info); if (mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK) return CODEC_ERROR; frequency = info.sample_freq; - + ci->configure(DSP_SET_FREQUENCY, (long *)info.sample_freq); + + /* TODO: this should no doubt be handled in metadata.c */ + ci->id3->length = info.pcm_samples/info.sample_freq*1000; + + /* set playback engine up for correct number of channels */ + /* NOTE: current musepack format only allows for stereo files + but code is here to handle other configurations anyway */ + if (info.channels == 2) + ci->configure(DSP_SET_STEREO_MODE, (long *)STEREO_INTERLEAVED); + else if (info.channels == 1) + ci->configure(DSP_SET_STEREO_MODE, (long *)STEREO_MONO); + else + return CODEC_ERROR; + /* instantiate a decoder with our file reader */ mpc_decoder_setup(&decoder, &reader); if (!mpc_decoder_initialize(&decoder, &info)) return CODEC_ERROR; - /* Initialise the output buffer. */ - OutputPtr = OutputBuffer; - OutputBufferEnd = OutputBuffer + OUTPUT_BUFFER_SIZE; - /* This is the decoding loop. */ samplesdone = 0; while (status != 0) { + if (ci->seek_time) { + mpc_int64_t new_sample_offset = ci->seek_time*info.sample_freq/1000; + if (mpc_decoder_seek_sample(&decoder, new_sample_offset)) { + samplesdone = new_sample_offset; + ci->set_elapsed(ci->seek_time); + } + ci->seek_complete(); + } + if (ci->stop_codec || ci->reload_codec) break; status = mpc_decoder_decode(&decoder, sample_buffer, 0, 0); - if (status == (unsigned)(-1)) { - /* decode error */ + ci->yield(); + if (status == (unsigned)(-1)) { /* decode error */ return CODEC_ERROR; - } else { /* status > 0 */ - /* Convert musepack's numbers to an array of 16-bit BE signed integers */ - for (i = 0; i < status*info.channels; i += info.channels) { - /* Left channel */ - Sample = shift_signed(sample_buffer[i], 16 - MPC_FIXED_POINT_SCALE_SHIFT); - *(OutputPtr++) = Sample >> 8; - *(OutputPtr++) = Sample & 0xff; - - /* Right channel. If the decoded stream is monophonic then - * the right output channel is the same as the left one. - */ - if (info.channels == 2) { - Sample = shift_signed(sample_buffer[i + 1], 16 - MPC_FIXED_POINT_SCALE_SHIFT); - } - *(OutputPtr++) = Sample >> 8; - *(OutputPtr++) = Sample & 0xff; - samplesdone++; - - /* Flush the buffer if it is full. */ - if (OutputPtr == OutputBufferEnd) { - ci->yield(); - while (!ci->pcmbuf_insert(OutputBuffer, OUTPUT_BUFFER_SIZE)) - ci->yield(); - ci->set_elapsed(samplesdone/(frequency/1000)); - OutputPtr = OutputBuffer; - } - } + } else { + while (!ci->pcmbuf_insert((char *)sample_buffer, + status*sizeof(MPC_SAMPLE_FORMAT)*2)) + ci->yield(); + samplesdone += status; + ci->set_elapsed(samplesdone/(frequency/1000)); } } - - /* Flush the remaining data in the output buffer */ - if (OutputPtr > OutputBuffer) { - ci->yield(); - while (!ci->pcmbuf_insert(OutputBuffer, OutputPtr - OutputBuffer)) - ci->yield(); - } - if (ci->request_next_track()) goto next_track; - return CODEC_OK; } |