summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/flac2wav.c229
1 files changed, 229 insertions, 0 deletions
diff --git a/apps/plugins/flac2wav.c b/apps/plugins/flac2wav.c
new file mode 100644
index 0000000000..6fa7940535
--- /dev/null
+++ b/apps/plugins/flac2wav.c
@@ -0,0 +1,229 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Björn Stenberg
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "plugin.h"
21
22#if (CONFIG_HWCODEC == MASNONE) && !defined(SIMULATOR)
23/* software codec platforms, not for simulator */
24
25#include <codecs/libFLAC/include/FLAC/seekable_stream_decoder.h>
26
27#include "lib/xxx2wav.h" /* Helper functions common to test decoders */
28
29#define FLAC_MAX_SUPPORTED_BLOCKSIZE 4608
30#define FLAC_MAX_SUPPORTED_CHANNELS 2
31
32static struct plugin_api* rb;
33
34/* Called when the FLAC decoder needs some FLAC data to decode */
35FLAC__SeekableStreamDecoderReadStatus flac_read_handler(const FLAC__SeekableStreamDecoder *dec,
36 FLAC__byte buffer[], unsigned *bytes, void *data)
37{ (void)dec;
38
39 file_info_struct *p = (file_info_struct *) data;
40
41 if (p->curpos >= p->filesize) {
42 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
43 }
44
45 rb->memcpy(buffer,&filebuf[p->curpos],*bytes);
46 p->curpos+=*bytes;
47
48 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
49}
50
51/* Called when the FLAC decoder has some decoded PCM data to write */
52FLAC__StreamDecoderWriteStatus flac_write_handler(const FLAC__SeekableStreamDecoder *dec,
53 const FLAC__Frame *frame,
54 const FLAC__int32 * const buf[],
55 void *data)
56{
57 unsigned int c_samp, c_chan, d_samp;
58 file_info_struct *p = (file_info_struct *) data;
59 uint32_t data_size = frame->header.blocksize * frame->header.channels * (p->bitspersample / 8);
60 uint32_t samples = frame->header.blocksize;
61
62 // FIXME: This should not be on the stack!
63 static unsigned char ldb[FLAC_MAX_SUPPORTED_BLOCKSIZE*FLAC_MAX_SUPPORTED_CHANNELS*2];
64
65 if (samples*frame->header.channels > (FLAC_MAX_SUPPORTED_BLOCKSIZE*FLAC_MAX_SUPPORTED_CHANNELS)) {
66 // ERROR!!!
67#ifdef SIMULATOR
68 fprintf(stderr,"ERROR: samples*frame->header.channels=%d\n",samples*frame->header.channels);
69#endif
70 return(FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE);
71 }
72
73 (void)dec;
74 (void)data_size;
75 for(c_samp = d_samp = 0; c_samp < samples; c_samp++) {
76 for(c_chan = 0; c_chan < frame->header.channels; c_chan++, d_samp++) {
77 ldb[d_samp*2] = buf[c_chan][c_samp]&0xff;
78 ldb[(d_samp*2)+1] = (buf[c_chan][c_samp]&0xff00)>>8;
79 }
80 }
81
82 rb->write(p->outfile,ldb,data_size);
83
84 p->current_sample += samples;
85
86 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
87}
88
89void flac_metadata_handler(const FLAC__SeekableStreamDecoder *dec,
90 const FLAC__StreamMetadata *meta, void *data)
91{
92 file_info_struct *p = (file_info_struct *) data;
93 (void)dec;
94
95 if(meta->type == FLAC__METADATA_TYPE_STREAMINFO) {
96 p->bitspersample = meta->data.stream_info.bits_per_sample;
97 p->samplerate = meta->data.stream_info.sample_rate;
98 p->channels = meta->data.stream_info.channels;
99// FLAC__ASSERT(meta->data.stream_info.total_samples < 0x100000000); /* we can handle < 4 gigasamples */
100 p->total_samples = (unsigned)
101 (meta->data.stream_info.total_samples & 0xffffffff);
102 p->current_sample = 0;
103 }
104}
105
106
107void flac_error_handler(const FLAC__SeekableStreamDecoder *dec,
108 FLAC__StreamDecoderErrorStatus status, void *data)
109{
110 (void)dec;
111 (void)status;
112 (void)data;
113}
114
115FLAC__SeekableStreamDecoderSeekStatus flac_seek_handler (const FLAC__SeekableStreamDecoder *decoder,
116 FLAC__uint64 absolute_byte_offset,
117 void *client_data)
118{
119 (void)decoder;
120 file_info_struct *p = (file_info_struct *) client_data;
121 rb->lseek(p->infile,SEEK_SET,absolute_byte_offset);
122 return(FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK);
123}
124
125FLAC__SeekableStreamDecoderTellStatus flac_tell_handler (const FLAC__SeekableStreamDecoder *decoder,
126 FLAC__uint64 *absolute_byte_offset, void *client_data)
127{
128 file_info_struct *p = (file_info_struct *) client_data;
129
130 (void)decoder;
131 *absolute_byte_offset=rb->lseek(p->infile,SEEK_CUR,0);
132 return(FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK);
133}
134
135FLAC__SeekableStreamDecoderLengthStatus flac_length_handler (const FLAC__SeekableStreamDecoder *decoder,
136 FLAC__uint64 *stream_length, void *client_data)
137{
138 file_info_struct *p = (file_info_struct *) client_data;
139
140 (void)decoder;
141 *stream_length=p->filesize;
142 return(FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK);
143}
144
145FLAC__bool flac_eof_handler (const FLAC__SeekableStreamDecoder *decoder,
146 void *client_data)
147{
148 file_info_struct *p = (file_info_struct *) client_data;
149
150 (void)decoder;
151 if (p->curpos >= p->filesize) {
152 return(true);
153 } else {
154 return(false);
155 }
156}
157
158
159/* this is the plugin entry point */
160enum plugin_status plugin_start(struct plugin_api* api, void* file)
161{
162 FLAC__SeekableStreamDecoder* flacDecoder;
163 file_info_struct file_info;
164
165 TEST_PLUGIN_API(api);
166
167 /* if you are using a global api pointer, don't forget to copy it!
168 otherwise you will get lovely "I04: IllInstr" errors... :-) */
169 rb = api;
170
171
172 /* This function sets up the buffers and reads the file into RAM */
173
174 if (local_init(file,"/flactest.wav",&file_info,api)) {
175 return PLUGIN_ERROR;
176 }
177
178 /* Create a decoder instance */
179
180 flacDecoder=FLAC__seekable_stream_decoder_new();
181
182 /* Set up the decoder and the callback functions - this must be done before init */
183
184 /* The following are required for stream_decoder and higher */
185 FLAC__seekable_stream_decoder_set_client_data(flacDecoder,&file_info);
186 FLAC__seekable_stream_decoder_set_write_callback(flacDecoder, flac_write_handler);
187 FLAC__seekable_stream_decoder_set_read_callback(flacDecoder, flac_read_handler);
188 FLAC__seekable_stream_decoder_set_metadata_callback(flacDecoder, flac_metadata_handler);
189 FLAC__seekable_stream_decoder_set_error_callback(flacDecoder, flac_error_handler);
190 FLAC__seekable_stream_decoder_set_metadata_respond(flacDecoder, FLAC__METADATA_TYPE_STREAMINFO);
191
192 /* The following are only for the seekable_stream_decoder */
193 FLAC__seekable_stream_decoder_set_seek_callback(flacDecoder, flac_seek_handler);
194 FLAC__seekable_stream_decoder_set_tell_callback(flacDecoder, flac_tell_handler);
195 FLAC__seekable_stream_decoder_set_length_callback(flacDecoder, flac_length_handler);
196 FLAC__seekable_stream_decoder_set_eof_callback(flacDecoder, flac_eof_handler);
197
198 if (FLAC__seekable_stream_decoder_init(flacDecoder)) {
199 return PLUGIN_ERROR;
200 }
201
202 /* The first thing to do is to parse the metadata */
203 FLAC__seekable_stream_decoder_process_until_end_of_metadata(flacDecoder);
204
205 file_info.frames_decoded=0;
206 file_info.start_tick=*(rb->current_tick);
207 while (FLAC__seekable_stream_decoder_get_state(flacDecoder)!=2) {
208 FLAC__seekable_stream_decoder_process_single(flacDecoder);
209 file_info.frames_decoded++;
210
211 display_status(&file_info);
212
213 if (rb->button_get(false)!=BUTTON_NONE) {
214 close_wav(&file_info);
215 return PLUGIN_OK;
216 }
217 }
218
219 close_wav(&file_info);
220 rb->splash(HZ*2, true, "FINISHED!");
221
222 /* Flush internal buffers etc */
223//No need for this. flacResult=FLAC__seekable_stream_decoder_reset(flacDecoder);
224
225 // audio_close();
226
227 return PLUGIN_OK;
228}
229#endif /* CONFIG_HWCODEC == MASNONE */