diff options
Diffstat (limited to 'apps/codecs')
| -rw-r--r-- | apps/codecs/flac.c | 306 | ||||
| -rw-r--r-- | apps/codecs/lib/xxx2wav.c | 25 | ||||
| -rw-r--r-- | apps/codecs/lib/xxx2wav.h | 6 | ||||
| -rw-r--r-- | apps/codecs/libFLAC/SOURCES | 1 | ||||
| -rw-r--r-- | apps/codecs/libFLAC/include/FLAC/metadata.h | 8 | ||||
| -rw-r--r-- | apps/codecs/vorbis.c | 15 |
6 files changed, 243 insertions, 118 deletions
diff --git a/apps/codecs/flac.c b/apps/codecs/flac.c index 259686e..0d21c3c 100644 --- a/apps/codecs/flac.c +++ b/apps/codecs/flac.c @@ -20,6 +20,8 @@ #include "codec.h" #include <codecs/libFLAC/include/FLAC/seekable_stream_decoder.h> +#include <codecs/libFLAC/include/FLAC/format.h> +#include <codecs/libFLAC/include/FLAC/metadata.h> #include "playback.h" #include "lib/codeclib.h" #include "dsp.h" @@ -30,6 +32,10 @@ static struct codec_api* rb; static uint32_t samplesdone; +static FLAC__StreamMetadata *stream_info; +static FLAC__StreamMetadata *seek_table; +unsigned int metadata_length; + /* Called when the FLAC decoder needs some FLAC data to decode */ FLAC__SeekableStreamDecoderReadStatus flac_read_handler(const FLAC__SeekableStreamDecoder *dec, FLAC__byte buffer[], unsigned *bytes, void *data) @@ -49,9 +55,9 @@ static unsigned char pcmbuf[FLAC_MAX_SUPPORTED_BLOCKSIZE*FLAC_MAX_SUPPORTED_CHAN /* Called when the FLAC decoder has some decoded PCM data to write */ FLAC__StreamDecoderWriteStatus flac_write_handler(const FLAC__SeekableStreamDecoder *dec, - const FLAC__Frame *frame, - const FLAC__int32 * const buf[], - void *data) + const FLAC__Frame *frame, + const FLAC__int32 * const buf[], + void *data) { struct codec_api* ci = (struct codec_api*)data; (void)dec; @@ -92,10 +98,23 @@ FLAC__StreamDecoderWriteStatus flac_write_handler(const FLAC__SeekableStreamDeco void flac_metadata_handler(const FLAC__SeekableStreamDecoder *dec, const FLAC__StreamMetadata *meta, void *data) { - /* Ignore metadata for now... */ - (void)dec; - (void)meta; - (void)data; + /* Ignore metadata for now... */ + (void)dec; + (void)data; + + metadata_length += meta->length; + + if ( meta->type == FLAC__METADATA_TYPE_STREAMINFO ) { + stream_info = FLAC__metadata_object_clone( meta ); + if ( stream_info == NULL ) { + //return CODEC_ERROR; + } + } else if ( meta->type == FLAC__METADATA_TYPE_SEEKTABLE ) { + seek_table = FLAC__metadata_object_clone( meta ); + if ( seek_table == NULL ) { + //return CODEC_ERROR; + } + } } @@ -111,47 +130,47 @@ FLAC__SeekableStreamDecoderSeekStatus flac_seek_handler (const FLAC__SeekableStr FLAC__uint64 absolute_byte_offset, void *client_data) { - (void)decoder; - struct codec_api* ci = (struct codec_api*)client_data; + (void)decoder; + struct codec_api* ci = (struct codec_api*)client_data; - if (ci->seek_buffer(absolute_byte_offset)) { + if (ci->seek_buffer(absolute_byte_offset)) { return(FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK); - } else { + } else { return(FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR); - } + } } FLAC__SeekableStreamDecoderTellStatus flac_tell_handler (const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) { - struct codec_api* ci = (struct codec_api*)client_data; + struct codec_api* ci = (struct codec_api*)client_data; - (void)decoder; - *absolute_byte_offset=ci->curpos; - return(FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK); + (void)decoder; + *absolute_byte_offset=ci->curpos; + return(FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK); } FLAC__SeekableStreamDecoderLengthStatus flac_length_handler (const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) { - struct codec_api* ci = (struct codec_api*)client_data; + struct codec_api* ci = (struct codec_api*)client_data; - (void)decoder; - *stream_length=ci->filesize; - return(FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK); + (void)decoder; + *stream_length=ci->filesize; + return(FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK); } FLAC__bool flac_eof_handler (const FLAC__SeekableStreamDecoder *decoder, void *client_data) { - struct codec_api* ci = (struct codec_api*)client_data; + struct codec_api* ci = (struct codec_api*)client_data; - (void)decoder; - if (ci->curpos >= ci->filesize) { + (void)decoder; + if (ci->curpos >= ci->filesize) { return(true); - } else { + } else { return(false); - } + } } #ifndef SIMULATOR @@ -160,104 +179,193 @@ extern char iramstart[]; extern char iramend[]; #endif +FLAC__uint64 find_sample_number(size_t offset) +{ + FLAC__StreamMetadata_SeekPoint *points; + FLAC__uint64 prev_sample, next_sample; + size_t prev_offset, next_offset; + int percent; + + if ( offset >= (rb->id3->filesize - metadata_length)) { + return stream_info->data.stream_info.total_samples; + } + + prev_offset = 0; + prev_sample = 0; + next_offset = rb->id3->filesize - metadata_length; + next_sample = stream_info->data.stream_info.total_samples; + + if ( seek_table ) { + int left, right, middle; + + middle = 0; /* Silence compiler warnings */ + points = seek_table->data.seek_table.points; + left = 0; + right = seek_table->data.seek_table.num_points - 1; + + /* Do a binary search to find the matching seek point */ + while ( left <= right ) { + middle = (left + right) / 2; + + if ( (FLAC__uint64)offset < points[middle].stream_offset ) { + right = middle - 1; + } else if ( (FLAC__uint64)offset > points[middle].stream_offset ) { + left = middle + 1; + } else { + return points[middle].sample_number; + } + } + + /* Didn't find a matching seek point, so get the sample numbers of the + * seek points to the left and right of offset to make our guess more + * accurate. Accuracy depends on how close these sample numbers are to + * each other. + */ + if ( (unsigned)left >= seek_table->data.seek_table.num_points ) { + prev_offset = points[middle].stream_offset; + prev_sample = points[middle].sample_number; + } else if ( right < 0 ) { + next_offset = points[middle].stream_offset; + next_sample = points[middle].sample_number; + } else { + middle--; + prev_offset = points[middle].stream_offset; + prev_sample = points[middle].sample_number; + next_offset = points[middle+1].stream_offset; + next_sample = points[middle+1].sample_number; + } + } + + /* Either there's no seek table or we didn't find our seek point, so now we + * have to guess. + */ + percent = ((offset - prev_offset) * 100) / (next_offset - prev_offset); + return (FLAC__uint64)(percent * (next_sample - prev_sample) / 100 + prev_sample); +} + /* this is the codec entry point */ enum codec_status codec_start(struct codec_api* api) { struct codec_api* ci = api; FLAC__SeekableStreamDecoder* flacDecoder; + FLAC__uint64 offset; - /* Generic codec initialisation */ - TEST_CODEC_API(api); + /* Generic codec initialisation */ + TEST_CODEC_API(api); - /* if you are using a global api pointer, don't forget to copy it! - otherwise you will get lovely "I04: IllInstr" errors... :-) */ - rb = api; + /* 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); + 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)); - ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*128)); + ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*10)); + ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512)); + ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*1024)); - ci->configure(DSP_DITHER, (bool *)false); - ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_INTERLEAVED); - ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(16)); + ci->configure(CODEC_DSP_ENABLE, (bool *)true); + ci->configure(DSP_DITHER, (bool *)false); + ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_INTERLEAVED); + ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(16)); - next_track: + next_track: - if (codec_init(api)) { - return CODEC_ERROR; - } + metadata_length = 0; + seek_table = NULL; + stream_info = NULL; - while (!rb->taginfo_ready) + if (codec_init(api)) { + return CODEC_ERROR; + } + + while (!rb->taginfo_ready) rb->yield(); - if (rb->id3->frequency != NATIVE_FREQUENCY) { - rb->configure(DSP_SET_FREQUENCY, (long *)(rb->id3->frequency)); - rb->configure(CODEC_DSP_ENABLE, (bool *)true); - } else { - rb->configure(CODEC_DSP_ENABLE, (bool *)false); - } + rb->configure(DSP_SET_FREQUENCY, (long *)(rb->id3->frequency)); + codec_set_replaygain(ci->id3); - /* Create a decoder instance */ - - flacDecoder=FLAC__seekable_stream_decoder_new(); - - /* Set up the decoder and the callback functions - this must be done before init */ - - /* The following are required for stream_decoder and higher */ - FLAC__seekable_stream_decoder_set_client_data(flacDecoder,ci); - FLAC__seekable_stream_decoder_set_write_callback(flacDecoder, flac_write_handler); - FLAC__seekable_stream_decoder_set_read_callback(flacDecoder, flac_read_handler); - FLAC__seekable_stream_decoder_set_metadata_callback(flacDecoder, flac_metadata_handler); - FLAC__seekable_stream_decoder_set_error_callback(flacDecoder, flac_error_handler); - FLAC__seekable_stream_decoder_set_metadata_respond(flacDecoder, FLAC__METADATA_TYPE_STREAMINFO); - - /* The following are only for the seekable_stream_decoder */ - FLAC__seekable_stream_decoder_set_seek_callback(flacDecoder, flac_seek_handler); - FLAC__seekable_stream_decoder_set_tell_callback(flacDecoder, flac_tell_handler); - FLAC__seekable_stream_decoder_set_length_callback(flacDecoder, flac_length_handler); - FLAC__seekable_stream_decoder_set_eof_callback(flacDecoder, flac_eof_handler); - - - /* QUESTION: What do we do when the init fails? */ - if (FLAC__seekable_stream_decoder_init(flacDecoder)) { - return CODEC_ERROR; - } - - /* The first thing to do is to parse the metadata */ - FLAC__seekable_stream_decoder_process_until_end_of_metadata(flacDecoder); - - samplesdone=0; - ci->set_elapsed(0); - /* The main decoder loop */ - while (FLAC__seekable_stream_decoder_get_state(flacDecoder)!=FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) { - rb->yield(); - if (ci->stop_codec || ci->reload_codec) { - break; + /* Create a decoder instance */ + + flacDecoder=FLAC__seekable_stream_decoder_new(); + + /* Set up the decoder and the callback functions - this must be done before init */ + + /* The following are required for stream_decoder and higher */ + FLAC__seekable_stream_decoder_set_client_data(flacDecoder,ci); + FLAC__seekable_stream_decoder_set_write_callback(flacDecoder, flac_write_handler); + FLAC__seekable_stream_decoder_set_read_callback(flacDecoder, flac_read_handler); + FLAC__seekable_stream_decoder_set_metadata_callback(flacDecoder, flac_metadata_handler); + FLAC__seekable_stream_decoder_set_error_callback(flacDecoder, flac_error_handler); + FLAC__seekable_stream_decoder_set_metadata_respond_all(flacDecoder); + + /* The following are only for the seekable_stream_decoder */ + FLAC__seekable_stream_decoder_set_seek_callback(flacDecoder, flac_seek_handler); + FLAC__seekable_stream_decoder_set_tell_callback(flacDecoder, flac_tell_handler); + FLAC__seekable_stream_decoder_set_length_callback(flacDecoder, flac_length_handler); + FLAC__seekable_stream_decoder_set_eof_callback(flacDecoder, flac_eof_handler); + + + /* QUESTION: What do we do when the init fails? */ + if (FLAC__seekable_stream_decoder_init(flacDecoder)) { + return CODEC_ERROR; } - if (ci->seek_time) { - int sample_loc; + /* The first thing to do is to parse the metadata */ + FLAC__seekable_stream_decoder_process_until_end_of_metadata(flacDecoder); - sample_loc = ci->seek_time/1000 * ci->id3->frequency; - if (FLAC__seekable_stream_decoder_seek_absolute(flacDecoder,sample_loc)) { - samplesdone=sample_loc; - ci->set_elapsed(samplesdone/(ci->id3->frequency/1000)); - } - ci->seek_time = 0; + if ( ci->id3->offset && stream_info ) { + FLAC__uint64 sample; + + sample = find_sample_number( ci->id3->offset - metadata_length ); + ci->advance_buffer(ci->id3->offset); + FLAC__seekable_stream_decoder_seek_absolute(flacDecoder, sample); + FLAC__seekable_stream_decoder_get_decode_position(flacDecoder, &offset); + ci->set_offset(offset); + samplesdone=(uint32_t)sample; + ci->set_elapsed(sample/(ci->id3->frequency/1000)); + } else { + samplesdone=0; + ci->set_elapsed(0); } - FLAC__seekable_stream_decoder_process_single(flacDecoder); - } + /* The main decoder loop */ + while (FLAC__seekable_stream_decoder_get_state(flacDecoder)!=FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) { + rb->yield(); + if (ci->stop_codec || ci->reload_codec) { + break; + } + + if (ci->seek_time) { + int sample_loc; + + sample_loc = ci->seek_time/1000 * ci->id3->frequency; + if (FLAC__seekable_stream_decoder_seek_absolute(flacDecoder,sample_loc)) { + samplesdone=sample_loc; + ci->set_elapsed(samplesdone/(ci->id3->frequency/1000)); + } + ci->seek_time = 0; + } + + FLAC__seekable_stream_decoder_process_single(flacDecoder); + FLAC__seekable_stream_decoder_get_decode_position(flacDecoder, &offset); + ci->set_offset(offset); + } - /* Flush the libFLAC buffers */ - FLAC__seekable_stream_decoder_finish(flacDecoder); + /* Flush the libFLAC buffers */ + FLAC__seekable_stream_decoder_finish(flacDecoder); - if (ci->request_next_track()) - goto next_track; + if (ci->request_next_track()) { + if ( stream_info ) { + FLAC__metadata_object_delete(stream_info); + } + if ( seek_table ) { + FLAC__metadata_object_delete(seek_table); + } + metadata_length = 0; + goto next_track; + } - return CODEC_OK; + return CODEC_OK; } diff --git a/apps/codecs/lib/xxx2wav.c b/apps/codecs/lib/xxx2wav.c index 338f1c4..8c6ceed 100644 --- a/apps/codecs/lib/xxx2wav.c +++ b/apps/codecs/lib/xxx2wav.c @@ -70,6 +70,31 @@ void* codec_realloc(void* ptr, size_t size) return(x); } +size_t strlen(const char *s) +{ + return(local_rb->strlen(s)); +} + +char *strcpy(char *dest, const char *src) +{ + return(local_rb->strcpy(dest,src)); +} + +char *strcat(char *dest, const char *src) +{ + return(local_rb->strcat(dest,src)); +} + +int strcmp(const char *s1, const char *s2) +{ + return(local_rb->strcmp(s1,s2)); +} + +int strncasecmp(const char *s1, const char *s2, size_t n) +{ + return(local_rb->strncasecmp(s1,s2,n)); +} + void *memcpy(void *dest, const void *src, size_t n) { return(local_rb->memcpy(dest,src,n)); diff --git a/apps/codecs/lib/xxx2wav.h b/apps/codecs/lib/xxx2wav.h index 1cdbc99..2c9a737 100644 --- a/apps/codecs/lib/xxx2wav.h +++ b/apps/codecs/lib/xxx2wav.h @@ -49,6 +49,12 @@ void* codec_calloc(size_t nmemb, size_t size); void* codec_alloca(size_t size); void* codec_realloc(void* ptr, size_t size); void codec_free(void* ptr); +size_t strlen(const char *s); +char *strcpy(char *dest, const char *src); +char *strcat(char *dest, const char *src); +int strcmp(const char *, const char *); +int strcasecmp(const char *, const char *); + void *memcpy(void *dest, const void *src, size_t n); void *memset(void *s, int c, size_t n); int memcmp(const void *s1, const void *s2, size_t n); diff --git a/apps/codecs/libFLAC/SOURCES b/apps/codecs/libFLAC/SOURCES index b6f21dc..9d4db2f 100644 --- a/apps/codecs/libFLAC/SOURCES +++ b/apps/codecs/libFLAC/SOURCES @@ -8,6 +8,7 @@ format.c lpc.c md5.c memory.c +metadata_object.c seekable_stream_decoder.c stream_decoder.c #if defined(CPU_COLDFIRE) && !defined(SIMULATOR) diff --git a/apps/codecs/libFLAC/include/FLAC/metadata.h b/apps/codecs/libFLAC/include/FLAC/metadata.h index ff40e6d..be3e6ef 100644 --- a/apps/codecs/libFLAC/include/FLAC/metadata.h +++ b/apps/codecs/libFLAC/include/FLAC/metadata.h @@ -295,7 +295,7 @@ extern FLAC_API const char * const FLAC__Metadata_SimpleIteratorStatusString[]; * \retval FLAC__Metadata_SimpleIterator* * \c NULL if there was an error allocating memory, else the new instance. */ -FLAC_API FLAC__Metadata_SimpleIterator *FLAC__metadata_simple_iterator_new(); +FLAC_API FLAC__Metadata_SimpleIterator *FLAC__metadata_simple_iterator_new(void); /** Free an iterator instance. Deletes the object pointed to by \a iterator. * @@ -652,7 +652,7 @@ extern FLAC_API const char * const FLAC__Metadata_ChainStatusString[]; * \retval FLAC__Metadata_Chain* * \c NULL if there was an error allocating memory, else the new instance. */ -FLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new(); +FLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new(void); /** Free a chain instance. Deletes the object pointed to by \a chain. * @@ -899,7 +899,7 @@ FLAC_API void FLAC__metadata_chain_sort_padding(FLAC__Metadata_Chain *chain); * \retval FLAC__Metadata_Iterator* * \c NULL if there was an error allocating memory, else the new instance. */ -FLAC_API FLAC__Metadata_Iterator *FLAC__metadata_iterator_new(); +FLAC_API FLAC__Metadata_Iterator *FLAC__metadata_iterator_new(void); /** Free an iterator instance. Deletes the object pointed to by \a iterator. * @@ -1621,7 +1621,7 @@ FLAC_API int FLAC__metadata_object_vorbiscomment_remove_entries_matching(FLAC__S * \retval FLAC__StreamMetadata_CueSheet_Track* * \c NULL if there was an error allocating memory, else the new instance. */ -FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_new(); +FLAC_API FLAC__StreamMetadata_CueSheet_Track *FLAC__metadata_object_cuesheet_track_new(void); /** Create a copy of an existing CUESHEET track object. * diff --git a/apps/codecs/vorbis.c b/apps/codecs/vorbis.c index 2976a05..e072acc 100644 --- a/apps/codecs/vorbis.c +++ b/apps/codecs/vorbis.c @@ -33,21 +33,6 @@ static struct codec_api* rb; int errno; -size_t strlen(const char *s) -{ - return(rb->strlen(s)); -} - -char *strcpy(char *dest, const char *src) -{ - return(rb->strcpy(dest,src)); -} - -char *strcat(char *dest, const char *src) -{ - return(rb->strcat(dest,src)); -} - size_t read_handler(void *ptr, size_t size, size_t nmemb, void *datasource) { (void)datasource; |