summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/a52towav.c312
-rw-r--r--apps/plugins/xxx2wav.h240
2 files changed, 278 insertions, 274 deletions
diff --git a/apps/plugins/a52towav.c b/apps/plugins/a52towav.c
index 17b6c91e51..552479b0b0 100644
--- a/apps/plugins/a52towav.c
+++ b/apps/plugins/a52towav.c
@@ -7,7 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2002 Björn Stenberg 10 * Copyright (C) 2005 Dave Chapman
11 * 11 *
12 * All files in this archive are subject to the GNU General Public License. 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. 13 * See the file COPYING in the source tree root for full license agreement.
@@ -27,7 +27,18 @@
27#include <codecs/liba52/config.h> 27#include <codecs/liba52/config.h>
28#include <codecs/liba52/a52.h> 28#include <codecs/liba52/a52.h>
29 29
30/* Currently used for WAV output */ 30static struct plugin_api* rb;
31
32/* Helper functions common to all decoder test viewers (uses rb) */
33
34#include "xxx2wav.h"
35
36/* FIX: We can remove this warning when the build system has a
37 mechanism for auto-detecting the endianness of the target CPU -
38 WORDS_BIGENDIAN is defined in liba52/config.h and is also used
39 internally by liba52.
40 */
41
31#ifdef WORDS_BIGENDIAN 42#ifdef WORDS_BIGENDIAN
32 #warning ************************************* BIG ENDIAN 43 #warning ************************************* BIG ENDIAN
33 #define LE_S16(x) ( (uint16_t) ( ((uint16_t)(x) >> 8) | ((uint16_t)(x) << 8) ) ) 44 #define LE_S16(x) ( (uint16_t) ( ((uint16_t)(x) >> 8) | ((uint16_t)(x) << 8) ) )
@@ -35,192 +46,16 @@
35 #define LE_S16(x) (x) 46 #define LE_S16(x) (x)
36#endif 47#endif
37 48
38typedef struct ao_sample_format {
39 int bits; /* bits per sample */
40 int rate; /* samples per second (in a single channel) */
41 int channels; /* number of audio channels */
42 int byte_format; /* Byte ordering in sample, see constants below */
43} ao_sample_format;
44
45#define AO_FMT_LITTLE 1
46#define AO_FMT_BIG 2
47#define AO_FMT_NATIVE 4
48
49/* the main data structure of the program */
50typedef struct {
51 int infile;
52 int outfile;
53 off_t curpos;
54 off_t filesize;
55 ao_sample_format samfmt; /* bits, rate, channels, byte_format */
56 // ao_device *ao_dev;
57 unsigned long total_samples;
58 unsigned long current_sample;
59 float total_time; /* seconds */
60 float elapsed_time; /* seconds */
61} file_info_struct;
62
63file_info_struct file_info;
64
65#define MALLOC_BUFSIZE (512*1024)
66 49
67int mem_ptr;
68int bufsize;
69unsigned char* mp3buf; // The actual MP3 buffer from Rockbox
70unsigned char* mallocbuf; // 512K from the start of MP3 buffer
71unsigned char* filebuf; // The rest of the MP3 buffer
72
73
74
75#define BUFFER_SIZE 4096
76//static uint8_t buffer[BUFFER_SIZE];
77static float gain = 1; 50static float gain = 1;
78static a52_state_t * state; 51static a52_state_t * state;
79 52
80int output;
81
82// DAVE: I'm not sure what these are for.
83int disable_accel=0;
84int disable_adjust=0;
85int disable_dynrng=0;
86
87/* welcome to the example rockbox plugin */
88
89/* here is a global api struct pointer. while not strictly necessary,
90 it's nice not to have to pass the api pointer in all function calls
91 in the plugin */
92static struct plugin_api* rb;
93
94void* malloc(size_t size) {
95 void* x;
96 char s[32];
97
98 x=&mallocbuf[mem_ptr];
99 mem_ptr+=size+(size%4); // Keep memory 32-bit aligned (if it was already?)
100
101 rb->snprintf(s,30,"Memory used: %d\r",mem_ptr);
102 rb->lcd_putsxy(0,80,s);
103 rb->lcd_update();
104 return(x);
105}
106
107void* calloc(size_t nmemb, size_t size) {
108 void* x;
109 x=malloc(nmemb*size);
110 rb->memset(x,0,nmemb*size);
111 return(x);
112}
113
114void free(void* ptr) {
115 (void)ptr;
116}
117
118void* realloc(void* ptr, size_t size) {
119 void* x;
120 (void)ptr;
121 x=malloc(size);
122 return(x);
123}
124
125void *memcpy(void *dest, const void *src, size_t n) {
126 return(rb->memcpy(dest,src,n));
127}
128
129void *memset(void *s, int c, size_t n) {
130 return(rb->memset(s,c,n));
131}
132
133int memcmp(const void *s1, const void *s2, size_t n) {
134 return(rb->memcmp(s1,s2,n));
135}
136
137void* memmove(const void *s1, const void *s2, size_t n) {
138 char* dest=(char*)s1;
139 char* src=(char*)s2;
140 size_t i;
141
142 for (i=0;i<n;i++) { dest[i]=src[i]; }
143 // while(n>0) { *(dest++)=*(src++); n--; }
144 return(dest);
145}
146
147void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)) {
148 rb->qsort(base,nmemb,size,compar);
149}
150
151
152
153
154static unsigned char wav_header[44]={'R','I','F','F', // 0 - ChunkID
155 0,0,0,0, // 4 - ChunkSize (filesize-8)
156 'W','A','V','E', // 8 - Format
157 'f','m','t',' ', // 12 - SubChunkID
158 16,0,0,0, // 16 - SubChunk1ID // 16 for PCM
159 1,0, // 20 - AudioFormat (1=16-bit)
160 2,0, // 22 - NumChannels
161 0,0,0,0, // 24 - SampleRate in Hz
162 0,0,0,0, // 28 - Byte Rate (SampleRate*NumChannels*(BitsPerSample/8)
163 4,0, // 32 - BlockAlign (== NumChannels * BitsPerSample/8)
164 16,0, // 34 - BitsPerSample
165 'd','a','t','a', // 36 - Subchunk2ID
166 0,0,0,0 // 40 - Subchunk2Size
167 };
168
169void close_wav(file_info_struct* file_info) {
170 int x;
171 int filesize=rb->filesize(file_info->outfile);
172
173 /* We assume 16-bit, Stereo */
174
175 rb->lseek(file_info->outfile,0,SEEK_SET);
176
177 // ChunkSize
178 x=filesize-8;
179 wav_header[4]=(x&0xff);
180 wav_header[5]=(x&0xff00)>>8;
181 wav_header[6]=(x&0xff0000)>>16;
182 wav_header[7]=(x&0xff000000)>>24;
183
184 // Samplerate
185 wav_header[24]=file_info->samfmt.rate&0xff;
186 wav_header[25]=(file_info->samfmt.rate&0xff00)>>8;
187 wav_header[26]=(file_info->samfmt.rate&0xff0000)>>16;
188 wav_header[27]=(file_info->samfmt.rate&0xff000000)>>24;
189
190 // ByteRate
191 x=file_info->samfmt.rate*4;
192 wav_header[28]=(x&0xff);
193 wav_header[29]=(x&0xff00)>>8;
194 wav_header[30]=(x&0xff0000)>>16;
195 wav_header[31]=(x&0xff000000)>>24;
196
197 // Subchunk2Size
198 x=filesize-44;
199 wav_header[40]=(x&0xff);
200 wav_header[41]=(x&0xff00)>>8;
201 wav_header[42]=(x&0xff0000)>>16;
202 wav_header[43]=(x&0xff000000)>>24;
203
204 rb->write(file_info->outfile,wav_header,sizeof(wav_header));
205 rb->close(file_info->outfile);
206}
207
208static inline int16_t convert (int32_t i) 53static inline int16_t convert (int32_t i)
209{ 54{
210 i >>= 15; 55 i >>= 15;
211 return (i > 32767) ? 32767 : ((i < -32768) ? -32768 : i); 56 return (i > 32767) ? 32767 : ((i < -32768) ? -32768 : i);
212} 57}
213 58
214void convert2s16_2 (sample_t * _f, int16_t * s16)
215{
216 int i;
217 int32_t * f = (int32_t *) _f;
218 for (i = 0; i < 256; i++) {
219 s16[2*i] = LE_S16(convert (f[i]));
220 s16[2*i+1] = LE_S16(convert (f[i+256]));
221 }
222}
223
224void ao_play(file_info_struct* file_info,sample_t* samples,int flags) { 59void ao_play(file_info_struct* file_info,sample_t* samples,int flags) {
225 int i; 60 int i;
226 static int16_t int16_samples[256*2]; 61 static int16_t int16_samples[256*2];
@@ -228,7 +63,6 @@ void ao_play(file_info_struct* file_info,sample_t* samples,int flags) {
228 flags &= A52_CHANNEL_MASK | A52_LFE; 63 flags &= A52_CHANNEL_MASK | A52_LFE;
229 64
230 if (flags==A52_STEREO) { 65 if (flags==A52_STEREO) {
231// convert2s16_2(samples,int16_samples,flags);
232 for (i = 0; i < 256; i++) { 66 for (i = 0; i < 256; i++) {
233 int16_samples[2*i] = LE_S16(convert (samples[i])); 67 int16_samples[2*i] = LE_S16(convert (samples[i]));
234 int16_samples[2*i+1] = LE_S16(convert (samples[i+256])); 68 int16_samples[2*i+1] = LE_S16(convert (samples[i+256]));
@@ -239,13 +73,8 @@ void ao_play(file_info_struct* file_info,sample_t* samples,int flags) {
239#endif 73#endif
240 } 74 }
241 75
76 /* FIX: Buffer the disk write to write larger amounts at one */
242 i=rb->write(file_info->outfile,int16_samples,256*2*2); 77 i=rb->write(file_info->outfile,int16_samples,256*2*2);
243
244#ifdef SIMULATOR
245 if (i!=(256*2*2)) {
246 fprintf(stderr,"Attempted to write %d bytes, wrote %d bytes\n",256*2*2,i);
247 }
248#endif
249} 78}
250 79
251 80
@@ -304,13 +133,10 @@ void a52_decode_data (file_info_struct* file_info, uint8_t * start, uint8_t * en
304 133
305 if (a52_frame (state, buf, &flags, &level, bias)) 134 if (a52_frame (state, buf, &flags, &level, bias))
306 goto error; 135 goto error;
136 file_info->frames_decoded++;
307 137
308 if (output==0) { 138 /* We assume this never changes */
309 file_info->samfmt.bits=16; 139 file_info->samplerate=sample_rate;
310 file_info->samfmt.rate=sample_rate;
311 output=1;
312// output=ao_open(&format);
313 }
314 140
315 // An A52 frame consists of 6 blocks of 256 samples 141 // An A52 frame consists of 6 blocks of 256 samples
316 // So we decode and output them one block at a time 142 // So we decode and output them one block at a time
@@ -323,7 +149,6 @@ void a52_decode_data (file_info_struct* file_info, uint8_t * start, uint8_t * en
323 } 149 }
324 bufptr = buf; 150 bufptr = buf;
325 bufpos = buf + 7; 151 bufpos = buf + 7;
326// print_fps (0);
327 continue; 152 continue;
328 error: 153 error:
329#ifdef SIMULATOR 154#ifdef SIMULATOR
@@ -336,111 +161,47 @@ void a52_decode_data (file_info_struct* file_info, uint8_t * start, uint8_t * en
336 } 161 }
337} 162}
338 163
164
165#define BUFFER_SIZE 4096
166
339/* this is the plugin entry point */ 167/* this is the plugin entry point */
340enum plugin_status plugin_start(struct plugin_api* api, void* file) 168enum plugin_status plugin_start(struct plugin_api* api, void* file)
341{ 169{
342 int i,n,bytesleft; 170 /* Generic plugin initialisation */
343 char s[32];
344 unsigned long ticks_taken;
345 unsigned long start_tick;
346 unsigned long long speed;
347 unsigned long xspeed;
348 int accel=0; // ??? This is the parameter to a52_init().
349
350 /* this macro should be called as the first thing you do in the plugin.
351 it test that the api version and model the plugin was compiled for
352 matches the machine it is running on */
353 TEST_PLUGIN_API(api);
354 171
355 /* if you are using a global api pointer, don't forget to copy it! 172 TEST_PLUGIN_API(api);
356 otherwise you will get lovely "I04: IllInstr" errors... :-) */
357 rb = api; 173 rb = api;
358 174
359 /* now go ahead and have fun! */
360 // rb->splash(HZ*2, true, "Hello world!");
361 175
362 mem_ptr=0; 176 /* This function sets up the buffers and reads the file into RAM */
363 mp3buf=rb->plugin_get_mp3_buffer(&bufsize);
364 mallocbuf=mp3buf;
365 filebuf=&mp3buf[MALLOC_BUFSIZE];
366 177
367 rb->snprintf(s,32,"mp3 bufsize: %d\r",bufsize); 178 if (local_init(file,&file_info)) {
368 rb->lcd_putsxy(0,100,s);
369 rb->lcd_update();
370
371 file_info.infile=rb->open(file,O_RDONLY);
372 file_info.outfile=rb->creat("/ac3test.wav",O_WRONLY);
373 rb->write(file_info.outfile,wav_header,sizeof(wav_header));
374 file_info.curpos=0;
375 file_info.filesize=rb->filesize(file_info.infile);
376
377 if (file_info.filesize > (bufsize-MALLOC_BUFSIZE)) {
378 rb->close(file_info.infile);
379 rb->splash(HZ*2, true, "File too large");
380 return PLUGIN_ERROR; 179 return PLUGIN_ERROR;
381 } 180 }
382 181
383 rb->snprintf(s,32,"Loading file..."); 182 /* Intialise the A52 decoder and check for success */
384 rb->lcd_putsxy(0,0,s); 183 state = a52_init (0); // Parameter is "accel"
385 rb->lcd_update();
386
387 bytesleft=file_info.filesize;
388 i=0;
389 while (bytesleft > 0) {
390 n=rb->read(file_info.infile,&filebuf[i],bytesleft);
391 if (n < 0) {
392 rb->close(file_info.infile);
393 rb->splash(HZ*2, true, "ERROR READING FILE");
394 return PLUGIN_ERROR;
395 }
396 i+=n; bytesleft-=n;
397 }
398 rb->close(file_info.infile);
399 184
400 state = a52_init (accel);
401 if (state == NULL) { 185 if (state == NULL) {
402 //fprintf (stderr, "A52 init failed\n"); 186 rb->splash(HZ*2, true, "a52_init failed");
403 return PLUGIN_ERROR; 187 return PLUGIN_ERROR;
404 } 188 }
405 189
406 i=0; 190 /* The main decoding loop */
407 start_tick=*(rb->current_tick); 191
192 file_info.start_tick=*(rb->current_tick);
408 while (file_info.curpos < file_info.filesize) { 193 while (file_info.curpos < file_info.filesize) {
409 i++; 194
410 if ((file_info.curpos+BUFFER_SIZE) < file_info.filesize) { 195 if ((file_info.curpos+BUFFER_SIZE) < file_info.filesize) {
411 a52_decode_data (&file_info,&filebuf[file_info.curpos],&filebuf[file_info.curpos+BUFFER_SIZE]); 196 a52_decode_data(&file_info,&filebuf[file_info.curpos],&filebuf[file_info.curpos+BUFFER_SIZE]);
412 file_info.curpos+=BUFFER_SIZE; 197 file_info.curpos+=BUFFER_SIZE;
413 } else { 198 } else {
414 a52_decode_data (&file_info,&filebuf[file_info.curpos],&filebuf[file_info.filesize-1]); 199 a52_decode_data(&file_info,&filebuf[file_info.curpos],&filebuf[file_info.filesize-1]);
415 file_info.curpos=file_info.filesize; 200 file_info.curpos=file_info.filesize;
416 } 201 }
417 202
418 rb->snprintf(s,32,"Bytes read: %d\r",file_info.curpos); 203 display_status(&file_info);
419 rb->lcd_putsxy(0,0,s);
420 rb->snprintf(s,32,"Samples Decoded: %d\r",file_info.current_sample);
421 rb->lcd_putsxy(0,20,s);
422 rb->snprintf(s,32,"Frames Decoded: %d\r",i);
423 rb->lcd_putsxy(0,40,s);
424
425 ticks_taken=*(rb->current_tick)-start_tick;
426
427 /* e.g.:
428 ticks_taken=500
429 sam_fmt.rate=44,100
430 samples_decoded=172,400
431 (samples_decoded/sam_fmt.rate)*100=400 (time it should have taken)
432 % Speed=(400/500)*100=80%
433
434 */
435 204
436 if (ticks_taken==0) { ticks_taken=1; } // Avoid fp exception.
437
438 speed=(100*file_info.current_sample)/file_info.samfmt.rate;
439 xspeed=(speed*10000)/ticks_taken;
440 rb->snprintf(s,32,"Speed %ld.%02ld %% Secs: %d",(xspeed/100),(xspeed%100),ticks_taken/100);
441 rb->lcd_putsxy(0,60,s);
442
443 rb->lcd_update();
444 if (rb->button_get(false)!=BUTTON_NONE) { 205 if (rb->button_get(false)!=BUTTON_NONE) {
445 close_wav(&file_info); 206 close_wav(&file_info);
446 return PLUGIN_OK; 207 return PLUGIN_OK;
@@ -448,7 +209,10 @@ enum plugin_status plugin_start(struct plugin_api* api, void* file)
448 } 209 }
449 close_wav(&file_info); 210 close_wav(&file_info);
450 211
451//NO NEED: a52_free (state); 212 /* Cleanly close and exit */
213
214//NOT NEEDED: a52_free (state);
215
452 rb->splash(HZ*2, true, "FINISHED!"); 216 rb->splash(HZ*2, true, "FINISHED!");
453 return PLUGIN_OK; 217 return PLUGIN_OK;
454} 218}
diff --git a/apps/plugins/xxx2wav.h b/apps/plugins/xxx2wav.h
new file mode 100644
index 0000000000..96942824fd
--- /dev/null
+++ b/apps/plugins/xxx2wav.h
@@ -0,0 +1,240 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 Dave Chapman
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/* Various "helper functions" common to all the xxx2wav decoder plugins
21
22 We include them as a .h because the plugin build system links
23 exactly one .c file with exactly one .rock file.
24 */
25
26
27/* the main data structure of the program */
28typedef struct {
29 int infile;
30 int outfile;
31 off_t curpos;
32 off_t filesize;
33 int samplerate;
34 int channels;
35 int frames_decoded;
36 unsigned long total_samples;
37 unsigned long current_sample;
38 unsigned long start_tick;
39} file_info_struct;
40
41file_info_struct file_info;
42
43#define MALLOC_BUFSIZE (512*1024)
44
45int mem_ptr;
46int bufsize;
47unsigned char* mp3buf; // The actual MP3 buffer from Rockbox
48unsigned char* mallocbuf; // 512K from the start of MP3 buffer
49unsigned char* filebuf; // The rest of the MP3 buffer
50
51void* malloc(size_t size) {
52 void* x;
53 char s[32];
54
55 x=&mallocbuf[mem_ptr];
56 mem_ptr+=size+(size%4); // Keep memory 32-bit aligned (if it was already?)
57
58 rb->snprintf(s,30,"Memory used: %d\r",mem_ptr);
59 rb->lcd_putsxy(0,80,s);
60 rb->lcd_update();
61 return(x);
62}
63
64void* calloc(size_t nmemb, size_t size) {
65 void* x;
66 x=malloc(nmemb*size);
67 rb->memset(x,0,nmemb*size);
68 return(x);
69}
70
71void free(void* ptr) {
72 (void)ptr;
73}
74
75void* realloc(void* ptr, size_t size) {
76 void* x;
77 (void)ptr;
78 x=malloc(size);
79 return(x);
80}
81
82void *memcpy(void *dest, const void *src, size_t n) {
83 return(rb->memcpy(dest,src,n));
84}
85
86void *memset(void *s, int c, size_t n) {
87 return(rb->memset(s,c,n));
88}
89
90int memcmp(const void *s1, const void *s2, size_t n) {
91 return(rb->memcmp(s1,s2,n));
92}
93
94void* memmove(const void *s1, const void *s2, size_t n) {
95 char* dest=(char*)s1;
96 char* src=(char*)s2;
97 size_t i;
98
99 for (i=0;i<n;i++) { dest[i]=src[i]; }
100 // while(n>0) { *(dest++)=*(src++); n--; }
101 return(dest);
102}
103
104void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)) {
105 rb->qsort(base,nmemb,size,compar);
106}
107
108void display_status(file_info_struct* file_info) {
109 char s[32];
110 unsigned long ticks_taken;
111 unsigned long long speed;
112 unsigned long xspeed;
113
114 rb->snprintf(s,32,"Bytes read: %d\r",file_info->curpos);
115 rb->lcd_putsxy(0,0,s);
116 rb->snprintf(s,32,"Samples Decoded: %d\r",file_info->current_sample);
117 rb->lcd_putsxy(0,20,s);
118 rb->snprintf(s,32,"Frames Decoded: %d\r",file_info->frames_decoded);
119 rb->lcd_putsxy(0,40,s);
120
121 ticks_taken=*(rb->current_tick)-file_info->start_tick;
122
123 /* e.g.:
124 ticks_taken=500
125 sam_fmt.rate=44,100
126 samples_decoded=172,400
127 (samples_decoded/sam_fmt.rate)*100=400 (time it should have taken)
128 % Speed=(400/500)*100=80%
129 */
130
131 if (ticks_taken==0) { ticks_taken=1; } // Avoid fp exception.
132
133 speed=(100*file_info->current_sample)/file_info->samplerate;
134 xspeed=(speed*10000)/ticks_taken;
135 rb->snprintf(s,32,"Speed %ld.%02ld %% Secs: %d",(xspeed/100),(xspeed%100),ticks_taken/100);
136 rb->lcd_putsxy(0,60,s);
137
138 rb->lcd_update();
139}
140
141static unsigned char wav_header[44]={'R','I','F','F', // 0 - ChunkID
142 0,0,0,0, // 4 - ChunkSize (filesize-8)
143 'W','A','V','E', // 8 - Format
144 'f','m','t',' ', // 12 - SubChunkID
145 16,0,0,0, // 16 - SubChunk1ID // 16 for PCM
146 1,0, // 20 - AudioFormat (1=16-bit)
147 2,0, // 22 - NumChannels
148 0,0,0,0, // 24 - SampleRate in Hz
149 0,0,0,0, // 28 - Byte Rate (SampleRate*NumChannels*(BitsPerSample/8)
150 4,0, // 32 - BlockAlign (== NumChannels * BitsPerSample/8)
151 16,0, // 34 - BitsPerSample
152 'd','a','t','a', // 36 - Subchunk2ID
153 0,0,0,0 // 40 - Subchunk2Size
154 };
155
156
157int local_init(char* file, file_info_struct* file_info) {
158 char s[32];
159 int i,n,bytesleft;
160
161 mem_ptr=0;
162 mp3buf=rb->plugin_get_mp3_buffer(&bufsize);
163 mallocbuf=mp3buf;
164 filebuf=&mp3buf[MALLOC_BUFSIZE];
165
166 rb->snprintf(s,32,"mp3 bufsize: %d\r",bufsize);
167 rb->lcd_putsxy(0,100,s);
168 rb->lcd_update();
169
170 file_info->infile=rb->open(file,O_RDONLY);
171 file_info->outfile=rb->creat("/ac3test.wav",O_WRONLY);
172 rb->write(file_info->outfile,wav_header,sizeof(wav_header));
173 file_info->curpos=0;
174 file_info->frames_decoded=0;
175 file_info->filesize=rb->filesize(file_info->infile);
176
177 if (file_info->filesize > (bufsize-MALLOC_BUFSIZE)) {
178 rb->close(file_info->infile);
179 rb->splash(HZ*2, true, "File too large");
180 return(1);
181 }
182
183 rb->snprintf(s,32,"Loading file...");
184 rb->lcd_putsxy(0,0,s);
185 rb->lcd_update();
186
187 bytesleft=file_info->filesize;
188 i=0;
189 while (bytesleft > 0) {
190 n=rb->read(file_info->infile,&filebuf[i],bytesleft);
191 if (n < 0) {
192 rb->close(file_info->infile);
193 rb->splash(HZ*2, true, "ERROR READING FILE");
194 return(1);
195 }
196 i+=n; bytesleft-=n;
197 }
198 rb->close(file_info->infile);
199 return(0);
200}
201
202void close_wav(file_info_struct* file_info) {
203 int x;
204 int filesize=rb->filesize(file_info->outfile);
205
206 /* We assume 16-bit, Stereo */
207
208 rb->lseek(file_info->outfile,0,SEEK_SET);
209
210 // ChunkSize
211 x=filesize-8;
212 wav_header[4]=(x&0xff);
213 wav_header[5]=(x&0xff00)>>8;
214 wav_header[6]=(x&0xff0000)>>16;
215 wav_header[7]=(x&0xff000000)>>24;
216
217 // Samplerate
218 wav_header[24]=file_info->samplerate&0xff;
219 wav_header[25]=(file_info->samplerate&0xff00)>>8;
220 wav_header[26]=(file_info->samplerate&0xff0000)>>16;
221 wav_header[27]=(file_info->samplerate&0xff000000)>>24;
222
223 // ByteRate
224 x=file_info->samplerate*4;
225 wav_header[28]=(x&0xff);
226 wav_header[29]=(x&0xff00)>>8;
227 wav_header[30]=(x&0xff0000)>>16;
228 wav_header[31]=(x&0xff000000)>>24;
229
230 // Subchunk2Size
231 x=filesize-44;
232 wav_header[40]=(x&0xff);
233 wav_header[41]=(x&0xff00)>>8;
234 wav_header[42]=(x&0xff0000)>>16;
235 wav_header[43]=(x&0xff000000)>>24;
236
237 rb->write(file_info->outfile,wav_header,sizeof(wav_header));
238 rb->close(file_info->outfile);
239}
240