⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sound.cpp

📁 Evc编的一个在wince5.0上运行的flash播放器
💻 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 + -