summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2005-02-16 16:07:25 +0000
committerDave Chapman <dave@dchapman.com>2005-02-16 16:07:25 +0000
commit711f763a127b5be80018c49db333841178103913 (patch)
tree000845d2828b49d632f805c6473fbb8578790eaa /apps
parenta9b7109b6778fb90d8321f888b822e2a3085833c (diff)
downloadrockbox-711f763a127b5be80018c49db333841178103913.tar.gz
rockbox-711f763a127b5be80018c49db333841178103913.zip
Code cleanup and change to use contents of xxx2wav.h (still more work to do)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5981 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/mpa2wav.c261
1 files changed, 31 insertions, 230 deletions
diff --git a/apps/plugins/mpa2wav.c b/apps/plugins/mpa2wav.c
index 025cb82dcb..2f1f329275 100644
--- a/apps/plugins/mpa2wav.c
+++ b/apps/plugins/mpa2wav.c
@@ -24,24 +24,11 @@
24 24
25#include <codecs/libmad/mad.h> 25#include <codecs/libmad/mad.h>
26 26
27typedef struct ao_sample_format { 27static struct plugin_api* rb;
28 int bits; /* bits per sample */ 28
29 int rate; /* samples per second (in a single channel) */ 29/* Helper functions common to all decoder test viewers (uses rb) */
30 int channels; /* number of audio channels */
31 int byte_format; /* Byte ordering in sample, see constants below */
32} ao_sample_format;
33
34typedef struct {
35 int infile;
36 int outfile;
37 off_t curpos;
38 off_t filesize;
39 ao_sample_format samfmt; /* bits, rate, channels, byte_format */
40 int framesize;
41 unsigned long total_samples;
42 unsigned long current_sample;
43} file_info_struct;
44 30
31#include "xxx2wav.h"
45 32
46struct mad_stream Stream; 33struct mad_stream Stream;
47struct mad_frame Frame; 34struct mad_frame Frame;
@@ -49,81 +36,11 @@ struct mad_synth Synth;
49mad_timer_t Timer; 36mad_timer_t Timer;
50struct dither d0, d1; 37struct dither d0, d1;
51 38
52file_info_struct file_info; 39/* The following function is used inside libmad - let's hope it's never
53 40 called.
54#define MALLOC_BUFSIZE (512*1024) 41*/
55
56int mem_ptr;
57int bufsize;
58unsigned char* mp3buf; // The actual MP3 buffer from Rockbox
59unsigned char* mallocbuf; // 512K from the start of MP3 buffer
60unsigned char* filebuf; // The rest of the MP3 buffer
61
62/* here is a global api struct pointer. while not strictly necessary,
63 it's nice not to have to pass the api pointer in all function calls
64 in the plugin */
65static struct plugin_api* rb;
66
67void* malloc(size_t size) {
68 void* x;
69 char s[32];
70
71 x=&mallocbuf[mem_ptr];
72 mem_ptr+=size+(size%4); // Keep memory 32-bit aligned (if it was already?)
73
74 rb->snprintf(s,30,"Memory used: %d",mem_ptr);
75 rb->lcd_putsxy(0,80,s);
76 rb->lcd_update();
77 return(x);
78}
79
80void* calloc(size_t nmemb, size_t size) {
81 void* x;
82 x=malloc(nmemb*size);
83 rb->memset(x,0,nmemb*size);
84 return(x);
85}
86
87void free(void* ptr) {
88 (void)ptr;
89}
90
91void* realloc(void* ptr, size_t size) {
92 void* x;
93 (void)ptr;
94 x=malloc(size);
95 return(x);
96}
97
98void *memcpy(void *dest, const void *src, size_t n) {
99 return(rb->memcpy(dest,src,n));
100}
101
102void *memset(void *s, int c, size_t n) {
103 return(rb->memset(s,c,n));
104}
105
106int memcmp(const void *s1, const void *s2, size_t n) {
107 return(rb->memcmp(s1,s2,n));
108}
109
110void* memmove(const void *s1, const void *s2, size_t n) {
111 char* dest=(char*)s1;
112 char* src=(char*)s2;
113 size_t i;
114
115 for (i=0;i<n;i++) { dest[i]=src[i]; }
116 // while(n>0) { *(dest++)=*(src++); n--; }
117 return(dest);
118}
119
120void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)) {
121 rb->qsort(base,nmemb,size,compar);
122}
123
124 42
125void abort(void) { 43void abort(void) {
126 /* Let's hope this is never called by libmad */
127} 44}
128 45
129/* The "dither" code to convert the 24-bit samples produced by libmad was 46/* The "dither" code to convert the 24-bit samples produced by libmad was
@@ -206,60 +123,6 @@ signed int dither(mad_fixed_t sample, struct dither *dither)
206 123
207#define SHRT_MAX 32767 124#define SHRT_MAX 32767
208 125
209static unsigned char wav_header[44]={'R','I','F','F', // 0 - ChunkID
210 0,0,0,0, // 4 - ChunkSize (filesize-8)
211 'W','A','V','E', // 8 - Format
212 'f','m','t',' ', // 12 - SubChunkID
213 16,0,0,0, // 16 - SubChunk1ID // 16 for PCM
214 1,0, // 20 - AudioFormat (1=16-bit)
215 2,0, // 22 - NumChannels
216 0,0,0,0, // 24 - SampleRate in Hz
217 0,0,0,0, // 28 - Byte Rate (SampleRate*NumChannels*(BitsPerSample/8)
218 4,0, // 32 - BlockAlign (== NumChannels * BitsPerSample/8)
219 16,0, // 34 - BitsPerSample
220 'd','a','t','a', // 36 - Subchunk2ID
221 0,0,0,0 // 40 - Subchunk2Size
222 };
223
224void close_wav(file_info_struct* file_info) {
225 int x;
226 int filesize=rb->filesize(file_info->outfile);
227
228 /* We assume 16-bit, Stereo */
229
230 rb->lseek(file_info->outfile,0,SEEK_SET);
231
232 // ChunkSize
233 x=filesize-8;
234 wav_header[4]=(x&0xff);
235 wav_header[5]=(x&0xff00)>>8;
236 wav_header[6]=(x&0xff0000)>>16;
237 wav_header[7]=(x&0xff000000)>>24;
238
239 // Samplerate
240 wav_header[24]=file_info->samfmt.rate&0xff;
241 wav_header[25]=(file_info->samfmt.rate&0xff00)>>8;
242 wav_header[26]=(file_info->samfmt.rate&0xff0000)>>16;
243 wav_header[27]=(file_info->samfmt.rate&0xff000000)>>24;
244
245 // ByteRate
246 x=file_info->samfmt.rate*4;
247 wav_header[28]=(x&0xff);
248 wav_header[29]=(x&0xff00)>>8;
249 wav_header[30]=(x&0xff0000)>>16;
250 wav_header[31]=(x&0xff000000)>>24;
251
252 // Subchunk2Size
253 x=filesize-44;
254 wav_header[40]=(x&0xff);
255 wav_header[41]=(x&0xff00)>>8;
256 wav_header[42]=(x&0xff0000)>>16;
257 wav_header[43]=(x&0xff000000)>>24;
258
259 rb->write(file_info->outfile,wav_header,sizeof(wav_header));
260 rb->close(file_info->outfile);
261}
262
263#define INPUT_BUFFER_SIZE (5*8192) 126#define INPUT_BUFFER_SIZE (5*8192)
264#define OUTPUT_BUFFER_SIZE 8192 /* Must be an integer multiple of 4. */ 127#define OUTPUT_BUFFER_SIZE 8192 /* Must be an integer multiple of 4. */
265 128
@@ -272,29 +135,23 @@ const unsigned char *OutputBufferEnd=OutputBuffer+OUTPUT_BUFFER_SIZE;
272/* this is the plugin entry point */ 135/* this is the plugin entry point */
273enum plugin_status plugin_start(struct plugin_api* api, void* file) 136enum plugin_status plugin_start(struct plugin_api* api, void* file)
274{ 137{
275 int i,n,bytesleft; 138 file_info_struct file_info;
276 char s[32];
277 unsigned long ticks_taken;
278 unsigned long start_tick;
279 unsigned long long speed;
280 unsigned long xspeed;
281 long file_ptr;
282
283 int Status=0; 139 int Status=0;
284 unsigned long FrameCount=0; 140 unsigned short Sample;
141 int i;
142 size_t ReadSize, Remaining;
143 unsigned char *ReadStart;
285 144
286 TEST_PLUGIN_API(api); 145 /* Generic plugin inititialisation */
287 146
147 TEST_PLUGIN_API(api);
288 rb = api; 148 rb = api;
289 149
290 mem_ptr=0; 150 /* This function sets up the buffers and reads the file into RAM */
291 mp3buf=rb->plugin_get_mp3_buffer(&bufsize);
292 mallocbuf=mp3buf;
293 filebuf=&mp3buf[MALLOC_BUFSIZE];
294 151
295 rb->snprintf(s,32,"mp3 bufsize: %d",bufsize); 152 if (local_init(file,"/libmadtest.wav",&file_info)) {
296 rb->lcd_putsxy(0,100,s); 153 return PLUGIN_ERROR;
297 rb->lcd_update(); 154 }
298 155
299 /* Create a decoder instance */ 156 /* Create a decoder instance */
300 157
@@ -305,51 +162,14 @@ enum plugin_status plugin_start(struct plugin_api* api, void* file)
305 162
306 //if error: return PLUGIN_ERROR; 163 //if error: return PLUGIN_ERROR;
307 164
308 file_info.infile=rb->open(file,O_RDONLY);
309 file_info.outfile=rb->creat("/libmadtest.wav",O_WRONLY);
310 rb->write(file_info.outfile,wav_header,sizeof(wav_header));
311 file_info.curpos=0; 165 file_info.curpos=0;
312 file_info.filesize=rb->filesize(file_info.infile); 166 file_info.start_tick=*(rb->current_tick);
313
314 if (file_info.filesize > (bufsize-512*1024)) {
315 rb->close(file_info.infile);
316 rb->splash(HZ*2, true, "File too large");
317 return PLUGIN_ERROR;
318 }
319
320 rb->snprintf(s,32,"Loading file...");
321 rb->lcd_putsxy(0,0,s);
322 rb->lcd_update();
323
324 bytesleft=file_info.filesize;
325 i=0;
326 while (bytesleft > 0) {
327 n=rb->read(file_info.infile,&filebuf[i],bytesleft);
328 if (n < 0) {
329 rb->close(file_info.infile);
330 rb->splash(HZ*2, true, "ERROR READING FILE");
331 return PLUGIN_ERROR;
332 }
333 n+=i; bytesleft-=n;
334 }
335 rb->close(file_info.infile);
336
337 mad_stream_init(&Stream);
338 mad_frame_init(&Frame);
339 mad_synth_init(&Synth);
340 mad_timer_reset(&Timer);
341
342 file_ptr=0;
343 start_tick=*(rb->current_tick);
344 167
345 rb->button_clear_queue(); 168 rb->button_clear_queue();
346 169
347 /* This is the decoding loop. */ 170 /* This is the decoding loop. */
348 while (file_ptr < file_info.filesize) { 171 while (file_info.curpos < file_info.filesize) {
349 if(Stream.buffer==NULL || Stream.error==MAD_ERROR_BUFLEN) { 172 if(Stream.buffer==NULL || Stream.error==MAD_ERROR_BUFLEN) {
350 size_t ReadSize, Remaining;
351 unsigned char *ReadStart;
352
353 if(Stream.next_frame!=NULL) { 173 if(Stream.next_frame!=NULL) {
354 Remaining=Stream.bufend-Stream.next_frame; 174 Remaining=Stream.bufend-Stream.next_frame;
355 memmove(InputBuffer,Stream.next_frame,Remaining); 175 memmove(InputBuffer,Stream.next_frame,Remaining);
@@ -367,22 +187,20 @@ enum plugin_status plugin_start(struct plugin_api* api, void* file)
367 * left untouched. 187 * left untouched.
368 */ 188 */
369 189
370 if ((file_info.filesize-file_ptr) < (int) ReadSize) { 190 if ((file_info.filesize-file_info.curpos) < (int) ReadSize) {
371 ReadSize=file_info.filesize-file_ptr; 191 ReadSize=file_info.filesize-file_info.curpos;
372 } 192 }
373 memcpy(ReadStart,&filebuf[file_ptr],ReadSize); 193 memcpy(ReadStart,&filebuf[file_info.curpos],ReadSize);
374 file_ptr+=ReadSize; 194 file_info.curpos+=ReadSize;
375 195
376 if (file_ptr >= file_info.filesize) 196 if (file_info.curpos >= file_info.filesize)
377 { 197 {
378 GuardPtr=ReadStart+ReadSize; 198 GuardPtr=ReadStart+ReadSize;
379 memset(GuardPtr,0,MAD_BUFFER_GUARD); 199 memset(GuardPtr,0,MAD_BUFFER_GUARD);
380 ReadSize+=MAD_BUFFER_GUARD; 200 ReadSize+=MAD_BUFFER_GUARD;
381 } 201 }
382 202
383 /* Pipe the new buffer content to libmad's stream decoder 203 /* Pipe the new buffer content to libmad's stream decoder facility */
384 * facility.
385 */
386 mad_stream_buffer(&Stream,InputBuffer,ReadSize+Remaining); 204 mad_stream_buffer(&Stream,InputBuffer,ReadSize+Remaining);
387 Stream.error=0; 205 Stream.error=0;
388 } 206 }
@@ -410,11 +228,12 @@ enum plugin_status plugin_start(struct plugin_api* api, void* file)
410 } 228 }
411 229
412 /* We assume all frames have same samplerate as the first */ 230 /* We assume all frames have same samplerate as the first */
413 if(FrameCount==0) { 231 if(file_info.frames_decoded==0) {
414 file_info.samfmt.rate=Frame.header.samplerate; 232 file_info.samplerate=Frame.header.samplerate;
415 } 233 }
416 234
417 FrameCount++; 235 file_info.frames_decoded++;
236
418 /* ?? Do we need the timer module? */ 237 /* ?? Do we need the timer module? */
419 mad_timer_add(&Timer,Frame.header.duration); 238 mad_timer_add(&Timer,Frame.header.duration);
420 239
@@ -427,8 +246,6 @@ enum plugin_status plugin_start(struct plugin_api* api, void* file)
427 /* Convert MAD's numbers to an array of 16-bit LE signed integers */ 246 /* Convert MAD's numbers to an array of 16-bit LE signed integers */
428 for(i=0;i<Synth.pcm.length;i++) 247 for(i=0;i<Synth.pcm.length;i++)
429 { 248 {
430 unsigned short Sample;
431
432 /* Left channel */ 249 /* Left channel */
433 Sample=scale(Synth.pcm.samples[0][i],&d0); 250 Sample=scale(Synth.pcm.samples[0][i],&d0);
434 *(OutputPtr++)=Sample&0xff; 251 *(OutputPtr++)=Sample&0xff;
@@ -450,26 +267,10 @@ enum plugin_status plugin_start(struct plugin_api* api, void* file)
450 } 267 }
451 } 268 }
452 269
453 rb->snprintf(s,32,"Bytes Read: %d ",file_ptr);
454 rb->lcd_putsxy(0,0,s);
455
456 rb->snprintf(s,32,"Samples Decoded: %d",file_info.current_sample);
457 rb->lcd_putsxy(0,20,s);
458 rb->snprintf(s,32,"Frames Decoded: %d",FrameCount);
459 rb->lcd_putsxy(0,40,s);
460
461 file_info.current_sample+=Synth.pcm.length; 270 file_info.current_sample+=Synth.pcm.length;
462 271
463 ticks_taken=*(rb->current_tick)-start_tick; 272 display_status(&file_info);
464
465 if (ticks_taken==0) { ticks_taken=1; } // Avoid fp exception.
466
467 speed=(100*file_info.current_sample)/file_info.samfmt.rate;
468 xspeed=(speed*10000)/ticks_taken;
469 rb->snprintf(s,32,"Speed %ld.%02ld%% Secs: %d",(xspeed/100),(xspeed%100),ticks_taken/100);
470 rb->lcd_putsxy(0,60,s);
471 273
472 rb->lcd_update();
473 if (rb->button_get(false)!=BUTTON_NONE) { 274 if (rb->button_get(false)!=BUTTON_NONE) {
474 close_wav(&file_info); 275 close_wav(&file_info);
475 return PLUGIN_OK; 276 return PLUGIN_OK;