Home | History | Annotate | Download | only in views
      1 #include "SkOSSound.h"
      2 
      3 #ifdef SK_BUILD_FOR_WIN
      4 
      5 //////////////////////////////////////////////////////////////////////
      6 // Construction/Destruction
      7 //////////////////////////////////////////////////////////////////////
      8 
      9 #include <Mmreg.h>
     10 #if defined _WIN32 && _MSC_VER >= 1300	// disable nameless struct/union
     11 #pragma warning ( push )
     12 #pragma warning ( disable : 4201 )
     13 #endif
     14 #include <Mmsystem.h>
     15 #if defined _WIN32 && _MSC_VER >= 1300
     16 #pragma warning ( pop )
     17 #endif
     18 #include <stdio.h>
     19 
     20 class CWaveFile {
     21 public:
     22 	BOOL Open(const char path[]);
     23 	void Close();
     24 
     25 	long Read(char* pData, long nLength);
     26 
     27 	long GetLength() const {return m_nLength;}
     28 	WAVEFORMATEX* GetWaveFormat()	{return (&m_Format);}
     29 
     30 protected:
     31 	FILE* m_pFile;
     32 	long m_nLength;
     33 	WAVEFORMATEX m_Format;
     34 
     35 private:
     36 	enum {
     37 		WF_OFFSET_FORMATTAG	=		20,
     38 		WF_OFFSET_CHANNELS =			22,
     39 		WF_OFFSET_SAMPLESPERSEC =		24,
     40 		WF_OFFSET_AVGBYTESPERSEC =	28,
     41 		WF_OFFSET_BLOCKALIGN =		32,
     42 		WF_OFFSET_BITSPERSAMPLE =		34,
     43 		WF_OFFSET_DATASIZE =			40,
     44 		WF_OFFSET_DATA =				44,
     45 		WF_HEADER_SIZE = WF_OFFSET_DATA
     46 	};
     47 };
     48 
     49 BOOL CWaveFile::Open(const char path[])
     50 {
     51 	BYTE aHeader[WF_HEADER_SIZE];
     52 
     53 /*	hResInfo = FindResource (hInst, lpName, "WAVE");
     54 
     55 	if (hResInfo == NULL)
     56 	return FALSE;
     57 
     58 	// Load the wave resource.
     59 	hRes = LoadResource (hInst, hResInfo);
     60 
     61 	if (hRes == NULL)
     62 		return FALSE;
     63 
     64 	// Lock the wave resource and play it.
     65 	lpRes = LockResource (0);
     66 */
     67 
     68 
     69 	// open file
     70 //	m_pFile = _tfopen(szFileName, TEXT("rb"));
     71 	m_pFile = fopen(path, "rb");
     72 	if (!m_pFile) {
     73 		return FALSE;
     74 	}
     75 
     76 	// set file length
     77 	fseek(m_pFile, 0, SEEK_END);
     78 	m_nLength = ftell(m_pFile) - WF_HEADER_SIZE;
     79 
     80 	// set the format attribute members
     81 	fseek(m_pFile, 0, SEEK_SET);
     82 	fread(aHeader, 1, WF_HEADER_SIZE, m_pFile);
     83 	m_Format.wFormatTag = *((WORD*) (aHeader + WF_OFFSET_FORMATTAG));
     84 	m_Format.nChannels = *((WORD*) (aHeader + WF_OFFSET_CHANNELS));
     85 	m_Format.nSamplesPerSec = *((DWORD*) (aHeader + WF_OFFSET_SAMPLESPERSEC));
     86 	m_Format.nAvgBytesPerSec = *((DWORD*) (aHeader + WF_OFFSET_AVGBYTESPERSEC));
     87 	m_Format.nBlockAlign = *((WORD*) (aHeader + WF_OFFSET_BLOCKALIGN));
     88 	m_Format.wBitsPerSample = *((WORD*) (aHeader + WF_OFFSET_BITSPERSAMPLE));
     89 
     90 	return TRUE;
     91 }
     92 
     93 void CWaveFile::Close()
     94 {
     95 	fclose(m_pFile);
     96 }
     97 
     98 long CWaveFile::Read(char* pData, long nLength)
     99 {
    100 	return fread(pData, 1, nLength, m_pFile);
    101 }
    102 
    103 ////////////////////////////////////////////////////////////////////////////////////////
    104 
    105 struct SkOSSoundWave {
    106 	HWAVEOUT hwo;
    107 	WAVEHDR whdr;
    108 	DWORD dwOldVolume;
    109 	CWaveFile waveFile;
    110 	HANDLE hDoneEvent;
    111 };
    112 
    113 static SkOSSoundWave gWave;
    114 static bool			 gWavePaused;
    115 static U8			 gVolume;
    116 static bool			 gInited = false;
    117 
    118 static void init_wave()
    119 {
    120 	if (gInited == false)
    121 	{
    122 		gWave.hwo = NULL;
    123 		gWavePaused = false;
    124 		gVolume = 0x80;
    125 		gInited = true;
    126 	}
    127 }
    128 
    129 MMRESULT StartWave(const char path[], SkOSSoundWave* wave, U32 vol);
    130 MMRESULT EndWave(SkOSSoundWave* wave);
    131 
    132 #define MAX_ERRMSG 256
    133 
    134 //#include "SkOSFile.h"	// for utf16
    135 
    136 void SkOSSound::Play(const char path[])
    137 {
    138 	init_wave();
    139 
    140 	if (gWave.hwo != NULL)
    141 		SkOSSound::Stop();
    142 
    143 	U32 v32 = (gVolume << 8) | gVolume;	// fill it out to 16bits
    144 	v32 |= v32 << 16;					// set the left and right channels
    145 
    146 	StartWave(path, &gWave, v32);
    147 	gWavePaused = false;
    148 }
    149 
    150 bool SkOSSound::TogglePause()
    151 {
    152 	init_wave();
    153 
    154 	if (gWavePaused)
    155 		SkOSSound::Resume();
    156 	else
    157 		SkOSSound::Pause();
    158 	return !gWavePaused;
    159 }
    160 
    161 
    162 void SkOSSound::Pause()
    163 {
    164 	init_wave();
    165 
    166 	if (gWave.hwo == NULL || (gWave.whdr.dwFlags & WHDR_DONE))
    167 		return;
    168 	waveOutPause(gWave.hwo);
    169 	gWavePaused = true;
    170 }
    171 
    172 void SkOSSound::Resume()
    173 {
    174 	init_wave();
    175 
    176 	if (gWave.hwo == NULL || (gWave.whdr.dwFlags & WHDR_DONE))
    177 		return;
    178 	waveOutRestart(gWave.hwo);
    179 	gWavePaused = false;
    180 }
    181 
    182 void SkOSSound::Stop()
    183 {
    184 	init_wave();
    185 
    186 //	if (gWave.hwo == NULL || (gWave.whdr.dwFlags & WHDR_DONE))
    187 	if (gWave.hwo == NULL)
    188 		return;
    189 	waveOutReset(gWave.hwo);
    190 	EndWave(&gWave);
    191 	gWavePaused = false;
    192 	gWave.hwo = NULL;
    193 }
    194 
    195 U8 SkOSSound::GetVolume()
    196 {
    197 	init_wave();
    198 	return gVolume;
    199 }
    200 
    201 void SkOSSound::SetVolume(U8CPU vol)
    202 {
    203 	if ((int)vol < 0)
    204 		vol = 0;
    205 	else if (vol > 255)
    206 		vol = 255;
    207 
    208 	init_wave();
    209 	gVolume = SkToU8(vol);
    210 
    211 	if (gWave.hwo)
    212 	{
    213 		unsigned long v32 = (vol << 8) | vol;	// fill it out to 16bits
    214 		v32 |= v32 << 16;						// set the left and right channels
    215 		waveOutSetVolume(gWave.hwo, v32);
    216 	}
    217 }
    218 
    219 #if 0
    220 unsigned long SoundManager::GetPosition()
    221 {
    222 	if (fWave.hwo == NULL)
    223 		return 0;
    224 	MMTIME time;
    225 	time.wType = TIME_MS;
    226 	if (waveOutGetPosition(fWave.hwo, &time, sizeof(time)) == MMSYSERR_NOERROR &&
    227 		time.wType == TIME_MS)
    228 	{
    229 		return time.u.ms;
    230 	}
    231 	return 0;
    232 }
    233 #endif
    234 
    235 MMRESULT StartWave(const char path[], SkOSSoundWave* wave, U32 vol)
    236 {
    237 	HWAVEOUT hwo = NULL;
    238 //	WAVEHDR whdr;
    239 	MMRESULT mmres = 0;
    240 //	CWaveFile waveFile;
    241 //	HANDLE hDoneEvent = wave.hDoneEvent =
    242 //		CreateEvent(NULL, FALSE, FALSE, TEXT("DONE_EVENT"));
    243 	UINT devId;
    244 //	DWORD dwOldVolume;
    245 
    246 	// Open wave file
    247 	if (!wave->waveFile.Open(path)) {
    248 //		TCHAR szErrMsg[MAX_ERRMSG];
    249 //		_stprintf(szErrMsg,	TEXT("Unable to open file: %s\n"), szWavFile);
    250 //		MessageBox(NULL, szErrMsg, TEXT("File I/O Error"), MB_OK);
    251 		return MMSYSERR_NOERROR;
    252 	}
    253 
    254 	// Open audio device
    255 	for (devId = 0; devId < waveOutGetNumDevs(); devId++)
    256 	{
    257 		mmres = waveOutOpen(&hwo, devId, wave->waveFile.GetWaveFormat(), 0, 0, CALLBACK_NULL);
    258 		if (mmres == MMSYSERR_NOERROR)
    259 		{
    260 			wave->hwo = hwo;
    261 			break;
    262 		}
    263 	}
    264 	if (mmres != MMSYSERR_NOERROR)
    265 	{
    266 		SkDEBUGCODE(SkDebugf("waveOutOpen(%s) -> %d\n", path, mmres);)
    267 		return mmres;
    268 	}
    269 
    270 	// Set volume
    271 	mmres = waveOutGetVolume(hwo, &wave->dwOldVolume);
    272 	if (mmres != MMSYSERR_NOERROR) {
    273 		return mmres;
    274 	}
    275 
    276 	waveOutSetVolume(hwo, vol);
    277 	if (mmres != MMSYSERR_NOERROR) {
    278 		return mmres;
    279 	}
    280 
    281 	// Initialize wave header
    282 	ZeroMemory(&wave->whdr, sizeof(WAVEHDR));
    283 	wave->whdr.lpData = new char[wave->waveFile.GetLength()];
    284 	wave->whdr.dwBufferLength = wave->waveFile.GetLength();
    285 	wave->whdr.dwUser = 0;
    286 	wave->whdr.dwFlags = 0;
    287 	wave->whdr.dwLoops = 0;
    288 	wave->whdr.dwBytesRecorded = 0;
    289 	wave->whdr.lpNext = 0;
    290 	wave->whdr.reserved = 0;
    291 
    292 	// Play buffer
    293 	wave->waveFile.Read(wave->whdr.lpData, wave->whdr.dwBufferLength);
    294 
    295 	mmres = waveOutPrepareHeader(hwo, &wave->whdr, sizeof(WAVEHDR));
    296 	if (mmres != MMSYSERR_NOERROR) {
    297 		return mmres;
    298 	}
    299 
    300 	mmres = waveOutWrite(hwo, &wave->whdr, sizeof(WAVEHDR));
    301 //	if (mmres != MMSYSERR_NOERROR) {
    302 		return mmres;
    303 //	}
    304 }
    305 
    306 #if 0
    307 void IdleWave(Wave& wave)
    308 {
    309 	// Wait for audio to finish playing
    310 	while (!(wave.whdr.dwFlags & WHDR_DONE)) {
    311 		WaitForSingleObject(wave.hDoneEvent, INFINITE);
    312 	}
    313 }
    314 #endif
    315 
    316 MMRESULT EndWave(SkOSSoundWave* wave)
    317 {
    318 	HWAVEOUT hwo = wave->hwo;
    319 	MMRESULT mmres;
    320 	// Clean up
    321 	mmres = waveOutUnprepareHeader(hwo, &wave->whdr, sizeof(WAVEHDR));
    322 	if (mmres != MMSYSERR_NOERROR) {
    323 		return mmres;
    324 	}
    325 
    326 	waveOutSetVolume(hwo, wave->dwOldVolume);
    327 	if (mmres != MMSYSERR_NOERROR) {
    328 		return mmres;
    329 	}
    330 
    331 	mmres = waveOutClose(hwo);
    332 	if (mmres != MMSYSERR_NOERROR) {
    333 		return mmres;
    334 	}
    335 
    336 	delete [] wave->whdr.lpData;
    337 	wave->waveFile.Close();
    338 
    339 	return MMSYSERR_NOERROR;
    340 }
    341 
    342 #endif	/* SK_BUILD_FOR_WIN */
    343 
    344