Simplify initing of the screens[] struct by using an initializer, also some reorderin...
[kugel-rb.git] / uisimulator / common / mpegplay.c
blobfa1333b3b5b3806a96ca3c45ff6d192b8acdbc15
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * Copyright (C) 2002 Dave Chapman
11 * This file contains significant code from two other projects:
13 * 1) madldd - a sample application to use libmad
14 * 2) CoolPlayer - a win32 audio player that also uses libmad
16 * All files in this archive are subject to the GNU General Public License.
17 * See the file COPYING in the source tree root for full license agreement.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
24 #ifdef HAVE_MPEG_PLAY
25 #ifdef HAVE_LIBMAD
27 #include <string.h>
28 #include <stdlib.h>
29 #include <file.h>
30 #include <lcd.h>
31 #include <button.h>
32 #include "id3.h"
34 #include <stdio.h>
35 #include <mad.h>
37 #include "sound.h"
39 /* The "dither" code to convert the 24-bit samples produced by libmad was
40 taken from the coolplayer project - coolplayer.sourceforge.net */
42 struct dither {
43 mad_fixed_t error[3];
44 mad_fixed_t random;
46 # define SAMPLE_DEPTH 16
47 # define scale(x, y) dither((x), (y))
49 struct mad_stream Stream;
50 struct mad_frame Frame;
51 struct mad_synth Synth;
52 mad_timer_t Timer;
55 * NAME: prng()
56 * DESCRIPTION: 32-bit pseudo-random number generator
58 static __inline
59 unsigned long prng(unsigned long state)
61 return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
65 * NAME: dither()
66 * DESCRIPTION: dither and scale sample
68 static __inline
69 signed int dither(mad_fixed_t sample, struct dither *dither)
71 unsigned int scalebits;
72 mad_fixed_t output, mask, random;
74 enum {
75 MIN = -MAD_F_ONE,
76 MAX = MAD_F_ONE - 1
79 /* noise shape */
80 sample += dither->error[0] - dither->error[1] + dither->error[2];
82 dither->error[2] = dither->error[1];
83 dither->error[1] = dither->error[0] / 2;
85 /* bias */
86 output = sample + (1L << (MAD_F_FRACBITS + 1 - SAMPLE_DEPTH - 1));
88 scalebits = MAD_F_FRACBITS + 1 - SAMPLE_DEPTH;
89 mask = (1L << scalebits) - 1;
91 /* dither */
92 random = prng(dither->random);
93 output += (random & mask) - (dither->random & mask);
95 dither->random = random;
97 /* clip */
98 if (output > MAX) {
99 output = MAX;
101 if (sample > MAX)
102 sample = MAX;
104 else if (output < MIN) {
105 output = MIN;
107 if (sample < MIN)
108 sample = MIN;
111 /* quantize */
112 output &= ~mask;
114 /* error feedback */
115 dither->error[0] = sample - output;
117 /* scale */
118 return output >> scalebits;
121 #define INPUT_BUFFER_SIZE (5*8192)
122 #define OUTPUT_BUFFER_SIZE 8192 /* Must be an integer multiple of 4. */
123 void real_mpeg_play(char* fname)
125 unsigned char InputBuffer[INPUT_BUFFER_SIZE],
126 OutputBuffer[OUTPUT_BUFFER_SIZE],
127 *OutputPtr=OutputBuffer;
128 const unsigned char *OutputBufferEnd=OutputBuffer+OUTPUT_BUFFER_SIZE;
129 int Status=0, i, fd;
130 unsigned long FrameCount=0;
131 sound_t sound;
132 struct mp3entry mp3;
133 static struct dither d0, d1;
134 int key=0;
136 mp3info(&mp3, fname, false); /* FIXME: honor the v1first setting */
138 init_sound(&sound);
140 /* Configure sound device for this file - always select Stereo because
141 some sound cards don't support mono */
142 config_sound(&sound,mp3.frequency,2);
144 if ((fd=open(fname,O_RDONLY)) < 0) {
145 fprintf(stderr,"could not open %s\n",fname);
146 return;
149 /* First the structures used by libmad must be initialized. */
150 mad_stream_init(&Stream);
151 mad_frame_init(&Frame);
152 mad_synth_init(&Synth);
153 mad_timer_reset(&Timer);
155 do {
156 if (Stream.buffer==NULL || Stream.error==MAD_ERROR_BUFLEN) {
157 size_t ReadSize,Remaining;
158 unsigned char *ReadStart;
160 if(Stream.next_frame!=NULL) {
161 Remaining=Stream.bufend-Stream.next_frame;
162 memmove(InputBuffer,Stream.next_frame,Remaining);
163 ReadStart=InputBuffer+Remaining;
164 ReadSize=INPUT_BUFFER_SIZE-Remaining;
165 } else {
166 ReadSize=INPUT_BUFFER_SIZE,
167 ReadStart=InputBuffer,
168 Remaining=0;
171 if ((int)(ReadSize=read(fd,ReadStart,ReadSize)) < 0) {
172 fprintf(stderr,"end of input stream\n");
173 break;
176 mad_stream_buffer(&Stream,InputBuffer,ReadSize+Remaining);
177 Stream.error=0;
180 if(mad_frame_decode(&Frame,&Stream)) {
181 if(MAD_RECOVERABLE(Stream.error)) {
182 fprintf(stderr,"recoverable frame level error\n");
183 fflush(stderr);
184 continue;
185 } else {
186 if(Stream.error==MAD_ERROR_BUFLEN) {
187 continue;
188 } else {
189 fprintf(stderr,"unrecoverable frame level error\n");
190 Status=1;
191 break;
196 FrameCount++;
197 mad_timer_add(&Timer,Frame.header.duration);
199 mad_synth_frame(&Synth,&Frame);
201 for(i=0;i<Synth.pcm.length;i++) {
202 unsigned short Sample;
204 /* Left channel */
205 Sample=scale(Synth.pcm.samples[0][i],&d0);
206 *(OutputPtr++)=Sample&0xff;
207 *(OutputPtr++)=Sample>>8;
209 /* Right channel. If the decoded stream is monophonic then
210 * the right output channel is the same as the left one.
212 if(MAD_NCHANNELS(&Frame.header)==2) {
213 Sample=scale(Synth.pcm.samples[1][i],&d1);
216 *(OutputPtr++)=Sample&0xff;
217 *(OutputPtr++)=Sample>>8;
219 /* Flush the buffer if it is full. */
220 if (OutputPtr==OutputBufferEnd) {
221 if (output_sound(&sound, OutputBuffer,
222 OUTPUT_BUFFER_SIZE)!=OUTPUT_BUFFER_SIZE) {
223 fprintf(stderr,"PCM write error.\n");
224 Status=2;
225 break;
227 OutputPtr=OutputBuffer;
231 if ((key=button_get(0))==BUTTON_STOP)
233 break;
236 }while(1);
238 /* Mad is no longer used, the structures that were initialized must
239 * now be cleared.
241 mad_synth_finish(&Synth);
242 mad_frame_finish(&Frame);
243 mad_stream_finish(&Stream);
245 /* If the output buffer is not empty and no error occured during
246 * the last write, then flush it. */
247 if(OutputPtr!=OutputBuffer && Status!=2)
249 size_t BufferSize=OutputPtr-OutputBuffer;
251 if (output_sound(&sound, OutputPtr, BufferSize)!=(int)BufferSize)
253 fprintf(stderr,"PCM write error\n");
254 Status=2;
258 /* Accounting report if no error occured. */
259 if(!Status)
261 char Buffer[80];
263 mad_timer_string(Timer,Buffer,"%lu:%02lu.%03u",
264 MAD_UNITS_MINUTES,MAD_UNITS_MILLISECONDS,0);
265 fprintf(stderr,"%lu frames decoded (%s).\n",FrameCount,Buffer);
268 close_sound(&sound);
269 /* That's the end of the world (in the H. G. Wells way). */
270 return;
274 #endif /* HAVE_LIBMAD */
275 #endif /* HAVE_MPEG_PLAY */