summaryrefslogtreecommitdiff
path: root/apps/codecs/mpa.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/mpa.c')
-rw-r--r--apps/codecs/mpa.c303
1 files changed, 24 insertions, 279 deletions
diff --git a/apps/codecs/mpa.c b/apps/codecs/mpa.c
index 736eef1ffe..f052b9df88 100644
--- a/apps/codecs/mpa.c
+++ b/apps/codecs/mpa.c
@@ -22,6 +22,7 @@
22#include <codecs/libmad/mad.h> 22#include <codecs/libmad/mad.h>
23 23
24#include "playback.h" 24#include "playback.h"
25#include "dsp.h"
25#include "mp3data.h" 26#include "mp3data.h"
26#include "lib/codeclib.h" 27#include "lib/codeclib.h"
27 28
@@ -29,7 +30,6 @@ struct mad_stream Stream IDATA_ATTR;
29struct mad_frame Frame IDATA_ATTR; 30struct mad_frame Frame IDATA_ATTR;
30struct mad_synth Synth IDATA_ATTR; 31struct mad_synth Synth IDATA_ATTR;
31mad_timer_t Timer; 32mad_timer_t Timer;
32struct dither d0, d1;
33 33
34/* The following function is used inside libmad - let's hope it's never 34/* The following function is used inside libmad - let's hope it's never
35 called. 35 called.
@@ -38,122 +38,6 @@ struct dither d0, d1;
38void abort(void) { 38void abort(void) {
39} 39}
40 40
41/* The "dither" code to convert the 24-bit samples produced by libmad was
42 taken from the coolplayer project - coolplayer.sourceforge.net */
43
44struct dither {
45 mad_fixed_t error[3];
46 mad_fixed_t random;
47};
48
49# define SAMPLE_DEPTH 16
50# define scale(x, y) dither((x), (y))
51
52/*
53 * NAME: prng()
54 * DESCRIPTION: 32-bit pseudo-random number generator
55 */
56static __inline
57unsigned long prng(unsigned long state)
58{
59 return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
60}
61
62/*
63 * NAME: dither()
64 * DESCRIPTION: dither and scale sample
65 */
66inline int dither(mad_fixed_t sample, struct dither *dither)
67{
68 unsigned int scalebits;
69 mad_fixed_t output, mask, random;
70
71 enum {
72 MIN = -MAD_F_ONE,
73 MAX = MAD_F_ONE - 1
74 };
75
76 /* noise shape */
77 sample += dither->error[0] - dither->error[1] + dither->error[2];
78
79 dither->error[2] = dither->error[1];
80 dither->error[1] = dither->error[0]/2;
81
82 /* bias */
83 output = sample + (1L << (MAD_F_FRACBITS + 1 - SAMPLE_DEPTH - 1));
84
85 scalebits = MAD_F_FRACBITS + 1 - SAMPLE_DEPTH;
86 mask = (1L << scalebits) - 1;
87
88 /* dither */
89 random = prng(dither->random);
90 output += (random & mask) - (dither->random & mask);
91
92 //dither->random = random;
93
94 /* clip */
95 if (output > MAX) {
96 output = MAX;
97
98 if (sample > MAX)
99 sample = MAX;
100 } else if (output < MIN) {
101 output = MIN;
102
103 if (sample < MIN)
104 sample = MIN;
105 }
106
107 /* quantize */
108 output &= ~mask;
109
110 /* error feedback */
111 dither->error[0] = sample - output;
112
113 /* scale */
114 return output >> scalebits;
115}
116
117inline int detect_silence(mad_fixed_t sample)
118{
119 unsigned int scalebits;
120 mad_fixed_t output, mask;
121
122 enum {
123 MIN = -MAD_F_ONE,
124 MAX = MAD_F_ONE - 1
125 };
126
127 /* bias */
128 output = sample + (1L << (MAD_F_FRACBITS + 1 - SAMPLE_DEPTH - 1));
129
130 scalebits = MAD_F_FRACBITS + 1 - SAMPLE_DEPTH;
131 mask = (1L << scalebits) - 1;
132
133 /* clip */
134 if (output > MAX) {
135 output = MAX;
136
137 if (sample > MAX)
138 sample = MAX;
139 } else if (output < MIN) {
140 output = MIN;
141
142 if (sample < MIN)
143 sample = MIN;
144 }
145
146 /* quantize */
147 output &= ~mask;
148
149 /* scale */
150 output >>= scalebits + 4;
151
152 if (output == 0x00 || output == 0xff)
153 return 1;
154
155 return 0;
156}
157 41
158#define INPUT_CHUNK_SIZE 8192 42#define INPUT_CHUNK_SIZE 8192
159#define OUTPUT_BUFFER_SIZE 65536 /* Must be an integer multiple of 4. */ 43#define OUTPUT_BUFFER_SIZE 65536 /* Must be an integer multiple of 4. */
@@ -162,7 +46,6 @@ unsigned char OutputBuffer[OUTPUT_BUFFER_SIZE];
162unsigned char *OutputPtr; 46unsigned char *OutputPtr;
163unsigned char *GuardPtr = NULL; 47unsigned char *GuardPtr = NULL;
164const unsigned char *OutputBufferEnd = OutputBuffer + OUTPUT_BUFFER_SIZE; 48const unsigned char *OutputBufferEnd = OutputBuffer + OUTPUT_BUFFER_SIZE;
165long resampled_data[2][5000]; /* enough to cope with 11khz upsampling */
166 49
167mad_fixed_t mad_frame_overlap[2][32][18] IDATA_ATTR; 50mad_fixed_t mad_frame_overlap[2][32][18] IDATA_ATTR;
168unsigned char mad_main_data[MAD_BUFFER_MDLEN] IDATA_ATTR; 51unsigned char mad_main_data[MAD_BUFFER_MDLEN] IDATA_ATTR;
@@ -174,73 +57,7 @@ extern char iramstart[];
174extern char iramend[]; 57extern char iramend[];
175#endif 58#endif
176 59
177#undef DEBUG_GAPLESS 60/*
178
179struct resampler {
180 long last_sample, phase, delta;
181};
182
183#if CONFIG_CPU==MCF5249 && !defined(SIMULATOR)
184
185#define INIT() asm volatile ("move.l #0xb0, %macsr") /* frac, round, clip */
186#define FRACMUL(x, y) \
187({ \
188 long t; \
189 asm volatile ("mac.l %[a], %[b], %%acc0\n\t" \
190 "movclr.l %%acc0, %[t]\n\t" \
191 : [t] "=r" (t) : [a] "r" (x), [b] "r" (y)); \
192 t; \
193})
194
195#else
196
197#define INIT()
198#define FRACMUL(x, y) (long)(((long long)(x)*(long long)(y)) << 1)
199#endif
200
201/* linear resampling, introduces one sample delay, because of our inability to
202 look into the future at the end of a frame */
203long downsample(long *in, long *out, int num, struct resampler *s)
204{
205 long i = 1, pos;
206 long last = s->last_sample;
207
208 INIT();
209 pos = s->phase >> 16;
210 /* check if we need last sample of previous frame for interpolation */
211 if (pos > 0)
212 last = in[pos - 1];
213 out[0] = last + FRACMUL((s->phase & 0xffff) << 15, in[pos] - last);
214 s->phase += s->delta;
215 while ((pos = s->phase >> 16) < num) {
216 out[i++] = in[pos - 1] + FRACMUL((s->phase & 0xffff) << 15, in[pos] - in[pos - 1]);
217 s->phase += s->delta;
218 }
219 /* wrap phase accumulator back to start of next frame */
220 s->phase -= num << 16;
221 s->last_sample = in[num - 1];
222 return i;
223}
224
225long upsample(long *in, long *out, int num, struct resampler *s)
226{
227 long i = 0, pos;
228
229 INIT();
230 while ((pos = s->phase >> 16) == 0) {
231 out[i++] = s->last_sample + FRACMUL((s->phase & 0xffff) << 15, in[pos] - s->last_sample);
232 s->phase += s->delta;
233 }
234 while ((pos = s->phase >> 16) < num) {
235 out[i++] = in[pos - 1] + FRACMUL((s->phase & 0xffff) << 15, in[pos] - in[pos - 1]);
236 s->phase += s->delta;
237 }
238 /* wrap phase accumulator back to start of next frame */
239 s->phase -= num << 16;
240 s->last_sample = in[num - 1];
241 return i;
242}
243
244long resample(long *in, long *out, int num, struct resampler *s) 61long resample(long *in, long *out, int num, struct resampler *s)
245{ 62{
246 if (s->delta >= (1 << 16)) 63 if (s->delta >= (1 << 16))
@@ -248,7 +65,7 @@ long resample(long *in, long *out, int num, struct resampler *s)
248 else 65 else
249 return upsample(in, out, num, s); 66 return upsample(in, out, num, s);
250} 67}
251 68*/
252/* this is the codec entry point */ 69/* this is the codec entry point */
253enum codec_status codec_start(struct codec_api* api) 70enum codec_status codec_start(struct codec_api* api)
254{ 71{
@@ -257,20 +74,12 @@ enum codec_status codec_start(struct codec_api* api)
257 int Status = 0; 74 int Status = 0;
258 size_t size; 75 size_t size;
259 int file_end; 76 int file_end;
260 unsigned short Sample;
261 char *InputBuffer; 77 char *InputBuffer;
262 unsigned int samplecount; 78 unsigned int samplecount;
263 unsigned int samplesdone; 79 unsigned int samplesdone;
264 bool first_frame; 80 bool first_frame;
265#ifdef DEBUG_GAPLESS
266 bool first = true;
267 int fd;
268#endif
269 int i;
270 int yieldcounter = 0;
271 int stop_skip, start_skip; 81 int stop_skip, start_skip;
272 struct resampler lr = { 0, 0, 0 }, rr = { 0, 0, 0 }; 82 // struct resampler lr = { 0, 0, 0 }, rr = { 0, 0, 0 };
273 long length;
274 /* Generic codec inititialisation */ 83 /* Generic codec inititialisation */
275 84
276 TEST_CODEC_API(api); 85 TEST_CODEC_API(api);
@@ -289,7 +98,13 @@ enum codec_status codec_start(struct codec_api* api)
289 98
290 ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2)); 99 ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2));
291 ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16)); 100 ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16));
292 101 ci->configure(DSP_SET_CLIP_MIN, (int *)-MAD_F_ONE);
102 ci->configure(DSP_SET_CLIP_MAX, (int *)(MAD_F_ONE - 1));
103 ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(MAD_F_FRACBITS));
104 ci->configure(DSP_DITHER, (bool *)true);
105 ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_NONINTERLEAVED);
106 ci->configure(CODEC_DSP_ENABLE, (bool *)true);
107
293 ci->memset(&Stream, 0, sizeof(struct mad_stream)); 108 ci->memset(&Stream, 0, sizeof(struct mad_stream));
294 ci->memset(&Frame, 0, sizeof(struct mad_frame)); 109 ci->memset(&Frame, 0, sizeof(struct mad_frame));
295 ci->memset(&Synth, 0, sizeof(struct mad_synth)); 110 ci->memset(&Synth, 0, sizeof(struct mad_synth));
@@ -309,14 +124,6 @@ enum codec_status codec_start(struct codec_api* api)
309 for gapless playback */ 124 for gapless playback */
310 next_track: 125 next_track:
311 126
312#ifdef DEBUG_GAPLESS
313 if (first)
314 fd = ci->open("/first.pcm", O_WRONLY | O_CREAT);
315 else
316 fd = ci->open("/second.pcm", O_WRONLY | O_CREAT);
317 first = false;
318#endif
319
320 info = ci->mp3data; 127 info = ci->mp3data;
321 first_frame = false; 128 first_frame = false;
322 file_end = 0; 129 file_end = 0;
@@ -325,6 +132,8 @@ enum codec_status codec_start(struct codec_api* api)
325 while (!*ci->taginfo_ready) 132 while (!*ci->taginfo_ready)
326 ci->yield(); 133 ci->yield();
327 134
135 ci->configure(DSP_SET_FREQUENCY, (int *)ci->id3->frequency);
136
328 ci->request_buffer(&size, ci->id3->first_frame_offset); 137 ci->request_buffer(&size, ci->id3->first_frame_offset);
329 ci->advance_buffer(size); 138 ci->advance_buffer(size);
330 139
@@ -350,13 +159,7 @@ enum codec_status codec_start(struct codec_api* api)
350 samplecount = ci->id3->length * (ci->id3->frequency / 100) / 10; 159 samplecount = ci->id3->length * (ci->id3->frequency / 100) / 10;
351 samplesdone = ci->id3->elapsed * (ci->id3->frequency / 100) / 10; 160 samplesdone = ci->id3->elapsed * (ci->id3->frequency / 100) / 10;
352 } 161 }
353 /* rb->snprintf(buf2, sizeof(buf2), "sc: %d", samplecount); 162
354 rb->splash(0, true, buf2);
355 rb->snprintf(buf2, sizeof(buf2), "length: %d", ci->id3->length);
356 rb->splash(HZ*5, true, buf2);
357 rb->snprintf(buf2, sizeof(buf2), "frequency: %d", ci->id3->frequency);
358 rb->splash(HZ*5, true, buf2); */
359 lr.delta = rr.delta = ci->id3->frequency*65536/44100;
360 /* This is the decoding loop. */ 163 /* This is the decoding loop. */
361 while (1) { 164 while (1) {
362 ci->yield(); 165 ci->yield();
@@ -387,9 +190,6 @@ enum codec_status codec_start(struct codec_api* api)
387 mad_stream_buffer(&Stream, InputBuffer, size); 190 mad_stream_buffer(&Stream, InputBuffer, size);
388 } 191 }
389 192
390 //if ((int)ci->curpos >= ci->id3->first_frame_offset)
391 //first_frame = true;
392
393 if(mad_frame_decode(&Frame,&Stream)) 193 if(mad_frame_decode(&Frame,&Stream))
394 { 194 {
395 if (Stream.error == MAD_FLAG_INCOMPLETE || Stream.error == MAD_ERROR_BUFLEN) { 195 if (Stream.error == MAD_FLAG_INCOMPLETE || Stream.error == MAD_ERROR_BUFLEN) {
@@ -428,78 +228,23 @@ enum codec_status codec_start(struct codec_api* api)
428 228
429 mad_synth_frame(&Synth,&Frame); 229 mad_synth_frame(&Synth,&Frame);
430 230
431 //if (!first_frame) {
432 //samplecount -= Synth.pcm.length;
433 //continue ;
434 //}
435
436 /* Convert MAD's numbers to an array of 16-bit LE signed integers */ 231 /* Convert MAD's numbers to an array of 16-bit LE signed integers */
437 /* We skip start_skip number of samples here, this should only happen for 232 /* We skip start_skip number of samples here, this should only happen for
438 very first frame in the stream. */ 233 very first frame in the stream. */
439 /* TODO: possible for start_skip to exceed one frames worth of samples? */ 234 /* TODO: possible for start_skip to exceed one frames worth of samples? */
440 length = resample((long *)&Synth.pcm.samples[0][start_skip], resampled_data[0], Synth.pcm.length, &lr); 235 //length = resample((long *)&Synth.pcm.samples[0][start_skip], resampled_data[0], Synth.pcm.length, &lr);
441 if (MAD_NCHANNELS(&Frame.header) == 2) 236 //if (MAD_NCHANNELS(&Frame.header) == 2)
442 resample((long *)&Synth.pcm.samples[1][start_skip], resampled_data[1], Synth.pcm.length, &rr); 237 // resample((long *)&Synth.pcm.samples[1][start_skip], resampled_data[1], Synth.pcm.length, &rr);
443 for (i = 0; i < length; i++) 238 ci->audiobuffer_insert_split(&Synth.pcm.samples[0][start_skip],
444 { 239 &Synth.pcm.samples[1][start_skip],
445 start_skip = 0; /* not very elegant, and might want to keep this value */ 240 (Synth.pcm.length - start_skip) * 4);
446 samplesdone++; 241 start_skip = 0; /* not very elegant, and might want to keep this value */
447 //if (ci->mp3data->padding > 0) { 242
448 // ci->mp3data->padding--; 243 samplesdone += Synth.pcm.length;
449 // continue ; 244 samplecount -= Synth.pcm.length;
450 //}
451 /*if (!first_frame) {
452 if (detect_silence(Synth.pcm.samples[0][i]))
453 continue ;
454 first_frame = true;
455 }*/
456
457 /* Left channel */
458 Sample = scale(resampled_data[0][i], &d0);
459 *(OutputPtr++) = Sample >> 8;
460 *(OutputPtr++) = Sample & 0xff;
461
462 /* Right channel. If the decoded stream is monophonic then
463 * the right output channel is the same as the left one.
464 */
465 if (MAD_NCHANNELS(&Frame.header) == 2)
466 Sample = scale(resampled_data[1][i], &d1);
467 *(OutputPtr++) = Sample >> 8;
468 *(OutputPtr++) = Sample & 0xff;
469
470 samplecount--;
471 if (samplecount == 0) {
472#ifdef DEBUG_GAPLESS
473 ci->write(fd, OutputBuffer, (int)OutputPtr - (int)OutputBuffer);
474#endif
475 while (!ci->audiobuffer_insert(OutputBuffer, (int)OutputPtr - (int)OutputBuffer))
476 ci->yield();
477 goto song_end;
478 }
479
480 if (yieldcounter++ == 200) {
481 ci->yield();
482 yieldcounter = 0;
483 }
484
485 /* Flush the buffer if it is full. */
486 if (OutputPtr == OutputBufferEnd)
487 {
488#ifdef DEBUG_GAPLESS
489 ci->write(fd, OutputBuffer, OUTPUT_BUFFER_SIZE);
490#endif
491 while (!ci->audiobuffer_insert(OutputBuffer, OUTPUT_BUFFER_SIZE))
492 ci->yield();
493 OutputPtr = OutputBuffer;
494 }
495 }
496 ci->set_elapsed(samplesdone / (ci->id3->frequency/1000)); 245 ci->set_elapsed(samplesdone / (ci->id3->frequency/1000));
497 } 246 }
498 247
499 song_end:
500#ifdef DEBUG_GAPLESS
501 ci->close(fd);
502#endif
503 Stream.error = 0; 248 Stream.error = 0;
504 249
505 if (ci->request_next_track()) 250 if (ci->request_next_track())