• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetLength() const27 	long GetLength() const {return m_nLength;}
GetWaveFormat()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 
Open(const char path[])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 
Close()93 void CWaveFile::Close()
94 {
95 	fclose(m_pFile);
96 }
97 
Read(char * pData,long nLength)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 
init_wave()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 
Play(const char path[])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 
TogglePause()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 
Pause()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 
Resume()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 
Stop()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 
GetVolume()195 U8 SkOSSound::GetVolume()
196 {
197 	init_wave();
198 	return gVolume;
199 }
200 
SetVolume(U8CPU vol)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 
StartWave(const char path[],SkOSSoundWave * wave,U32 vol)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 
EndWave(SkOSSoundWave * wave)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