diff options
Diffstat (limited to 'apps/plugins/mpa2wav.c')
-rw-r--r-- | apps/plugins/mpa2wav.c | 269 |
1 files changed, 0 insertions, 269 deletions
diff --git a/apps/plugins/mpa2wav.c b/apps/plugins/mpa2wav.c deleted file mode 100644 index bf40fa3b81..0000000000 --- a/apps/plugins/mpa2wav.c +++ /dev/null | |||
@@ -1,269 +0,0 @@ | |||
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 | #include "plugin.h" | ||
21 | |||
22 | #if (CONFIG_HWCODEC == MASNONE) | ||
23 | /* software codec platforms */ | ||
24 | |||
25 | #include <codecs/libmad/mad.h> | ||
26 | |||
27 | #include "lib/xxx2wav.h" /* Helper functions common to test decoders */ | ||
28 | |||
29 | static struct plugin_api* rb; | ||
30 | |||
31 | struct mad_stream Stream IDATA_ATTR; | ||
32 | struct mad_frame Frame IDATA_ATTR; | ||
33 | struct mad_synth Synth IDATA_ATTR; | ||
34 | mad_timer_t Timer; | ||
35 | struct dither d0, d1; | ||
36 | |||
37 | /* The following function is used inside libmad - let's hope it's never | ||
38 | called. | ||
39 | */ | ||
40 | |||
41 | void abort(void) { | ||
42 | } | ||
43 | |||
44 | /* The "dither" code to convert the 24-bit samples produced by libmad was | ||
45 | taken from the coolplayer project - coolplayer.sourceforge.net */ | ||
46 | |||
47 | struct dither { | ||
48 | mad_fixed_t error[3]; | ||
49 | mad_fixed_t random; | ||
50 | }; | ||
51 | |||
52 | # define SAMPLE_DEPTH 16 | ||
53 | # define scale(x, y) dither((x), (y)) | ||
54 | |||
55 | /* | ||
56 | * NAME: prng() | ||
57 | * DESCRIPTION: 32-bit pseudo-random number generator | ||
58 | */ | ||
59 | static __inline | ||
60 | unsigned long prng(unsigned long state) | ||
61 | { | ||
62 | return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL; | ||
63 | } | ||
64 | |||
65 | /* | ||
66 | * NAME: dither() | ||
67 | * DESCRIPTION: dither and scale sample | ||
68 | */ | ||
69 | static __inline | ||
70 | signed int dither(mad_fixed_t sample, struct dither *dither) | ||
71 | { | ||
72 | unsigned int scalebits; | ||
73 | mad_fixed_t output, mask, random; | ||
74 | |||
75 | enum { | ||
76 | MIN = -MAD_F_ONE, | ||
77 | MAX = MAD_F_ONE - 1 | ||
78 | }; | ||
79 | |||
80 | /* noise shape */ | ||
81 | sample += dither->error[0] - dither->error[1] + dither->error[2]; | ||
82 | |||
83 | dither->error[2] = dither->error[1]; | ||
84 | dither->error[1] = dither->error[0] / 2; | ||
85 | |||
86 | /* bias */ | ||
87 | output = sample + (1L << (MAD_F_FRACBITS + 1 - SAMPLE_DEPTH - 1)); | ||
88 | |||
89 | scalebits = MAD_F_FRACBITS + 1 - SAMPLE_DEPTH; | ||
90 | mask = (1L << scalebits) - 1; | ||
91 | |||
92 | /* dither */ | ||
93 | random = prng(dither->random); | ||
94 | output += (random & mask) - (dither->random & mask); | ||
95 | |||
96 | dither->random = random; | ||
97 | |||
98 | /* clip */ | ||
99 | if (output > MAX) { | ||
100 | output = MAX; | ||
101 | |||
102 | if (sample > MAX) | ||
103 | sample = MAX; | ||
104 | } | ||
105 | else if (output < MIN) { | ||
106 | output = MIN; | ||
107 | |||
108 | if (sample < MIN) | ||
109 | sample = MIN; | ||
110 | } | ||
111 | |||
112 | /* quantize */ | ||
113 | output &= ~mask; | ||
114 | |||
115 | /* error feedback */ | ||
116 | dither->error[0] = sample - output; | ||
117 | |||
118 | /* scale */ | ||
119 | return output >> scalebits; | ||
120 | } | ||
121 | |||
122 | #define SHRT_MAX 32767 | ||
123 | |||
124 | #define INPUT_BUFFER_SIZE (10*8192) | ||
125 | #define OUTPUT_BUFFER_SIZE 65536 /* Must be an integer multiple of 4. */ | ||
126 | |||
127 | unsigned char InputBuffer[INPUT_BUFFER_SIZE+MAD_BUFFER_GUARD]; | ||
128 | unsigned char OutputBuffer[OUTPUT_BUFFER_SIZE]; | ||
129 | unsigned char *OutputPtr=OutputBuffer; | ||
130 | unsigned char *GuardPtr=NULL; | ||
131 | const unsigned char *OutputBufferEnd=OutputBuffer+OUTPUT_BUFFER_SIZE; | ||
132 | |||
133 | mad_fixed_t mad_frame_overlap[2][32][18] IDATA_ATTR; | ||
134 | unsigned char mad_main_data[MAD_BUFFER_MDLEN] IDATA_ATTR; | ||
135 | |||
136 | #ifdef USE_IRAM | ||
137 | extern char iramcopy[]; | ||
138 | extern char iramstart[]; | ||
139 | extern char iramend[]; | ||
140 | #endif | ||
141 | |||
142 | /* this is the plugin entry point */ | ||
143 | enum plugin_status plugin_start(struct plugin_api* api, void* file) | ||
144 | { | ||
145 | file_info_struct file_info; | ||
146 | int Status=0; | ||
147 | unsigned short Sample; | ||
148 | int i; | ||
149 | |||
150 | /* Generic plugin inititialisation */ | ||
151 | |||
152 | TEST_PLUGIN_API(api); | ||
153 | rb = api; | ||
154 | |||
155 | #ifdef USE_IRAM | ||
156 | rb->memcpy(iramstart, iramcopy, iramend-iramstart); | ||
157 | #endif | ||
158 | |||
159 | /* This function sets up the buffers and reads the file into RAM */ | ||
160 | |||
161 | if (local_init(file,"/libmadtest.wav",&file_info,api)) { | ||
162 | return PLUGIN_ERROR; | ||
163 | } | ||
164 | |||
165 | /* Create a decoder instance */ | ||
166 | |||
167 | mad_stream_init(&Stream); | ||
168 | mad_frame_init(&Frame); | ||
169 | mad_synth_init(&Synth); | ||
170 | mad_timer_reset(&Timer); | ||
171 | |||
172 | /* We do this so libmad doesn't try to call codec_calloc() */ | ||
173 | memset(mad_frame_overlap, 0, sizeof(mad_frame_overlap)); | ||
174 | Frame.overlap = &mad_frame_overlap; | ||
175 | Stream.main_data = &mad_main_data; | ||
176 | |||
177 | GuardPtr = &filebuf[file_info.filesize]; | ||
178 | memset(GuardPtr,0,MAD_BUFFER_GUARD); | ||
179 | mad_stream_buffer(&Stream, filebuf,file_info.filesize); | ||
180 | |||
181 | file_info.curpos=0; | ||
182 | file_info.start_tick=*(rb->current_tick); | ||
183 | |||
184 | rb->button_clear_queue(); | ||
185 | |||
186 | /* This is the decoding loop. */ | ||
187 | while (file_info.curpos < file_info.filesize && | ||
188 | Stream.this_frame != GuardPtr && | ||
189 | Stream.error != MAD_ERROR_BUFLEN) { | ||
190 | file_info.curpos += (int)Stream.next_frame - (int)Stream.this_frame; | ||
191 | |||
192 | if(mad_frame_decode(&Frame,&Stream)) | ||
193 | { | ||
194 | if(MAD_RECOVERABLE(Stream.error)) | ||
195 | { | ||
196 | if(Stream.error!=MAD_ERROR_LOSTSYNC || Stream.this_frame!=GuardPtr) | ||
197 | { | ||
198 | rb->splash(HZ*1, true, "Recoverable...!"); | ||
199 | } | ||
200 | continue; | ||
201 | } | ||
202 | else | ||
203 | if(Stream.error==MAD_ERROR_BUFLEN) | ||
204 | continue; | ||
205 | else | ||
206 | { | ||
207 | rb->splash(HZ*1, true, "Recoverable...!"); | ||
208 | //fprintf(stderr,"%s: unrecoverable frame level error.\n",ProgName); | ||
209 | Status=1; | ||
210 | break; | ||
211 | } | ||
212 | } | ||
213 | |||
214 | /* We assume all frames have same samplerate as the first */ | ||
215 | if(file_info.frames_decoded==0) { | ||
216 | file_info.samplerate=Frame.header.samplerate; | ||
217 | } | ||
218 | |||
219 | file_info.frames_decoded++; | ||
220 | |||
221 | /* ?? Do we need the timer module? */ | ||
222 | mad_timer_add(&Timer,Frame.header.duration); | ||
223 | |||
224 | /* DAVE: This can be used to attenuate the audio */ | ||
225 | // if(DoFilter) | ||
226 | // ApplyFilter(&Frame); | ||
227 | |||
228 | mad_synth_frame(&Synth,&Frame); | ||
229 | |||
230 | /* Convert MAD's numbers to an array of 16-bit LE signed integers */ | ||
231 | for(i=0;i<Synth.pcm.length;i++) | ||
232 | { | ||
233 | /* Left channel */ | ||
234 | Sample=scale(Synth.pcm.samples[0][i],&d0); | ||
235 | *(OutputPtr++)=Sample&0xff; | ||
236 | *(OutputPtr++)=Sample>>8; | ||
237 | |||
238 | /* Right channel. If the decoded stream is monophonic then | ||
239 | * the right output channel is the same as the left one. | ||
240 | */ | ||
241 | if(MAD_NCHANNELS(&Frame.header)==2) | ||
242 | Sample=scale(Synth.pcm.samples[1][i],&d1); | ||
243 | *(OutputPtr++)=Sample&0xff; | ||
244 | *(OutputPtr++)=Sample>>8; | ||
245 | |||
246 | /* Flush the buffer if it is full. */ | ||
247 | if(OutputPtr==OutputBufferEnd) | ||
248 | { | ||
249 | rb->write(file_info.outfile,OutputBuffer,OUTPUT_BUFFER_SIZE); | ||
250 | OutputPtr=OutputBuffer; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | file_info.current_sample+=Synth.pcm.length; | ||
255 | |||
256 | display_status(&file_info); | ||
257 | |||
258 | if (rb->button_get(false)!=BUTTON_NONE) { | ||
259 | close_wav(&file_info); | ||
260 | return PLUGIN_OK; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | close_wav(&file_info); | ||
265 | rb->splash(HZ*2, true, "FINISHED!"); | ||
266 | |||
267 | return PLUGIN_OK; | ||
268 | } | ||
269 | #endif /* CONFIG_HWCODEC == MASNONE */ | ||