summaryrefslogtreecommitdiff
path: root/apps/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs')
-rw-r--r--apps/codecs/flac.c306
-rw-r--r--apps/codecs/lib/xxx2wav.c25
-rw-r--r--apps/codecs/lib/xxx2wav.h6
-rw-r--r--apps/codecs/libFLAC/SOURCES1
-rw-r--r--apps/codecs/libFLAC/include/FLAC/metadata.h8
-rw-r--r--apps/codecs/vorbis.c15
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;