author | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
---|---|---|
committer | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
commit | 15318cad33835e4e2dc620d033e43cd930676cdd (patch) (unidiff) | |
tree | c2fa0399a2c47fda8e2cd0092c73a809d17f68eb /core/multimedia/opieplayer/libflash/sound.cc | |
download | opie-15318cad33835e4e2dc620d033e43cd930676cdd.zip opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.gz opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.bz2 |
Initial revision
Diffstat (limited to 'core/multimedia/opieplayer/libflash/sound.cc') (more/less context) (show whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/libflash/sound.cc | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/libflash/sound.cc b/core/multimedia/opieplayer/libflash/sound.cc new file mode 100644 index 0000000..e93f9b5 --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/sound.cc | |||
@@ -0,0 +1,439 @@ | |||
1 | ///////////////////////////////////////////////////////////// | ||
2 | // Flash Plugin and Player | ||
3 | // Copyright (C) 1998,1999 Olivier Debon | ||
4 | // | ||
5 | // This program is free software; you can redistribute it and/or | ||
6 | // modify it under the terms of the GNU General Public License | ||
7 | // as published by the Free Software Foundation; either version 2 | ||
8 | // of the License, or (at your option) any later version. | ||
9 | // | ||
10 | // This program 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 | ||
13 | // GNU General Public License for more details. | ||
14 | // | ||
15 | // You should have received a copy of the GNU General Public License | ||
16 | // along with this program; if not, write to the Free Software | ||
17 | // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | // | ||
19 | /////////////////////////////////////////////////////////////// | ||
20 | // Author : Olivier Debon <odebon@club-internet.fr> | ||
21 | // | ||
22 | |||
23 | #include "swf.h" | ||
24 | |||
25 | #include <unistd.h> | ||
26 | #include <fcntl.h> | ||
27 | #include <sys/ioctl.h> | ||
28 | #ifndef NOSOUND | ||
29 | #include <linux/soundcard.h> | ||
30 | #endif | ||
31 | |||
32 | #ifdef RCSID | ||
33 | static char *rcsid = "$Id$"; | ||
34 | #endif | ||
35 | |||
36 | #define PRINT 0 | ||
37 | |||
38 | //////////// SOUND | ||
39 | |||
40 | Sound::Sound(long id) : Character(SoundType, id) | ||
41 | { | ||
42 | samples = 0; | ||
43 | stereo = 0; | ||
44 | soundRate = 0; | ||
45 | sampleSize = 1; | ||
46 | } | ||
47 | |||
48 | Sound::~Sound() | ||
49 | { | ||
50 | if (samples) { | ||
51 | delete samples; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | void | ||
56 | Sound::setSoundFlags(long f) { | ||
57 | switch (GET_SOUND_RATE_CODE(f)) { | ||
58 | case 0: | ||
59 | soundRate = 5500; | ||
60 | break; | ||
61 | case 1: | ||
62 | soundRate = 11000; | ||
63 | break; | ||
64 | case 2: | ||
65 | soundRate = 22000; | ||
66 | break; | ||
67 | case 3: | ||
68 | soundRate = 44000; | ||
69 | break; | ||
70 | } | ||
71 | if (f & soundIs16bit) { | ||
72 | sampleSize = 2; | ||
73 | } | ||
74 | if (f & soundIsStereo) { | ||
75 | stereo = 1; | ||
76 | } | ||
77 | |||
78 | #if PRINT | ||
79 | printf("-----\nFlags = %2x\n", f); | ||
80 | printf("Rate = %d kHz ", soundRate); | ||
81 | printf("SampleSize = %d byte(s) ", sampleSize); | ||
82 | if (f & soundIsStereo) { | ||
83 | printf("Stereo "); | ||
84 | } else { | ||
85 | printf("Mono "); | ||
86 | } | ||
87 | if (f & soundIsADPCMCompressed) { | ||
88 | printf("ADPCM\n"); | ||
89 | } else { | ||
90 | printf("Raw\n"); | ||
91 | } | ||
92 | #endif | ||
93 | } | ||
94 | |||
95 | char * | ||
96 | Sound::setNbSamples(long n) { | ||
97 | long size; | ||
98 | |||
99 | nbSamples = n; | ||
100 | |||
101 | size = nbSamples * (stereo ? 2 : 1) * sampleSize; | ||
102 | |||
103 | samples = new char[ size ]; | ||
104 | |||
105 | memset((char *)samples,0, size); | ||
106 | |||
107 | return samples; | ||
108 | } | ||
109 | |||
110 | long | ||
111 | Sound::getRate() { | ||
112 | return soundRate; | ||
113 | } | ||
114 | |||
115 | long | ||
116 | Sound::getChannel() { | ||
117 | return stereo ? 2 : 1; | ||
118 | } | ||
119 | |||
120 | long | ||
121 | Sound::getNbSamples() { | ||
122 | return nbSamples; | ||
123 | } | ||
124 | |||
125 | long | ||
126 | Sound::getSampleSize() { | ||
127 | return sampleSize; | ||
128 | } | ||
129 | |||
130 | char * | ||
131 | Sound::getSamples() { | ||
132 | return samples; | ||
133 | } | ||
134 | |||
135 | //////////// SOUND MIXER | ||
136 | |||
137 | long SoundMixer::dsp = -1;// Init of descriptor | ||
138 | long SoundMixer::blockSize = 0;// Driver sound buffer size | ||
139 | long SoundMixer::nbInst = 0;// Nb SoundMixer instances | ||
140 | long SoundMixer::sampleSize = 0; | ||
141 | long SoundMixer::stereo = 0; | ||
142 | long SoundMixer::soundRate = 0; | ||
143 | char *SoundMixer::buffer = 0; | ||
144 | |||
145 | SoundMixer::SoundMixer(char *device) | ||
146 | { | ||
147 | #ifndef NOSOUND | ||
148 | int status; | ||
149 | long fmt; | ||
150 | |||
151 | list = 0;// No sound to play | ||
152 | |||
153 | if (nbInst++) { | ||
154 | // Device is already open | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | dsp = open(device,O_WRONLY); | ||
159 | if (dsp < 0) { | ||
160 | perror("open dsp"); | ||
161 | return; | ||
162 | } | ||
163 | |||
164 | // Reset device | ||
165 | status = ioctl(dsp, SNDCTL_DSP_RESET); | ||
166 | if (status < 0) perror("ioctl SNDCTL_DSP_RESET"); | ||
167 | |||
168 | // Set sample size | ||
169 | fmt = AFMT_S16_LE; | ||
170 | sampleSize = 2; | ||
171 | status = ioctl(dsp, SNDCTL_DSP_SETFMT, &fmt); | ||
172 | if (status < 0) perror("ioctl SNDCTL_DSP_SETFMT"); | ||
173 | |||
174 | if (status) { | ||
175 | fmt = AFMT_U8; | ||
176 | sampleSize = 1; | ||
177 | status = ioctl(dsp, SNDCTL_DSP_SETFMT, &fmt); | ||
178 | if (status < 0) perror("ioctl SNDCTL_DSP_SETFMT"); | ||
179 | } | ||
180 | |||
181 | // Set stereo channel | ||
182 | stereo = 1; | ||
183 | status = ioctl(dsp, SNDCTL_DSP_STEREO, &stereo); | ||
184 | |||
185 | if (status) { | ||
186 | stereo = 0; | ||
187 | } | ||
188 | |||
189 | // Set sound rate in Hertz | ||
190 | soundRate = 11000; | ||
191 | status = ioctl(dsp, SNDCTL_DSP_SPEED, &soundRate); | ||
192 | if (status < 0) perror("ioctl SNDCTL_DSP_SPEED"); | ||
193 | |||
194 | // Get device buffer size | ||
195 | status = ioctl(dsp, SNDCTL_DSP_GETBLKSIZE, &blockSize); | ||
196 | if (status < 0) perror("ioctl SNDCTL_DSP_GETBLKSIZE"); | ||
197 | if (blockSize < 1024) { | ||
198 | blockSize = 32768; | ||
199 | } | ||
200 | blockSize *= 2; | ||
201 | |||
202 | buffer = (char *)malloc(blockSize); | ||
203 | if (buffer == 0) { | ||
204 | close(dsp); | ||
205 | dsp = -1; | ||
206 | } | ||
207 | |||
208 | #if PRINT | ||
209 | int caps; | ||
210 | |||
211 | ioctl(dsp,SNDCTL_DSP_GETCAPS, &caps); | ||
212 | printf("Audio capabilities = %x\n", caps); | ||
213 | printf("Sound Rate = %d\n", soundRate); | ||
214 | printf("Stereo = %d\n", stereo); | ||
215 | printf("Sample Size = %d\n", sampleSize); | ||
216 | printf("Buffer Size = %d\n", blockSize); | ||
217 | #endif /* PRINT */ | ||
218 | |||
219 | #endif/* NOSOUND */ | ||
220 | } | ||
221 | |||
222 | SoundMixer::~SoundMixer() | ||
223 | { | ||
224 | if (--nbInst == 0) { | ||
225 | if (dsp > 0) { | ||
226 | close(dsp); | ||
227 | free(buffer); | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | |||
232 | void | ||
233 | SoundMixer::stopSounds() | ||
234 | { | ||
235 | #ifndef NOSOUND | ||
236 | SoundList *sl,*del; | ||
237 | |||
238 | for(sl = list; sl; ) { | ||
239 | del = sl; | ||
240 | sl = sl->next; | ||
241 | delete del; | ||
242 | } | ||
243 | list = 0; | ||
244 | #endif | ||
245 | } | ||
246 | |||
247 | void | ||
248 | SoundMixer::startSound(Sound *sound) | ||
249 | { | ||
250 | #ifndef NOSOUND | ||
251 | SoundList *sl; | ||
252 | |||
253 | if (sound) { | ||
254 | // Add sound in list | ||
255 | sl = new SoundList; | ||
256 | sl->rate = sound->getRate(); | ||
257 | sl->stereo = (sound->getChannel() == 2); | ||
258 | sl->sampleSize = sound->getSampleSize(); | ||
259 | sl->current = sound->getSamples(); | ||
260 | sl->remaining = sound->getSampleSize()*sound->getNbSamples()*sound->getChannel(); | ||
261 | sl->next = list; | ||
262 | list = sl; | ||
263 | } | ||
264 | #endif | ||
265 | } | ||
266 | |||
267 | long | ||
268 | SoundMixer::playSounds() | ||
269 | { | ||
270 | #ifndef NOSOUND | ||
271 | audio_buf_info bufInfo; | ||
272 | long nbBytes, n; | ||
273 | SoundList*sl,*prev; | ||
274 | int status; | ||
275 | |||
276 | // Init failed | ||
277 | if (dsp < 0) return 0; | ||
278 | |||
279 | // No sound to play | ||
280 | if (list == 0) return 0; | ||
281 | |||
282 | // Get free DMA buffer space | ||
283 | status = ioctl(dsp, SNDCTL_DSP_GETOSPACE, &bufInfo); | ||
284 | |||
285 | // Free space is not large enough to output data without blocking | ||
286 | // But there are still sounds to play. We must wait. | ||
287 | if (bufInfo.bytes < blockSize) return 1; | ||
288 | |||
289 | nbBytes = 0; | ||
290 | |||
291 | // Fill buffer with silence. | ||
292 | memset((void*)buffer, 0, blockSize); | ||
293 | |||
294 | prev = 0; | ||
295 | sl = list; | ||
296 | while(sl) { | ||
297 | |||
298 | // Ask sound to fill the buffer | ||
299 | // according to device capabilities | ||
300 | n = fillSoundBuffer(sl, buffer, blockSize); | ||
301 | |||
302 | // Remember the largest written size | ||
303 | if (n > nbBytes) { | ||
304 | nbBytes = n; | ||
305 | } | ||
306 | |||
307 | // No more samples for this sound | ||
308 | if (sl->remaining == 0) { | ||
309 | // Remove sound from list | ||
310 | if (prev) { | ||
311 | prev->next = sl->next; | ||
312 | delete sl; | ||
313 | sl = prev->next; | ||
314 | } else { | ||
315 | list = sl->next; | ||
316 | delete sl; | ||
317 | sl = list; | ||
318 | } | ||
319 | } else { | ||
320 | sl = sl->next; | ||
321 | } | ||
322 | } | ||
323 | |||
324 | if (nbBytes) { | ||
325 | // At last ! Play It ! | ||
326 | write(dsp,buffer,nbBytes); | ||
327 | status = ioctl(dsp, SNDCTL_DSP_POST); | ||
328 | } | ||
329 | |||
330 | return nbBytes; | ||
331 | #else | ||
332 | return 0; | ||
333 | #endif | ||
334 | } | ||
335 | |||
336 | long | ||
337 | SoundMixer::fillSoundBuffer(SoundList *sl, char *buff, long buffSize) | ||
338 | { | ||
339 | long sampleLeft, sampleRight; | ||
340 | long skipOut, skipOutInit; | ||
341 | long skipIn, skipInInit; | ||
342 | long freqRatio; | ||
343 | long totalOut = 0; | ||
344 | |||
345 | sampleLeft = sampleRight = 0; | ||
346 | skipOutInit = skipInInit = 0; | ||
347 | |||
348 | freqRatio = sl->rate / soundRate; | ||
349 | if (freqRatio) { | ||
350 | skipOutInit = freqRatio - 1; | ||
351 | skipInInit = 0; | ||
352 | } | ||
353 | |||
354 | freqRatio = soundRate / sl->rate; | ||
355 | if (freqRatio) { | ||
356 | skipInInit = freqRatio - 1; | ||
357 | skipOutInit = 0; | ||
358 | } | ||
359 | |||
360 | skipOut = skipOutInit; | ||
361 | skipIn = skipInInit; | ||
362 | while (buffSize && sl->remaining) { | ||
363 | if (skipIn-- == 0) { | ||
364 | // Get sampleLeft | ||
365 | if (sl->sampleSize == 2) { | ||
366 | sampleLeft = (long)(*(short *)(sl->current)); | ||
367 | if (sampleSize == 1) { | ||
368 | sampleLeft = (sampleLeft >> 8) &0xff; | ||
369 | } | ||
370 | } else { | ||
371 | sampleLeft = (long)*(sl->current); | ||
372 | if (sampleSize == 2) { | ||
373 | sampleLeft <<= 8; | ||
374 | } | ||
375 | } | ||
376 | sl->current += sl->sampleSize; | ||
377 | sl->remaining -= sl->sampleSize; | ||
378 | |||
379 | if (sl->stereo) { | ||
380 | // Get sampleRight | ||
381 | if (sl->sampleSize == 2) { | ||
382 | sampleRight = (long)(*(short *)(sl->current)); | ||
383 | if (sampleSize == 1) { | ||
384 | sampleRight = (sampleRight >> 8) &0xff; | ||
385 | } | ||
386 | } else { | ||
387 | sampleRight = (long)*(sl->current); | ||
388 | if (sampleSize == 2) { | ||
389 | sampleRight <<= 8; | ||
390 | } | ||
391 | } | ||
392 | sl->current += sl->sampleSize; | ||
393 | sl->remaining -= sl->sampleSize; | ||
394 | |||
395 | } else { | ||
396 | sampleRight = sampleLeft; | ||
397 | } | ||
398 | |||
399 | skipIn = skipInInit; | ||
400 | } | ||
401 | |||
402 | if (skipOut-- == 0) { | ||
403 | // Output | ||
404 | if (stereo) { | ||
405 | if (sampleSize == 2) { | ||
406 | *((short *)buff) += sampleLeft/2; | ||
407 | buffSize -= sampleSize; | ||
408 | buff += sampleSize; | ||
409 | *((short *)buff) += sampleRight/2; | ||
410 | buffSize -= sampleSize; | ||
411 | buff += sampleSize; | ||
412 | } else { | ||
413 | *((char *)buff) += sampleLeft/2; | ||
414 | buffSize -= sampleSize; | ||
415 | buff += sampleSize; | ||
416 | *((char *)buff) += sampleRight/2; | ||
417 | buffSize -= sampleSize; | ||
418 | buff += sampleSize; | ||
419 | } | ||
420 | totalOut += 2*sampleSize; | ||
421 | } else { | ||
422 | if (sampleSize == 2) { | ||
423 | *((short *)buff) += (sampleLeft+sampleRight)>>2; | ||
424 | buffSize -= sampleSize; | ||
425 | buff += sampleSize; | ||
426 | } else { | ||
427 | *((char *)buff) += (sampleLeft+sampleRight)>>2; | ||
428 | buffSize -= sampleSize; | ||
429 | buff += sampleSize; | ||
430 | } | ||
431 | totalOut += sampleSize; | ||
432 | } | ||
433 | |||
434 | skipOut = skipOutInit; | ||
435 | } | ||
436 | } | ||
437 | |||
438 | return totalOut; | ||
439 | } | ||