TNB Library
TnbWavePlayer.h
[詳解]
1#pragma once
11#include "TnbSync.h"
12#include <mmsystem.h>
13#pragma comment(lib, "winmm.lib")
14
15
16
17//TNB Library
18namespace TNB
19{
20
21
22
32{
33public:
35 CWavePlayer(void) : m_bankNumber(0), m_hWave(NULL), m_currentBank(0), m_pBuffers(NULL), m_pSyncBank(NULL), m_hasBuffer(false)
36 {
37 }
38
41 {
42 Close();
43 }
44
46 void Close(void)
47 {
48 if ( m_hWave != NULL )
49 {
50 ::waveOutReset(m_hWave);
51 ::waveOutClose(m_hWave);
52 m_hWave = NULL;
53 }
54 if ( m_pBuffers != NULL )
55 {
56 delete[] m_pBuffers;
57 m_pBuffers = NULL;
58 }
59 if ( m_pSyncBank != NULL )
60 {
61 delete m_pSyncBank;
62 m_pSyncBank = NULL;
63 }
64 m_bankNumber = 0;
65 m_currentBank = 0;
66 }
67
76 MMRESULT Open(const WAVEFORMATEX& format, int bankNumber, UINT bankSize)
77 {
78 Close();
79 m_bankNumber = bankNumber;
80 m_pSyncBank = new CSyncSemaphore(NULL, bankNumber);
81 MMRESULT mr = ::waveOutOpen(&m_hWave, WAVE_MAPPER, &format,
82 reinterpret_cast<DWORD_PTR>(ms_WaveCallback),
83 reinterpret_cast<DWORD_PTR>(m_pSyncBank), CALLBACK_FUNCTION);
84 if ( mr == MMSYSERR_NOERROR )
85 {
86 m_pBuffers = new CBuffer[m_bankNumber];
87 loop ( i, m_bankNumber )
88 {
89 mr = m_pBuffers[i].Init(m_hWave, bankSize);
90 if ( mr != MMSYSERR_NOERROR )
91 {
92 break;
93 }
94 }
95 m_hasBuffer = false;
96 }
97 if ( mr != MMSYSERR_NOERROR )
98 {
99 Close();
100 }
101 return mr;
102 }
103
114 MMRESULT Write(bool& _isPlayed, const BYTE* pData, size_t size)
115 {
116 if ( m_bankNumber == 0 ) { return MMSYSERR_ERROR; }
117 size_t nWritten = 0;
118 while ( size > 0 )
119 {
120 if ( ! m_hasBuffer )
121 {
122 m_pSyncBank->Lock();
123 m_hasBuffer = true;
124 }
125 bool isPlayed;
126 MMRESULT r = m_pBuffers[m_currentBank].Write(isPlayed, nWritten, pData, size);
127 if ( r != MMSYSERR_NOERROR )
128 {
129 return r;
130 }
131 if ( isPlayed )
132 {
133 m_hasBuffer = false;
134 m_currentBank = (m_currentBank + 1) % m_bankNumber;
135 }
136 size -= nWritten;
137 pData += nWritten;
138 }
139 return MMSYSERR_NOERROR;
140 }
141
148 MMRESULT Flush(void)
149 {
150 MMRESULT r = MMSYSERR_NOERROR;
151 if ( m_bankNumber != 0 )
152 {
153 if ( m_hasBuffer )
154 {
155 r = m_pBuffers[m_currentBank].Flush();
156 m_hasBuffer = false;
157 }
158 m_currentBank = (m_currentBank + 1) % m_bankNumber;
159 }
160 return r;
161 }
162
166 void Clear(void)
167 {
168 loop ( i, m_bankNumber )
169 {
170 m_pBuffers[i].Clear();
171 }
172 m_currentBank = 0;
173 }
174
176 void Pause(void)
177 {
178 ::waveOutPause(m_hWave);
179 }
180
182 void Restart(void)
183 {
184 ::waveOutRestart(m_hWave);
185 }
186
188 void Reset(void)
189 {
190 ::waveOutReset(m_hWave);
191 }
192
198 void SetVolume(int vol)
199 {
200 DWORD lvol = vol * 512;
201 DWORD rvol = vol * 512;
202 ::waveOutSetVolume(m_hWave, MAKELONG(lvol, rvol));
203 }
204
209 int GetVolume(void) const
210 {
211 DWORD vol;
212 ::waveOutGetVolume(m_hWave, &vol);
213 return LOWORD(vol) / 512;
214 }
215
216private:
218 class CBuffer
219 {
220 WAVEHDR m_hdr;
221 HWAVEOUT m_hWave;
222 size_t m_sentBytes;
223 public:
225 CBuffer(void) : m_hWave(NULL), m_sentBytes(0)
226 {
227 Zero(m_hdr);
228 }
230 ~CBuffer(void)
231 {
232 if ( m_hdr.lpData != NULL )
233 {
234 ::waveOutUnprepareHeader(m_hWave, &m_hdr, sizeof(WAVEHDR));
235 ::LocalFree(m_hdr.lpData);
236 m_hdr.lpData = NULL;
237 }
238 }
246 MMRESULT Init(HWAVEOUT hWave, UINT size)
247 {
248 m_hWave = hWave;
249 m_sentBytes = 0;
250 Zero(m_hdr);
251 m_hdr.lpData = static_cast<LPSTR>(::LocalAlloc(LMEM_FIXED, size));
252 if ( m_hdr.lpData == NULL )
253 {
254 return MMSYSERR_ERROR;
255 }
256 m_hdr.dwBufferLength = size;
257 return ::waveOutPrepareHeader(hWave, &m_hdr, sizeof(WAVEHDR));
258 }
260 MMRESULT Flush(void)
261 {
262 size_t s = m_hdr.dwBufferLength;
263 m_hdr.dwBufferLength = m_sentBytes;
264 MMRESULT r = ::waveOutWrite(m_hWave, &m_hdr, sizeof(WAVEHDR));
265 m_sentBytes = 0;
266 m_hdr.dwBufferLength = s;
267 return r;
268 }
270 void Clear(void)
271 {
272 m_sentBytes = 0;
273 }
283 MMRESULT Write(bool& _isPlayed, size_t& _writtenSize, const BYTE* pData, size_t size)
284 {
285 _writtenSize = min(m_hdr.dwBufferLength - m_sentBytes, size);
286 ::CopyMemory(m_hdr.lpData + m_sentBytes, pData, _writtenSize);
287 m_sentBytes += _writtenSize;
288 if ( m_sentBytes == m_hdr.dwBufferLength )
289 {
290 m_sentBytes = 0;
291 _isPlayed = true;
292 return ::waveOutWrite(m_hWave, &m_hdr, sizeof(WAVEHDR));
293 }
294 _isPlayed = false;
295 return MMSYSERR_NOERROR;
296 }
297 };
299 static void CALLBACK ms_WaveCallback(HWAVEOUT hWave, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
300 {
301 if ( uMsg == WOM_DONE )
302 {
303 CSyncSemaphore* P = reinterpret_cast<CSyncSemaphore*>(dwUser);
304 P->Unlock();
305 }
306 }
307 CSyncSemaphore* m_pSyncBank;
308 HWAVEOUT m_hWave;
309 int m_bankNumber;
310 int m_currentBank;
311 CBuffer* m_pBuffers;
312 bool m_hasBuffer;
313};
314
315
316
317}; //TNB
#define loop(VAR, CNT)
loop構文.
Definition: TnbDef.h:343
同期処理関係のヘッダ
virtual bool Lock(DWORD dwTime=INFINITE) const
[排他] ロック
Definition: TnbSync.h:91
[ETC] コピー不可能スーパークラス.
Definition: TnbDef.h:599
Semaphore排他管理クラス
Definition: TnbSync.h:370
virtual void Unlock(void) const
[排他] アンロック
Definition: TnbSync.h:421
WAVE再生クラス
Definition: TnbWavePlayer.h:32
MMRESULT Flush(void)
[書込] 再生
CWavePlayer(void)
コンストラクタ
Definition: TnbWavePlayer.h:35
void Clear(void)
[設定] クリア
MMRESULT Write(bool &_isPlayed, const BYTE *pData, size_t size)
[書込] 再生
void Pause(void)
[処理] 一時停止
void SetVolume(int vol)
[設定] ボリューム設定.
void Close(void)
クローズ
Definition: TnbWavePlayer.h:46
MMRESULT Open(const WAVEFORMATEX &format, int bankNumber, UINT bankSize)
[初期] オープン
Definition: TnbWavePlayer.h:76
void Restart(void)
[処理] 再スタート
int GetVolume(void) const
[取得] ボリューム取得.
~CWavePlayer(void)
デストラクタ
Definition: TnbWavePlayer.h:40
void Reset(void)
[再生] 停止
void Zero(V &value)
[設定] ゼロクリア.
Definition: TnbDef.h:399
TNB Library
Definition: TnbDoxyTitle.txt:2