summaryrefslogtreecommitdiff
path: root/apps/plugins/mpa2wav.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/mpa2wav.c')
-rw-r--r--apps/plugins/mpa2wav.c269
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
29static struct plugin_api* rb;
30
31struct mad_stream Stream IDATA_ATTR;
32struct mad_frame Frame IDATA_ATTR;
33struct mad_synth Synth IDATA_ATTR;
34mad_timer_t Timer;
35struct dither d0, d1;
36
37/* The following function is used inside libmad - let's hope it's never
38 called.
39*/
40
41void 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
47struct 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 */
59static __inline
60unsigned 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 */
69static __inline
70signed 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
127unsigned char InputBuffer[INPUT_BUFFER_SIZE+MAD_BUFFER_GUARD];
128unsigned char OutputBuffer[OUTPUT_BUFFER_SIZE];
129unsigned char *OutputPtr=OutputBuffer;
130unsigned char *GuardPtr=NULL;
131const unsigned char *OutputBufferEnd=OutputBuffer+OUTPUT_BUFFER_SIZE;
132
133mad_fixed_t mad_frame_overlap[2][32][18] IDATA_ATTR;
134unsigned char mad_main_data[MAD_BUFFER_MDLEN] IDATA_ATTR;
135
136#ifdef USE_IRAM
137extern char iramcopy[];
138extern char iramstart[];
139extern char iramend[];
140#endif
141
142/* this is the plugin entry point */
143enum 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 */