1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Thom Johansen 2005-10-10 19:56:40 +00:00
parent 5fd58dc0ef
commit 3d98ecf951

View file

@ -18,7 +18,6 @@
****************************************************************************/ ****************************************************************************/
#include "codec.h" #include "codec.h"
#include "dsp.h"
#include "lib/codeclib.h" #include "lib/codeclib.h"
#include <codecs/libmusepack/musepack.h> #include <codecs/libmusepack/musepack.h>
@ -27,14 +26,14 @@ mpc_decoder decoder;
/* Our implementations of the mpc_reader callback functions. */ /* Our implementations of the mpc_reader callback functions. */
mpc_int32_t read_impl(void *data, void *ptr, mpc_int32_t size) 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))); return ((mpc_int32_t)(ci->read_filebuf(ptr, size)));
} }
bool seek_impl(void *data, mpc_int32_t offset) 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, /* WARNING: assumes we don't need to skip too far into the past,
this might not be supported by the buffering layer yet */ 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) 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; return ci->curpos;
} }
mpc_int32_t get_size_impl(void *data) 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; return ci->filesize;
} }
@ -63,22 +62,8 @@ bool canseek_impl(void *data)
return true; 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 */ /* temporary, we probably have better use for iram than this */
MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH] IDATA_ATTR; MPC_SAMPLE_FORMAT sample_buffer[MPC_DECODER_BUFFER_LENGTH] IDATA_ATTR;
unsigned char *OutputPtr;
const unsigned char *OutputBufferEnd;
#ifdef USE_IRAM #ifdef USE_IRAM
extern char iramcopy[]; extern char iramcopy[];
@ -90,27 +75,25 @@ extern char iramend[];
enum codec_status codec_start(struct codec_api *api) enum codec_status codec_start(struct codec_api *api)
{ {
struct codec_api *ci = api; struct codec_api *ci = api;
unsigned short Sample; mpc_int64_t samplesdone;
unsigned long samplesdone;
unsigned long frequency; unsigned long frequency;
unsigned status = 1; unsigned status = 1;
unsigned int i;
mpc_reader reader; mpc_reader reader;
mpc_streaminfo info;
/* Generic codec inititialisation */
TEST_CODEC_API(api); TEST_CODEC_API(api);
#ifdef USE_IRAM
#ifndef SIMULATOR
ci->memcpy(iramstart, iramcopy, iramend - iramstart); ci->memcpy(iramstart, iramcopy, iramend - iramstart);
#endif #endif
ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2)); ci->configure(CODEC_DSP_ENABLE, (bool *)true);
ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16)); ci->configure(DSP_DITHER, (bool *)false);
ci->configure(DSP_SET_SAMPLE_DEPTH, (long *)(MPC_FIXED_POINT_SCALE_SHIFT - 1));
next_track: ci->configure(DSP_SET_CLIP_MAX, (long *)MPC_FIXED_POINT_SCALE);
if (codec_init(api)) ci->configure(DSP_SET_CLIP_MIN, (long *)-MPC_FIXED_POINT_SCALE);
return CODEC_ERROR; ci->configure(CODEC_SET_FILEBUF_LIMIT, (long *)(1024*1024*2));
ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (long *)(1024*16));
/* Create a decoder instance */ /* Create a decoder instance */
reader.read = read_impl; reader.read = read_impl;
reader.seek = seek_impl; reader.seek = seek_impl;
@ -119,72 +102,64 @@ enum codec_status codec_start(struct codec_api *api)
reader.canseek = canseek_impl; reader.canseek = canseek_impl;
reader.data = ci; reader.data = ci;
next_track:
if (codec_init(api))
return CODEC_ERROR;
/* read file's streaminfo data */ /* read file's streaminfo data */
mpc_streaminfo info;
mpc_streaminfo_init(&info); mpc_streaminfo_init(&info);
if (mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK) if (mpc_streaminfo_read(&info, &reader) != ERROR_CODE_OK)
return CODEC_ERROR; return CODEC_ERROR;
frequency = info.sample_freq; 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 */ /* instantiate a decoder with our file reader */
mpc_decoder_setup(&decoder, &reader); mpc_decoder_setup(&decoder, &reader);
if (!mpc_decoder_initialize(&decoder, &info)) if (!mpc_decoder_initialize(&decoder, &info))
return CODEC_ERROR; return CODEC_ERROR;
/* Initialise the output buffer. */
OutputPtr = OutputBuffer;
OutputBufferEnd = OutputBuffer + OUTPUT_BUFFER_SIZE;
/* This is the decoding loop. */ /* This is the decoding loop. */
samplesdone = 0; samplesdone = 0;
while (status != 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) if (ci->stop_codec || ci->reload_codec)
break; break;
status = mpc_decoder_decode(&decoder, sample_buffer, 0, 0); status = mpc_decoder_decode(&decoder, sample_buffer, 0, 0);
if (status == (unsigned)(-1)) { ci->yield();
/* decode error */ if (status == (unsigned)(-1)) { /* decode error */
return CODEC_ERROR; return CODEC_ERROR;
} else { /* status > 0 */ } else {
/* Convert musepack's numbers to an array of 16-bit BE signed integers */ while (!ci->pcmbuf_insert((char *)sample_buffer,
for (i = 0; i < status*info.channels; i += info.channels) { status*sizeof(MPC_SAMPLE_FORMAT)*2))
/* Left channel */ ci->yield();
Sample = shift_signed(sample_buffer[i], 16 - MPC_FIXED_POINT_SCALE_SHIFT); samplesdone += status;
*(OutputPtr++) = Sample >> 8; ci->set_elapsed(samplesdone/(frequency/1000));
*(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;
}
}
} }
} }
/* 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()) if (ci->request_next_track())
goto next_track; goto next_track;
return CODEC_OK; return CODEC_OK;
} }