1 /*
2 Ming, an SWF output library
3 Copyright (C) 2002 Opaque Industries - http://www.opaque.net/
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 /* $Id$ */
21
22 #include "libming.h"
23 #include "input.h"
24 #include "mp3.h"
25 #include "error.h"
26 #include "sound.h"
27
28
29 // [version][idx]
30 static unsigned short mp3_samplingrate_tbl[4][4] =
31 {
32 // mpeg 2.5
33 { 11025, 12000, 8000, 0},
34 // reserved
35 { 0, 0, 0, 0},
36 // mpeg 2
37 { 22050, 24000, 16000, 0},
38 // mpeg 1
39 { 44100, 48000, 32000, 0}
40 };
41
42 // [version][layer][idx]
43 static unsigned short mp3_bitrate_tbl[4][4][16] =
44 {
45 // mpeg 2.5
46 {
47 // reserved
48 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
49 // layer 3
50 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0},
51 // layer 2
52 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0},
53 // layer 1
54 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
55 },
56
57 // reserved
58 {
59 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
60 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
61 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
62 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
63 },
64
65 // mpeg version 2
66 {
67 // reserved
68 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
69 // layer 3
70 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0},
71 // layer 2
72 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0},
73 // layer 1
74 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
75
76 },
77 // mpeg version 1
78 {
79 // reserved
80 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
81 // layer 3
82 { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0},
83 // layer 2
84 { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0 },
85 // layer 1
86 { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 382, 416, 448, 0}
87 }
88 };
89
90
91 #define CHECK_STREAM(__in) \
92 do { \
93 if(SWFInput_eof(__in)) \
94 return 0; \
95 } while(0);
96
97
98 /*
99 * reads a MP3 header
100 * returns:
101 * 0 if EOF
102 * -1 if invalid header; stream is unaltered
103 * 1 on success
104 */
readMP3Header(SWFInput input,struct mp3_header * mp3h)105 int readMP3Header(SWFInput input, struct mp3_header *mp3h)
106 {
107 int frameSync, br, sr;
108 if(SWFInput_length(input) - SWFInput_tell(input) < 4)
109 return 0;
110
111 frameSync = SWFInput_readBits(input, 11);
112 CHECK_STREAM(input);
113
114 mp3h->version = SWFInput_readBits(input, 2);
115 mp3h->layer = SWFInput_readBits(input, 2);
116 SWFInput_readBits(input, 1); // protect bit
117 CHECK_STREAM(input);
118
119 br = SWFInput_readBits(input, 4);
120 sr = SWFInput_readBits(input, 2);
121 mp3h->bitrate = mp3_bitrate_tbl[mp3h->version][mp3h->layer][br];
122 mp3h->samplingRate = mp3_samplingrate_tbl[mp3h->version][sr];
123 mp3h->padding = SWFInput_readBits(input, 1);
124 SWFInput_readBits(input, 1); // private bit
125 CHECK_STREAM(input);
126
127 mp3h->channelMode = SWFInput_readBits(input, 2);
128 SWFInput_readBits(input, 2); // extension
129 SWFInput_readBits(input, 3); // copyright, orig, emphasis
130 CHECK_STREAM(input);
131 SWFInput_byteAlign(input);
132 if((frameSync & 0x7ff) != 0x7ff)
133 {
134 SWFInput_seek(input, -4, SEEK_CUR);
135 return -1;
136 }
137
138 if(mp3h->version == 1 || mp3h->layer == 0)
139 {
140 SWFInput_seek(input, -4, SEEK_CUR);
141 return -1;
142 }
143 return 1;
144 }
145
nextMP3Frame(SWFInput input)146 int nextMP3Frame(SWFInput input)
147 {
148 int frameLen, ret;
149 struct mp3_header mp3h;
150
151 ret = readMP3Header(input, &mp3h);
152
153 if(ret < 0)
154 return -1;
155
156 if(ret == 0 || SWFInput_eof(input))
157 return 0;
158
159 if(mp3h.samplingRate == 0 || mp3h.bitrate == 0)
160 SWF_error("invalid mp3 file\n");
161 if(mp3h.version == MP3_VERSION_1)
162 {
163 frameLen = 144 * mp3h.bitrate * 1000
164 / mp3h.samplingRate + mp3h.padding;
165 }
166 else
167 frameLen = 72 * mp3h.bitrate * 1000
168 / mp3h.samplingRate + mp3h.padding;
169
170 SWFInput_seek(input, frameLen-4, SEEK_CUR);
171 return frameLen;
172 }
173
174 /*
175 * returns the sound flags used within ming
176 * stream is set to the first mp3 frame header.
177 */
getMP3Flags(SWFInput input,byte * flags)178 int getMP3Flags(SWFInput input, byte *flags)
179 {
180 struct mp3_header mp3h;
181 int rate=0, channels, start = 0;
182 int ret;
183
184 /*
185 * skip stream until first MP3 header which starts with 0xffe
186 */
187 while((ret = readMP3Header(input, &mp3h)) < 0)
188 {
189 SWFInput_seek(input, 1, SEEK_CUR);
190 start++;
191 }
192
193 if(ret == 0 || SWFInput_eof(input))
194 return -1;
195
196 SWFInput_seek(input, start, SEEK_SET);
197 if (mp3h.channelMode == MP3_CHANNEL_MONO )
198 channels = SWF_SOUND_MONO;
199 else
200 channels = SWF_SOUND_STEREO;
201
202 switch ( mp3h.version )
203 {
204 case MP3_VERSION_1:
205 rate = SWF_SOUND_44KHZ;
206 break;
207
208 case MP3_VERSION_2:
209 rate = SWF_SOUND_22KHZ;
210 break;
211
212 case MP3_VERSION_25:
213 rate = SWF_SOUND_11KHZ;
214 break;
215 }
216
217 *flags =
218 SWF_SOUND_MP3_COMPRESSED | rate | SWF_SOUND_16BITS | channels;
219 return start;
220 }
221
getMP3Samples(SWFInput input,int flags,int * wanted)222 int getMP3Samples(SWFInput input, int flags, int *wanted)
223 {
224 int frameSize, length;
225 int numSamples = 0;
226 int totalLength = 0;
227
228 switch(flags & SWF_SOUND_RATE)
229 {
230 case SWF_SOUND_44KHZ:
231 frameSize = 1152;
232 break;
233 case SWF_SOUND_22KHZ:
234 case SWF_SOUND_11KHZ:
235 frameSize = 576;
236 break;
237 default:
238 *wanted = 0;
239 return -1;
240 }
241
242 while(*wanted < 0 || numSamples < *wanted - frameSize)
243 {
244 length = nextMP3Frame(input);
245 if(length <= 0)
246 break;
247 totalLength += length;
248 numSamples += frameSize;
249 }
250 *wanted = numSamples;
251 return totalLength;
252 }
253
254 /*
255 * Returns the length of a mp3 stream in ms. The duration is
256 * measured in ms. The stream is unaltered.
257 */
getMP3Duration(SWFInput input)258 unsigned int getMP3Duration(SWFInput input)
259 {
260 int start, flags, samples = -1;
261 int sampleRate;
262
263 start = SWFInput_tell(input);
264 if(getMP3Flags(input, (byte *)&flags) < 0)
265 return 0;
266 if(getMP3Samples(input, flags, &samples) <= 0)
267 return 0;
268
269 sampleRate = SWFSound_getSampleRate(flags);
270 SWFInput_seek(input, start, SEEK_SET);
271 return samples * 1000.0 / sampleRate;
272 }
273 /*
274 * Local variables:
275 * tab-width: 2
276 * c-basic-offset: 2
277 * End:
278 */
279