summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/libflash/sound.cc
Unidiff
Diffstat (limited to 'core/multimedia/opieplayer/libflash/sound.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/libflash/sound.cc439
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
33static char *rcsid = "$Id$";
34#endif
35
36#define PRINT 0
37
38//////////// SOUND
39
40Sound::Sound(long id) : Character(SoundType, id)
41{
42 samples = 0;
43 stereo = 0;
44 soundRate = 0;
45 sampleSize = 1;
46}
47
48Sound::~Sound()
49{
50 if (samples) {
51 delete samples;
52 }
53}
54
55void
56Sound::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
95char *
96Sound::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
110long
111Sound::getRate() {
112 return soundRate;
113}
114
115long
116Sound::getChannel() {
117 return stereo ? 2 : 1;
118}
119
120long
121Sound::getNbSamples() {
122 return nbSamples;
123}
124
125long
126Sound::getSampleSize() {
127 return sampleSize;
128}
129
130char *
131Sound::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
140long SoundMixer::sampleSize = 0;
141long SoundMixer::stereo = 0;
142long SoundMixer::soundRate = 0;
143char *SoundMixer::buffer = 0;
144
145SoundMixer::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
222SoundMixer::~SoundMixer()
223{
224 if (--nbInst == 0) {
225 if (dsp > 0) {
226 close(dsp);
227 free(buffer);
228 }
229 }
230}
231
232void
233SoundMixer::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
247void
248SoundMixer::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
267long
268SoundMixer::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
336long
337SoundMixer::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}