?? sound.cpp
字號:
/////////////////////////////////////////////////////////////
// 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>
#include <windows.h>
#include <mmsystem.h>
#include <math.h>
#endif
#define WAV_BUFFERS 1
#define BUFF_AHEAD 8
#define WAV_MASK 0x1F
#define WAV_BUFFER_SIZE 0x40000
#define SECONDARY_BUFFER_SIZE 0x10000
#ifdef RCSID
static char *rcsid = "$Id: sound.cc,v 1.11 1999/01/31 21:14:22 olivier Exp $";
#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;
HANDLE hData;
HGLOBAL hWaveHdr;
LPWAVEHDR lpWaveHdr;
HWAVEOUT hWaveOut;
WAVEOUTCAPS wavecaps;
DWORD gSndBufSize;
BOOL waveInit = FALSE;
SoundMixer::SoundMixer(char *device)
{
#ifndef NOSOUND
WAVEFORMATEX format;
int i;
HRESULT hr;
list = 0; // No sound to play
if (nbInst++) {
// Device is already open
return;
}
memset (&format, 0, sizeof(format));
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = 2;
format.wBitsPerSample = 16;
format.nSamplesPerSec = 11025;
format.nBlockAlign = format.nChannels*format.wBitsPerSample / 8;
format.cbSize = 0;
format.nAvgBytesPerSec = format.nSamplesPerSec*format.nBlockAlign;
// Open a waveform device for output using window callback.
hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER,
&format, 0, 0L, CALLBACK_NULL);
if (hr != MMSYSERR_NOERROR) {
// perror("open dsp");
MessageBox(NULL, _T("waveOutOpen error"), _T(""), MB_SETFOREGROUND);
dsp = -1;
return;
} else {
dsp = 1;
}
stereo = 1;
sampleSize = 2;
soundRate = 11000;
blockSize = WAV_BUFFERS*WAV_BUFFER_SIZE;
buffer = (char *)malloc(blockSize);
if (buffer == 0) {
return;
}
memset (buffer, 0, blockSize);
lpWaveHdr = (LPWAVEHDR)malloc((DWORD) sizeof(WAVEHDR) * WAV_BUFFERS);
//if (hWaveHdr == NULL)
if (lpWaveHdr == NULL)
{
MessageBox(NULL, _T("malloc error"), _T(""), MB_SETFOREGROUND);
return;
}
memset (lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS);
for (i = 0; i < WAV_BUFFERS; i++)
{
lpWaveHdr[i].dwBufferLength = WAV_BUFFER_SIZE;
lpWaveHdr[i].lpData = buffer + i*WAV_BUFFER_SIZE;
if ((hr = waveOutPrepareHeader(hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR))) != MMSYSERR_NOERROR)
{
TCHAR szErr[256];
wsprintf(szErr, _T("waveOutPrepareHeader error %d %d ... "), GetLastError(), hr);
MessageBox(NULL, szErr, _T(""), MB_SETFOREGROUND);
return;
}
}
/*
for (i = 0; i < NUM_CHANNELS; i++)
{
ResetChannel(i);
}
*/
waveInit = TRUE;
#endif /* NOSOUND */
}
SoundMixer::~SoundMixer
()
{
#ifndef NOSOUND
if (--nbInst == 0) {
int i;
if ( hWaveOut )
{
waveOutReset(hWaveOut);
if (lpWaveHdr)
{
for (i = 0; i < WAV_BUFFERS; i++)
{
waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR));
}
}
waveOutClose (hWaveOut);
//if (hWaveHdr)
if (lpWaveHdr)
{
// These functions are not supported in Windows CE
//GlobalUnlock(hWaveHdr);
//GlobalFree(hWaveHdr);
free(lpWaveHdr);
}
if (buffer)
{
free(buffer);
}
}
hWaveOut = 0;
hData = 0;
hWaveHdr = 0;
buffer = NULL;
lpWaveHdr = NULL;
}
#endif
}
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
}
BOOL firsttime = TRUE;
long
SoundMixer::playSounds()
{
#ifndef NOSOUND
// audio_buf_info bufInfo;
long nbBytes, n;
SoundList *sl,*prev;
int status;
DWORD flags;
// Init failed
if (dsp < 0) return 0;
// No sound to play
if (list == 0) return 0;
if (!waveInit) return 0;
flags = lpWaveHdr[ 0 & WAV_MASK].dwFlags;
// Get free DMA buffer space
//status = ioctl(dsp, SNDCTL_DSP_GETOSPACE, &bufInfo);
if (firsttime) {
firsttime = FALSE;
waveOutRestart(hWaveOut);
flags = WHDR_DONE;
}
if (!(flags & WHDR_DONE)) {
return 0;
} else {
firsttime = TRUE;
}
if (firsttime) {
firsttime = FALSE;
waveOutRestart(hWaveOut);
}
// 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);
int hr;
lpWaveHdr[0].dwBufferLength = nbBytes;
if ((hr = waveOutWrite(hWaveOut, &lpWaveHdr[0&WAV_MASK], sizeof(WAVEHDR))) != MMSYSERR_NOERROR) {
TCHAR szErr[256];
wsprintf(szErr, _T("waveOutWrite error %d %d ... "), GetLastError(), hr);
//MessageBox(NULL, szErr, _T(""), MB_SETFOREGROUND);
return 0;
}
//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;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -