summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2002-05-12 10:37:49 +0000
committerDave Chapman <dave@dchapman.com>2002-05-12 10:37:49 +0000
commitf622a630ca4b2c828271fc0f7a1367cd94ad9103 (patch)
tree942d4d191008b90b30678e3a8743a85f8913cdfe
parentb133675d3e39ee9e25f4c6e919b88ceb3e9d51c0 (diff)
downloadrockbox-f622a630ca4b2c828271fc0f7a1367cd94ad9103.tar.gz
rockbox-f622a630ca4b2c828271fc0f7a1367cd94ad9103.zip
improved mpeg audio quality
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@548 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--uisimulator/x11/mpegplay.c141
1 files changed, 136 insertions, 5 deletions
diff --git a/uisimulator/x11/mpegplay.c b/uisimulator/x11/mpegplay.c
index 2d31c073dd..c01ab2487c 100644
--- a/uisimulator/x11/mpegplay.c
+++ b/uisimulator/x11/mpegplay.c
@@ -8,6 +8,11 @@
8 * 8 *
9 * Copyright (C) 2002 Dave Chapman 9 * Copyright (C) 2002 Dave Chapman
10 * 10 *
11 * This file contains significant code from two other projects:
12 *
13 * 1) madldd - a sample application to use libmad
14 * 2) CoolPlayer - a win32 audio player that also uses libmad
15 *
11 * All files in this archive are subject to the GNU General Public License. 16 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement. 17 * See the file COPYING in the source tree root for full license agreement.
13 * 18 *
@@ -33,12 +38,137 @@
33/* We want to use the "real" open in some cases */ 38/* We want to use the "real" open in some cases */
34#undef open 39#undef open
35 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# define SAMPLE_DEPTH 16
49# define scale(x, y) dither((x), (y))
50
36struct mad_stream Stream; 51struct mad_stream Stream;
37struct mad_frame Frame; 52struct mad_frame Frame;
38struct mad_synth Synth; 53struct mad_synth Synth;
39mad_timer_t Timer; 54mad_timer_t Timer;
40int sound; 55int sound;
41 56
57/*
58 * NAME: prng()
59 * DESCRIPTION: 32-bit pseudo-random number generator
60 */
61static __inline
62unsigned long prng(unsigned long state)
63{
64 return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
65}
66
67/*
68 * NAME: dither()
69 * DESCRIPTION: dither and scale sample
70 */
71static __inline
72signed int dither(mad_fixed_t sample, struct dither *dither)
73{
74 unsigned int scalebits;
75 mad_fixed_t output, mask, random;
76
77 enum {
78 MIN = -MAD_F_ONE,
79 MAX = MAD_F_ONE - 1
80 };
81
82 /* noise shape */
83 sample += dither->error[0] - dither->error[1] + dither->error[2];
84
85 dither->error[2] = dither->error[1];
86 dither->error[1] = dither->error[0] / 2;
87
88 /* bias */
89 output = sample + (1L << (MAD_F_FRACBITS + 1 - SAMPLE_DEPTH - 1));
90
91 scalebits = MAD_F_FRACBITS + 1 - SAMPLE_DEPTH;
92 mask = (1L << scalebits) - 1;
93
94 /* dither */
95 random = prng(dither->random);
96 output += (random & mask) - (dither->random & mask);
97
98 dither->random = random;
99
100 /* clip */
101 if (output > MAX) {
102 output = MAX;
103
104 if (sample > MAX)
105 sample = MAX;
106 }
107 else if (output < MIN) {
108 output = MIN;
109
110 if (sample < MIN)
111 sample = MIN;
112 }
113
114 /* quantize */
115 output &= ~mask;
116
117 /* error feedback */
118 dither->error[0] = sample - output;
119
120 /* scale */
121 return output >> scalebits;
122}
123
124/*
125 * NAME: pack_pcm()
126 * DESCRIPTION: scale and dither MAD output
127 */
128static
129void pack_pcm(unsigned char **pcm, unsigned int nsamples,
130 mad_fixed_t const *ch1, mad_fixed_t const *ch2)
131{
132 register signed int s0, s1;
133 static struct dither d0, d1;
134
135 if (ch2) { /* stereo */
136 while (nsamples--) {
137 s0 = scale(*ch1++, &d0);
138 s1 = scale(*ch2++, &d1);
139# if SAMPLE_DEPTH == 16
140 (*pcm)[0 + 0] = s0 >> 0;
141 (*pcm)[0 + 1] = s0 >> 8;
142 (*pcm)[2 + 0] = s1 >> 0;
143 (*pcm)[2 + 1] = s1 >> 8;
144
145 *pcm += 2 * 2;
146# elif SAMPLE_DEPTH == 8
147 (*pcm)[0] = s0 ^ 0x80;
148 (*pcm)[1] = s1 ^ 0x80;
149
150 *pcm += 2;
151# else
152# error "bad SAMPLE_DEPTH"
153# endif
154 }
155 }
156 else { /* mono */
157 while (nsamples--) {
158 s0 = scale(*ch1++, &d0);
159
160# if SAMPLE_DEPTH == 16
161 (*pcm)[0] = s0 >> 0;
162 (*pcm)[1] = s0 >> 8;
163
164 *pcm += 2;
165# elif SAMPLE_DEPTH == 8
166 *(*pcm)++ = s0 ^ 0x80;
167# endif
168 }
169 }
170}
171
42void init_oss(int sound, int sound_freq, int channels) { 172void init_oss(int sound, int sound_freq, int channels) {
43 int format=AFMT_U16_LE; 173 int format=AFMT_U16_LE;
44 int setting=0x000C000D; // 12 fragments size 8kb ? WHAT IS THIS? 174 int setting=0x000C000D; // 12 fragments size 8kb ? WHAT IS THIS?
@@ -56,7 +186,7 @@ void init_oss(int sound, int sound_freq, int channels) {
56 perror("SNDCTL_DSP_SETFMT"); 186 perror("SNDCTL_DSP_SETFMT");
57 } 187 }
58 188
59 fprintf(stderr,"SETTING /dev/dsp to %dHz\n",sound_freq); 189// fprintf(stderr,"SETTING /dev/dsp to %dHz\n",sound_freq);
60 if (ioctl(sound,SNDCTL_DSP_SPEED,&sound_freq)==-1) { 190 if (ioctl(sound,SNDCTL_DSP_SPEED,&sound_freq)==-1) {
61 perror("SNDCTL_DSP_SPEED"); 191 perror("SNDCTL_DSP_SPEED");
62 } 192 }
@@ -81,6 +211,8 @@ int mpeg_play(char* fname)
81 unsigned long FrameCount=0; 211 unsigned long FrameCount=0;
82 int sound,fd; 212 int sound,fd;
83 mp3entry mp3; 213 mp3entry mp3;
214 register signed int s0, s1;
215 static struct dither d0, d1;
84 216
85 mp3info(&mp3, fname); 217 mp3info(&mp3, fname);
86 218
@@ -108,7 +240,7 @@ int mpeg_play(char* fname)
108 240
109 do 241 do
110 { 242 {
111 if (button_get()) break; /* Return if a key is pressed */ 243 //if (button_get()) break; /* Return if a key is pressed */
112 244
113 if(Stream.buffer==NULL || Stream.error==MAD_ERROR_BUFLEN) 245 if(Stream.buffer==NULL || Stream.error==MAD_ERROR_BUFLEN)
114 { 246 {
@@ -165,7 +297,7 @@ int mpeg_play(char* fname)
165 unsigned short Sample; 297 unsigned short Sample;
166 298
167 /* Left channel */ 299 /* Left channel */
168 Sample=MadFixedToUshort(Synth.pcm.samples[0][i]); 300 Sample=scale(Synth.pcm.samples[0][i],&d0);
169 *(OutputPtr++)=Sample&0xff; 301 *(OutputPtr++)=Sample&0xff;
170 *(OutputPtr++)=Sample>>8; 302 *(OutputPtr++)=Sample>>8;
171 303
@@ -173,7 +305,7 @@ int mpeg_play(char* fname)
173 * the right output channel is the same as the left one. 305 * the right output channel is the same as the left one.
174 */ 306 */
175 if(MAD_NCHANNELS(&Frame.header)==2) 307 if(MAD_NCHANNELS(&Frame.header)==2)
176 Sample=MadFixedToUshort(Synth.pcm.samples[1][i]); 308 Sample=scale(Synth.pcm.samples[1][i],&d0);
177 *(OutputPtr++)=Sample&0xff; 309 *(OutputPtr++)=Sample&0xff;
178 *(OutputPtr++)=Sample>>8; 310 *(OutputPtr++)=Sample>>8;
179 311
@@ -191,7 +323,6 @@ int mpeg_play(char* fname)
191 } 323 }
192 }while(1); 324 }while(1);
193 325
194 fprintf(stderr,"END OF MAD LOOP\n");
195 /* Mad is no longer used, the structures that were initialized must 326 /* Mad is no longer used, the structures that were initialized must
196 * now be cleared. 327 * now be cleared.
197 */ 328 */