diff options
-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; } |