summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/libflash/sound.cc
Side-by-side diff
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 @@
+/////////////////////////////////////////////////////////////
+// Flash Plugin and Player
+// Copyright (C) 1998,1999 Olivier Debon
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////
+// Author : Olivier Debon <odebon@club-internet.fr>
+//
+
+#include "swf.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#ifndef NOSOUND
+#include <linux/soundcard.h>
+#endif
+
+#ifdef RCSID
+static char *rcsid = "$Id$";
+#endif
+
+#define PRINT 0
+
+//////////// SOUND
+
+Sound::Sound(long id) : Character(SoundType, id)
+{
+ samples = 0;
+ stereo = 0;
+ soundRate = 0;
+ sampleSize = 1;
+}
+
+Sound::~Sound()
+{
+ if (samples) {
+ delete samples;
+ }
+}
+
+void
+Sound::setSoundFlags(long f) {
+ switch (GET_SOUND_RATE_CODE(f)) {
+ case 0:
+ soundRate = 5500;
+ break;
+ case 1:
+ soundRate = 11000;
+ break;
+ case 2:
+ soundRate = 22000;
+ break;
+ case 3:
+ soundRate = 44000;
+ break;
+ }
+ if (f & soundIs16bit) {
+ sampleSize = 2;
+ }
+ if (f & soundIsStereo) {
+ stereo = 1;
+ }
+
+#if PRINT
+ printf("-----\nFlags = %2x\n", f);
+ printf("Rate = %d kHz ", soundRate);
+ printf("SampleSize = %d byte(s) ", sampleSize);
+ if (f & soundIsStereo) {
+ printf("Stereo ");
+ } else {
+ printf("Mono ");
+ }
+ if (f & soundIsADPCMCompressed) {
+ printf("ADPCM\n");
+ } else {
+ printf("Raw\n");
+ }
+#endif
+}
+
+char *
+Sound::setNbSamples(long n) {
+ long size;
+
+ nbSamples = n;
+
+ size = nbSamples * (stereo ? 2 : 1) * sampleSize;
+
+ samples = new char[ size ];
+
+ memset((char *)samples,0, size);
+
+ return samples;
+}
+
+long
+Sound::getRate() {
+ return soundRate;
+}
+
+long
+Sound::getChannel() {
+ return stereo ? 2 : 1;
+}
+
+long
+Sound::getNbSamples() {
+ return nbSamples;
+}
+
+long
+Sound::getSampleSize() {
+ return sampleSize;
+}
+
+char *
+Sound::getSamples() {
+ return samples;
+}
+
+//////////// SOUND MIXER
+
+long SoundMixer::dsp = -1; // Init of descriptor
+long SoundMixer::blockSize = 0; // Driver sound buffer size
+long SoundMixer::nbInst = 0; // Nb SoundMixer instances
+long SoundMixer::sampleSize = 0;
+long SoundMixer::stereo = 0;
+long SoundMixer::soundRate = 0;
+char *SoundMixer::buffer = 0;
+
+SoundMixer::SoundMixer(char *device)
+{
+#ifndef NOSOUND
+ int status;
+ long fmt;
+
+ list = 0; // No sound to play
+
+ if (nbInst++) {
+ // Device is already open
+ return;
+ }
+
+ dsp = open(device,O_WRONLY);
+ if (dsp < 0) {
+ perror("open dsp");
+ return;
+ }
+
+ // Reset device
+ status = ioctl(dsp, SNDCTL_DSP_RESET);
+ if (status < 0) perror("ioctl SNDCTL_DSP_RESET");
+
+ // Set sample size
+ fmt = AFMT_S16_LE;
+ sampleSize = 2;
+ status = ioctl(dsp, SNDCTL_DSP_SETFMT, &fmt);
+ if (status < 0) perror("ioctl SNDCTL_DSP_SETFMT");
+
+ if (status) {
+ fmt = AFMT_U8;
+ sampleSize = 1;
+ status = ioctl(dsp, SNDCTL_DSP_SETFMT, &fmt);
+ if (status < 0) perror("ioctl SNDCTL_DSP_SETFMT");
+ }
+
+ // Set stereo channel
+ stereo = 1;
+ status = ioctl(dsp, SNDCTL_DSP_STEREO, &stereo);
+
+ if (status) {
+ stereo = 0;
+ }
+
+ // Set sound rate in Hertz
+ soundRate = 11000;
+ status = ioctl(dsp, SNDCTL_DSP_SPEED, &soundRate);
+ if (status < 0) perror("ioctl SNDCTL_DSP_SPEED");
+
+ // Get device buffer size
+ status = ioctl(dsp, SNDCTL_DSP_GETBLKSIZE, &blockSize);
+ if (status < 0) perror("ioctl SNDCTL_DSP_GETBLKSIZE");
+ if (blockSize < 1024) {
+ blockSize = 32768;
+ }
+ blockSize *= 2;
+
+ buffer = (char *)malloc(blockSize);
+ if (buffer == 0) {
+ close(dsp);
+ dsp = -1;
+ }
+
+#if PRINT
+ int caps;
+
+ ioctl(dsp,SNDCTL_DSP_GETCAPS, &caps);
+ printf("Audio capabilities = %x\n", caps);
+ printf("Sound Rate = %d\n", soundRate);
+ printf("Stereo = %d\n", stereo);
+ printf("Sample Size = %d\n", sampleSize);
+ printf("Buffer Size = %d\n", blockSize);
+#endif /* PRINT */
+
+#endif /* NOSOUND */
+}
+
+SoundMixer::~SoundMixer()
+{
+ if (--nbInst == 0) {
+ if (dsp > 0) {
+ close(dsp);
+ free(buffer);
+ }
+ }
+}
+
+void
+SoundMixer::stopSounds()
+{
+#ifndef NOSOUND
+ SoundList *sl,*del;
+
+ for(sl = list; sl; ) {
+ del = sl;
+ sl = sl->next;
+ delete del;
+ }
+ list = 0;
+#endif
+}
+
+void
+SoundMixer::startSound(Sound *sound)
+{
+#ifndef NOSOUND
+ SoundList *sl;
+
+ if (sound) {
+ // Add sound in list
+ sl = new SoundList;
+ sl->rate = sound->getRate();
+ sl->stereo = (sound->getChannel() == 2);
+ sl->sampleSize = sound->getSampleSize();
+ sl->current = sound->getSamples();
+ sl->remaining = sound->getSampleSize()*sound->getNbSamples()*sound->getChannel();
+ sl->next = list;
+ list = sl;
+ }
+#endif
+}
+
+long
+SoundMixer::playSounds()
+{
+#ifndef NOSOUND
+ audio_buf_info bufInfo;
+ long nbBytes, n;
+ SoundList *sl,*prev;
+ int status;
+
+ // Init failed
+ if (dsp < 0) return 0;
+
+ // No sound to play
+ if (list == 0) return 0;
+
+ // Get free DMA buffer space
+ status = ioctl(dsp, SNDCTL_DSP_GETOSPACE, &bufInfo);
+
+ // Free space is not large enough to output data without blocking
+ // But there are still sounds to play. We must wait.
+ if (bufInfo.bytes < blockSize) return 1;
+
+ nbBytes = 0;
+
+ // Fill buffer with silence.
+ memset((void*)buffer, 0, blockSize);
+
+ prev = 0;
+ sl = list;
+ while(sl) {
+
+ // Ask sound to fill the buffer
+ // according to device capabilities
+ n = fillSoundBuffer(sl, buffer, blockSize);
+
+ // Remember the largest written size
+ if (n > nbBytes) {
+ nbBytes = n;
+ }
+
+ // No more samples for this sound
+ if (sl->remaining == 0) {
+ // Remove sound from list
+ if (prev) {
+ prev->next = sl->next;
+ delete sl;
+ sl = prev->next;
+ } else {
+ list = sl->next;
+ delete sl;
+ sl = list;
+ }
+ } else {
+ sl = sl->next;
+ }
+ }
+
+ if (nbBytes) {
+ // At last ! Play It !
+ write(dsp,buffer,nbBytes);
+ status = ioctl(dsp, SNDCTL_DSP_POST);
+ }
+
+ return nbBytes;
+#else
+ return 0;
+#endif
+}
+
+long
+SoundMixer::fillSoundBuffer(SoundList *sl, char *buff, long buffSize)
+{
+ long sampleLeft, sampleRight;
+ long skipOut, skipOutInit;
+ long skipIn, skipInInit;
+ long freqRatio;
+ long totalOut = 0;
+
+ sampleLeft = sampleRight = 0;
+ skipOutInit = skipInInit = 0;
+
+ freqRatio = sl->rate / soundRate;
+ if (freqRatio) {
+ skipOutInit = freqRatio - 1;
+ skipInInit = 0;
+ }
+
+ freqRatio = soundRate / sl->rate;
+ if (freqRatio) {
+ skipInInit = freqRatio - 1;
+ skipOutInit = 0;
+ }
+
+ skipOut = skipOutInit;
+ skipIn = skipInInit;
+ while (buffSize && sl->remaining) {
+ if (skipIn-- == 0) {
+ // Get sampleLeft
+ if (sl->sampleSize == 2) {
+ sampleLeft = (long)(*(short *)(sl->current));
+ if (sampleSize == 1) {
+ sampleLeft = (sampleLeft >> 8) &0xff;
+ }
+ } else {
+ sampleLeft = (long)*(sl->current);
+ if (sampleSize == 2) {
+ sampleLeft <<= 8;
+ }
+ }
+ sl->current += sl->sampleSize;
+ sl->remaining -= sl->sampleSize;
+
+ if (sl->stereo) {
+ // Get sampleRight
+ if (sl->sampleSize == 2) {
+ sampleRight = (long)(*(short *)(sl->current));
+ if (sampleSize == 1) {
+ sampleRight = (sampleRight >> 8) &0xff;
+ }
+ } else {
+ sampleRight = (long)*(sl->current);
+ if (sampleSize == 2) {
+ sampleRight <<= 8;
+ }
+ }
+ sl->current += sl->sampleSize;
+ sl->remaining -= sl->sampleSize;
+
+ } else {
+ sampleRight = sampleLeft;
+ }
+
+ skipIn = skipInInit;
+ }
+
+ if (skipOut-- == 0) {
+ // Output
+ if (stereo) {
+ if (sampleSize == 2) {
+ *((short *)buff) += sampleLeft/2;
+ buffSize -= sampleSize;
+ buff += sampleSize;
+ *((short *)buff) += sampleRight/2;
+ buffSize -= sampleSize;
+ buff += sampleSize;
+ } else {
+ *((char *)buff) += sampleLeft/2;
+ buffSize -= sampleSize;
+ buff += sampleSize;
+ *((char *)buff) += sampleRight/2;
+ buffSize -= sampleSize;
+ buff += sampleSize;
+ }
+ totalOut += 2*sampleSize;
+ } else {
+ if (sampleSize == 2) {
+ *((short *)buff) += (sampleLeft+sampleRight)>>2;
+ buffSize -= sampleSize;
+ buff += sampleSize;
+ } else {
+ *((char *)buff) += (sampleLeft+sampleRight)>>2;
+ buffSize -= sampleSize;
+ buff += sampleSize;
+ }
+ totalOut += sampleSize;
+ }
+
+ skipOut = skipOutInit;
+ }
+ }
+
+ return totalOut;
+}