diff options
author | Dave Chapman <dave@dchapman.com> | 2002-05-12 10:37:49 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2002-05-12 10:37:49 +0000 |
commit | f622a630ca4b2c828271fc0f7a1367cd94ad9103 (patch) | |
tree | 942d4d191008b90b30678e3a8743a85f8913cdfe | |
parent | b133675d3e39ee9e25f4c6e919b88ceb3e9d51c0 (diff) | |
download | rockbox-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.c | 141 |
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 | |||
44 | struct 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 | |||
36 | struct mad_stream Stream; | 51 | struct mad_stream Stream; |
37 | struct mad_frame Frame; | 52 | struct mad_frame Frame; |
38 | struct mad_synth Synth; | 53 | struct mad_synth Synth; |
39 | mad_timer_t Timer; | 54 | mad_timer_t Timer; |
40 | int sound; | 55 | int sound; |
41 | 56 | ||
57 | /* | ||
58 | * NAME: prng() | ||
59 | * DESCRIPTION: 32-bit pseudo-random number generator | ||
60 | */ | ||
61 | static __inline | ||
62 | unsigned 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 | */ | ||
71 | static __inline | ||
72 | signed 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 | */ | ||
128 | static | ||
129 | void 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 | |||
42 | void init_oss(int sound, int sound_freq, int channels) { | 172 | void 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 | */ |