Mercurial > SDL_sound_CoreAudio
annotate decoders/mpglib/mpglib_common.c @ 474:c66080364dff
Most decoders now report total sample play time, now. Technically, this
breaks binary compatibility with the 1.0 branch, since it extends the
Sound_Sample struct, but most (all?) programs are just passing pointers
allocated by SDL_sound around, and might be okay.
Source-level compatibility is not broken...yet! :)
--ryan.
-------- Original Message --------
Subject: SDL_sound patch: Finding total length of time of sound file.
Date: Sun, 26 Jan 2003 09:31:17 -0800 (PST)
Hi Ryan,
I am working with Eric Wing and helping him modify
SDL_sound. AS part of our efforts in improving and
enhancing SDL_sound, we like to submit this patch. We
modified the codecs to find the total time of a sound
file. Below is the explanation of the patch. The
patch is appended as an attachment to this email.
* MOTIVATION:
We needed the ability to get the total play time of a
sample (And we noticed that we're not the only ones).
Since SDL_sound blocks direct access to the specific
decoders, there is no way for a user to know this
information short of decoding the whole thing.
Because of this, we believe this will be a useful
addition, even though the accuracy may not be perfect
(subject to each decoder) or the information may not
always be available.
* CONTRIBUTORS:
Wesley Leong (modified the majority of the codecs and
verified the results)
Eric Wing (showed everyone how to do modify codec,
modified mikmod)
Wang Lam (modified a handful of codecs, researched
into specs and int overflow)
Ahilan Anantha (modified a few codecs and helped with
integer math)
* GENERAL ISSUES:
We chose the value to be milliseconds as an Sint32.
Milliseconds because that's what Sound_Seek takes as a
parameter and -1 to allow for instances/codecs where
the value could not be determined. We are
not sure if this is the final convention you want, so
we are willing to work with you on this.
We also expect the total_time field to be set on open
and never again modified by SDL_sound. Users may
access it directly much like the sample buffer and
buffer_size. We thought about recomputing the time
on DecodeAll, but since users may seek or decode small
chunks first, not all the data may be there. So this
is better done by the user. This may be good
information to document.
Currently, all the main codecs are implemented except
for QuickTime.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Sat, 08 May 2004 08:19:50 +0000 |
parents | fb519e6028e3 |
children |
rev | line source |
---|---|
377
cbb15ecf423a
WinCE (PocketPC) patches from Tyler.
Ryan C. Gordon <icculus@icculus.org>
parents:
322
diff
changeset
|
1 |
cbb15ecf423a
WinCE (PocketPC) patches from Tyler.
Ryan C. Gordon <icculus@icculus.org>
parents:
322
diff
changeset
|
2 #if HAVE_CONFIG_H |
cbb15ecf423a
WinCE (PocketPC) patches from Tyler.
Ryan C. Gordon <icculus@icculus.org>
parents:
322
diff
changeset
|
3 # include <config.h> |
cbb15ecf423a
WinCE (PocketPC) patches from Tyler.
Ryan C. Gordon <icculus@icculus.org>
parents:
322
diff
changeset
|
4 #endif |
cbb15ecf423a
WinCE (PocketPC) patches from Tyler.
Ryan C. Gordon <icculus@icculus.org>
parents:
322
diff
changeset
|
5 |
298 | 6 #include <ctype.h> |
7 #include <stdlib.h> | |
8 | |
9 #include "SDL_sound.h" | |
10 | |
11 #define __SDL_SOUND_INTERNAL__ | |
12 #include "SDL_sound_internal.h" | |
13 | |
14 #include "mpg123_sdlsound.h" | |
15 | |
16 struct parameter param = { 1 , 1 , 0 , 0 }; | |
17 | |
18 int tabsel_123[2][3][16] = { | |
19 { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,}, | |
20 {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,}, | |
21 {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} }, | |
22 | |
23 { {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,}, | |
24 {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,}, | |
25 {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} } | |
26 }; | |
27 | |
28 long mpglib_freqs[9] = { 44100, 48000, 32000, | |
29 22050, 24000, 16000 , | |
30 11025 , 12000 , 8000 }; | |
31 | |
32 int bitindex; | |
33 unsigned char *wordpointer; | |
34 unsigned char *pcm_sample; | |
35 int pcm_point = 0; | |
36 | |
37 | |
38 #define HDRCMPMASK 0xfffffd00 | |
39 | |
40 #if 0 | |
41 int head_check(unsigned long head) | |
42 { | |
43 if( (head & 0xffe00000) != 0xffe00000) | |
44 return FALSE; | |
45 if(!((head>>17)&3)) | |
46 return FALSE; | |
47 if( ((head>>12)&0xf) == 0xf) | |
48 return FALSE; | |
49 if( ((head>>10)&0x3) == 0x3 ) | |
50 return FALSE; | |
51 return TRUE; | |
52 } | |
53 #endif | |
54 | |
55 | |
56 /* | |
57 * the code a header and write the information | |
58 * into the frame structure | |
59 */ | |
60 int decode_header(struct frame *fr,unsigned long newhead) | |
61 { | |
62 if( newhead & (1<<20) ) { | |
63 fr->lsf = (newhead & (1<<19)) ? 0x0 : 0x1; | |
64 fr->mpeg25 = 0; | |
65 } | |
66 else { | |
67 fr->lsf = 1; | |
68 fr->mpeg25 = 1; | |
69 } | |
70 | |
71 fr->lay = 4-((newhead>>17)&3); | |
72 if( ((newhead>>10)&0x3) == 0x3) { | |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
73 BAIL_MACRO("MPGLIB: Corrupted header", 0); |
298 | 74 } |
75 if(fr->mpeg25) { | |
76 fr->sampling_frequency = 6 + ((newhead>>10)&0x3); | |
77 } | |
78 else | |
79 fr->sampling_frequency = ((newhead>>10)&0x3) + (fr->lsf*3); | |
80 fr->error_protection = ((newhead>>16)&0x1)^0x1; | |
81 | |
82 if(fr->mpeg25) /* allow Bitrate change for 2.5 ... */ | |
83 fr->bitrate_index = ((newhead>>12)&0xf); | |
84 | |
85 fr->bitrate_index = ((newhead>>12)&0xf); | |
86 fr->padding = ((newhead>>9)&0x1); | |
87 fr->extension = ((newhead>>8)&0x1); | |
88 fr->mode = ((newhead>>6)&0x3); | |
89 fr->mode_ext = ((newhead>>4)&0x3); | |
90 fr->copyright = ((newhead>>3)&0x1); | |
91 fr->original = ((newhead>>2)&0x1); | |
92 fr->emphasis = newhead & 0x3; | |
93 | |
94 fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2; | |
95 | |
96 if(!fr->bitrate_index) | |
97 { | |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
98 BAIL_MACRO("MPGLIB: Free format not supported.", 0); |
298 | 99 } |
100 | |
101 switch(fr->lay) | |
102 { | |
103 case 1: | |
104 #ifdef LAYER1 | |
105 #if 0 | |
106 fr->jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? | |
107 (fr->mode_ext<<2)+4 : 32; | |
108 #endif | |
109 fr->framesize = (long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000; | |
110 fr->framesize /= mpglib_freqs[fr->sampling_frequency]; | |
111 fr->framesize = ((fr->framesize+fr->padding)<<2)-4; | |
112 #else | |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
113 __Sound_SetError("MPGLIB: Not supported!"); |
298 | 114 #endif |
115 break; | |
116 case 2: | |
117 #ifdef LAYER2 | |
118 #if 0 | |
119 fr->jsbound = (fr->mode == MPG_MD_JOINT_STEREO) ? | |
120 (fr->mode_ext<<2)+4 : fr->II_sblimit; | |
121 #endif | |
122 fr->framesize = (long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000; | |
123 fr->framesize /= mpglib_freqs[fr->sampling_frequency]; | |
124 fr->framesize += fr->padding - 4; | |
125 #else | |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
126 __Sound_SetError("MPGLIB: Not supported!"); |
298 | 127 #endif |
128 break; | |
129 case 3: | |
130 #if 0 | |
131 fr->do_layer = do_layer3; | |
132 if(fr->lsf) | |
133 ssize = (fr->stereo == 1) ? 9 : 17; | |
134 else | |
135 ssize = (fr->stereo == 1) ? 17 : 32; | |
136 #endif | |
137 | |
138 #if 0 | |
139 if(fr->error_protection) | |
140 ssize += 2; | |
141 #endif | |
142 fr->framesize = (long) tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000; | |
143 fr->framesize /= mpglib_freqs[fr->sampling_frequency]<<(fr->lsf); | |
144 fr->framesize = fr->framesize + fr->padding - 4; | |
145 break; | |
146 default: | |
387
fb519e6028e3
Changed all the Sound_SetError() calls to __Sound_SetError (or BAIL*_MACRO)
Ryan C. Gordon <icculus@icculus.org>
parents:
377
diff
changeset
|
147 BAIL_MACRO("MPGLIB: Unknown layer type.", 0); |
298 | 148 } |
474
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
387
diff
changeset
|
149 |
c66080364dff
Most decoders now report total sample play time, now. Technically, this
Ryan C. Gordon <icculus@icculus.org>
parents:
387
diff
changeset
|
150 fr->bitrate = (int) tabsel_123[fr->lsf][(fr->lay - 1)][fr->bitrate_index]; |
298 | 151 return 1; |
152 } | |
153 | |
154 #if 0 | |
155 void print_header(struct frame *fr) | |
156 { | |
157 static char *modes[4] = { "Stereo", "Joint-Stereo", "Dual-Channel", "Single-Channel" }; | |
158 static char *layers[4] = { "Unknown" , "I", "II", "III" }; | |
159 | |
160 fprintf(stderr,"MPEG %s, Layer: %s, Freq: %ld, mode: %s, modext: %d, BPF : %d\n", | |
161 fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"), | |
162 layers[fr->lay],mpglib_freqs[fr->sampling_frequency], | |
163 modes[fr->mode],fr->mode_ext,fr->framesize+4); | |
164 fprintf(stderr,"Channels: %d, copyright: %s, original: %s, CRC: %s, emphasis: %d.\n", | |
165 fr->stereo,fr->copyright?"Yes":"No", | |
166 fr->original?"Yes":"No",fr->error_protection?"Yes":"No", | |
167 fr->emphasis); | |
168 fprintf(stderr,"Bitrate: %d Kbits/s, Extension value: %d\n", | |
169 tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index],fr->extension); | |
170 } | |
171 | |
172 void print_header_compact(struct frame *fr) | |
173 { | |
174 static char *modes[4] = { "stereo", "joint-stereo", "dual-channel", "mono" }; | |
175 static char *layers[4] = { "Unknown" , "I", "II", "III" }; | |
176 | |
177 fprintf(stderr,"MPEG %s layer %s, %d kbit/s, %ld Hz %s\n", | |
178 fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"), | |
179 layers[fr->lay], | |
180 tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index], | |
181 mpglib_freqs[fr->sampling_frequency], modes[fr->mode]); | |
182 } | |
183 | |
184 #endif | |
185 | |
186 unsigned int getbits(int number_of_bits) | |
187 { | |
188 unsigned long rval; | |
189 | |
190 if(!number_of_bits) | |
191 return 0; | |
192 | |
193 { | |
194 rval = wordpointer[0]; | |
195 rval <<= 8; | |
196 rval |= wordpointer[1]; | |
197 rval <<= 8; | |
198 rval |= wordpointer[2]; | |
199 rval <<= bitindex; | |
200 rval &= 0xffffff; | |
201 | |
202 bitindex += number_of_bits; | |
203 | |
204 rval >>= (24-number_of_bits); | |
205 | |
206 wordpointer += (bitindex>>3); | |
207 bitindex &= 7; | |
208 } | |
209 return rval; | |
210 } | |
211 | |
212 unsigned int getbits_fast(int number_of_bits) | |
213 { | |
214 unsigned long rval; | |
215 | |
216 { | |
217 rval = wordpointer[0]; | |
218 rval <<= 8; | |
219 rval |= wordpointer[1]; | |
220 rval <<= bitindex; | |
221 rval &= 0xffff; | |
222 bitindex += number_of_bits; | |
223 | |
224 rval >>= (16-number_of_bits); | |
225 | |
226 wordpointer += (bitindex>>3); | |
227 bitindex &= 7; | |
228 } | |
229 return rval; | |
230 } | |
231 | |
232 unsigned int get1bit(void) | |
233 { | |
234 unsigned char rval; | |
235 rval = *wordpointer << bitindex; | |
236 | |
237 bitindex++; | |
238 wordpointer += (bitindex>>3); | |
239 bitindex &= 7; | |
240 | |
241 return rval>>7; | |
242 } | |
243 | |
244 | |
245 |