• R/O
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

X operations(XOPS)に非常に近いFPSゲームを制作・リメイクし、成果物をオープンソースとして公開することを目的としたプロジェクトです。


Commit MetaInfo

Revision137 (tree)
Time2016-06-19 16:30:13
Authorxops-mikan

Log Message

サウンドで用いるezdsとDirectSoundをソースファイルごと分割

Change Summary

Incremental Difference

--- trunk/sound.cpp (revision 136)
+++ trunk/sound.cpp (nonexistent)
@@ -1,750 +0,0 @@
1-//! @file sound.cpp
2-//! @brief SoundControlクラスの定義
3-
4-//--------------------------------------------------------------------------------
5-//
6-// OpenXOPS
7-// Copyright (c) 2014-2016, OpenXOPS Project / [-_-;](mikan) All rights reserved.
8-//
9-// Redistribution and use in source and binary forms, with or without
10-// modification, are permitted provided that the following conditions are met:
11-// * Redistributions of source code must retain the above copyright notice,
12-// this list of conditions and the following disclaimer.
13-// * Redistributions in binary form must reproduce the above copyright notice,
14-// this list of conditions and the following disclaimer in the documentation
15-// and/or other materials provided with the distribution.
16-// * Neither the name of the OpenXOPS Project nor the names of its contributors
17-// may be used to endorse or promote products derived from this software
18-// without specific prior written permission.
19-//
20-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23-// DISCLAIMED. IN NO EVENT SHALL OpenXOPS Project BE LIABLE FOR ANY
24-// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27-// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30-//--------------------------------------------------------------------------------
31-
32-#include "sound.h"
33-
34-#ifdef SOUND_DIRECTSOUND
35-
36-//! @brief コンストラクタ
37-SoundControl::SoundControl()
38-{
39- pDSound = NULL;
40-}
41-
42-//! @brief ディストラクタ
43-SoundControl::~SoundControl()
44-{
45- DestroySound();
46-}
47-
48-//! @brief 初期化
49-//! @param WindowCtrl WindowControlクラスのポインタ
50-//! @return 成功:0 失敗:1
51-int SoundControl::InitSound(WindowControl *WindowCtrl)
52-{
53-#ifdef ENABLE_DEBUGLOG
54- //ログに出力
55- OutputLog.WriteLog(LOG_INIT, "サウンド", "DirectSound");
56-#endif
57-
58- //DirectSoundオブジェクトを生成
59- if( FAILED( DirectSoundCreate8(NULL, &pDSound, NULL) ) ){
60- return 1;
61- }
62-
63- //協調レベルの設定
64- if( FAILED( pDSound->SetCooperativeLevel(WindowCtrl->GethWnd(), DSSCL_EXCLUSIVE) ) ){
65- return 1;
66- }
67-
68- //プライマリ バッファを作成し、リスナーインターフェイスを取得する
69- LPDIRECTSOUNDBUFFER pPrimary;
70- DSBUFFERDESC dsbd;
71- ZeroMemory(&dsbd, sizeof(DSBUFFERDESC));
72- dsbd.dwSize = sizeof(DSBUFFERDESC);
73- dsbd.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER;
74- if( SUCCEEDED(pDSound->CreateSoundBuffer(&dsbd, &pPrimary, NULL)) ){
75- pPrimary->QueryInterface(IID_IDirectSound3DListener8,(LPVOID *)&p3DListener);
76- pPrimary->Release();
77- }
78-
79- //ドップラー効果を無効に
80- p3DListener->SetDopplerFactor(DS3D_MINDOPPLERFACTOR, DS3D_IMMEDIATE);
81-
82- //ロール・オフ(減衰度合い)設定
83- p3DListener->SetRolloffFactor(0.05f, DS3D_IMMEDIATE);
84-
85-#ifdef ENABLE_DEBUGLOG
86- //ログに出力
87- OutputLog.WriteLog(LOG_COMPLETE, "", "");
88-#endif
89-
90- return 0;
91-}
92-
93-//! @brief 解放
94-//! @attention 本関数は自動的に呼び出されますが、明示的に呼び出すことも可能です。
95-void SoundControl::DestroySound()
96-{
97- if( pDSound == NULL ){ return; }
98-
99- for(int i=0;i<MAX_LOADSOUND; i++){
100- for(int j=0; j<MAX_SOUNDLISTS; j++){
101- if( pDSBuffer[i][j] != NULL ){
102- pDSBuffer[i][j]->Release();
103- pDSBuffer[i][j] = NULL;
104- }
105- }
106- }
107- if( pDSound != NULL ){
108- pDSound->Release();
109- pDSound = NULL;
110- }
111-
112-#ifdef ENABLE_DEBUGLOG
113- //ログに出力
114- OutputLog.WriteLog(LOG_CLEANUP, "サウンド", "DirectSound");
115-#endif
116-}
117-
118-//! @brief 再生音量を設定
119-//! @param volume 再生音量 (0.0=無音 1.0=100%)
120-void SoundControl::SetVolume(float volume)
121-{
122- //
123-}
124-
125-//! @brief カメラの座標と角度を設定
126-//! @param x カメラのX座標
127-//! @param y カメラのY座標
128-//! @param z カメラのZ座標
129-//! @param rx カメラのX軸角度 (予約)
130-//! @warning 毎フレーム呼び出して、最新のカメラ座標を設定(適用)してください。
131-void SoundControl::SetCamera(float x, float y, float z, float rx)
132-{
133- p3DListener->SetPosition(x, y, z, DS3D_IMMEDIATE);
134- p3DListener->SetOrientation(cos(rx), 0.0f, sin(rx), 0.0f, 1.0f, 0.0f, DS3D_IMMEDIATE);
135-}
136-
137-//! @brief サウンドを読み込む
138-//! @param filename ファイル名
139-//! @return 成功:0以上の認識番号 失敗:-1
140-//! @attention 2チャンネル(ステレオ)データが指定された場合、右側のデータだけ取得され、左側のデータは無視されます。
141-int SoundControl::LoadSound(char* filename)
142-{
143- if( pDSound == NULL ){ return -1; }
144-
145-#ifdef ENABLE_DEBUGLOG
146- //ログに出力
147- OutputLog.WriteLog(LOG_LOAD, "サウンド", filename);
148-#endif
149-
150- //開いている番号を探す
151- int id=0;
152- for(id=0; id<MAX_LOADSOUND; id++){
153- if( pDSBuffer[id][0] == NULL ){ break; }
154- }
155- if( id == MAX_LOADSOUND ){ return -1; }
156-
157- WAVEFORMATEX* pwfex;
158- int WavSize = 0;
159- int Wavoffset = 0;
160- bool d2channels = false;
161-
162- //Waveファイルの情報を取得
163- if( CheckSoundFile(filename, &WavSize, &Wavoffset, &pwfex) == true ){
164- return -1;
165- }
166- pwfex->cbSize = 0;
167-
168- //もしステレオデータなら
169- if( pwfex->nChannels == 2 ){
170- d2channels = true; //フラグを設定
171- WavSize /= 2; //サイズを半分に
172-
173- //モノラルとして強制的に再計算
174- pwfex->nChannels = 1;
175- pwfex->nAvgBytesPerSec /= 2;
176- pwfex->nBlockAlign /= 2;
177- }
178-
179- // DirectSoundセカンダリーバッファー作成
180- DSBUFFERDESC dsbd;
181- ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
182- dsbd.dwSize = sizeof(DSBUFFERDESC);
183- dsbd.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME;
184- dsbd.dwBufferBytes = WavSize;
185- dsbd.guid3DAlgorithm = DS3DALG_NO_VIRTUALIZATION;
186- dsbd.lpwfxFormat = pwfex;
187- if( FAILED( pDSound->CreateSoundBuffer(&dsbd, &pDSBuffer[id][0], NULL) ) ){
188- return -1; //セカンダリバッファー作成失敗
189- }
190-
191- //ロックする
192- VOID* pBuffer = NULL;
193- DWORD dwBufferSize = 0;
194- if( FAILED(pDSBuffer[id][0]->Lock(0, WavSize, &pBuffer, &dwBufferSize, NULL, NULL, 0) ) ){
195- return -1; //バッファのロック失敗
196- }
197-
198- //一時領域を確保
199- BYTE* pWavData;
200- int dwSize = dwBufferSize;
201- if( dwSize > WavSize ){ dwSize = WavSize; }
202- if( d2channels == true ){
203- dwSize = dwSize * 2;
204- }
205- pWavData = new BYTE[dwSize];
206- if( pWavData == NULL ){
207- //WAVEファイルを読み込むメモリーが確保できない
208- return -1;
209- }
210-
211-#ifdef PATH_DELIMITER_SLASH
212- //パス区切り文字を変換
213- filename = ChangePathDelimiter(filename);
214-#endif
215-
216- //波形データを取り込む
217- FILE* fp;
218- fp = fopen(filename,"rb");
219- fseek(fp, Wavoffset, SEEK_SET);
220- fread(pWavData, 1, dwSize, fp);
221- fclose(fp);
222-
223- //一時領域からセカンダリバッファーへコピー
224- if( d2channels == false ){
225- //モノラルデータなら1バイトづつコピーする
226- for(int i=0; i<dwSize; i++){
227- *((BYTE*)pBuffer+i) = *((BYTE*) pWavData+i);
228- }
229- }
230- else{
231- //サンプリングバイト数を取得
232- int samplingbytes = pwfex->wBitsPerSample/2;
233-
234- //ステレオデータなら、右側のデータだけ格納
235- int byte = 0;
236- for(int i=0; i<dwSize; i++){
237- *((BYTE*)pBuffer+byte) = *((BYTE*) pWavData+i);
238- byte += 1;
239- if( i%samplingbytes == samplingbytes-1 ){ i += samplingbytes; } //左側のデータはスキップ
240- }
241- }
242-
243- //ロック解除
244- pDSBuffer[id][0]->Unlock(pBuffer, dwBufferSize, NULL, 0);
245-
246- //一時領域を解放
247- delete pWavData;
248-
249- //フォーマット情報解放
250- delete pwfex;
251-
252- //セカンダリバッファーのコピーを作成
253- for(int i=1; i<MAX_SOUNDLISTS; i++){
254- if( pDSound->DuplicateSoundBuffer(pDSBuffer[id][0], &(pDSBuffer[id][i])) != DS_OK ){
255- CleanupSound(id);
256- return -1;
257- }
258- }
259-
260- //音量最小で一度再生しておく
261- pDSBuffer[id][0]->SetVolume(DSBVOLUME_MIN);
262- pDSBuffer[id][0]->Play(NULL, 0, NULL);
263-
264-#ifdef ENABLE_DEBUGLOG
265- //ログに出力
266- OutputLog.WriteLog(LOG_COMPLETE, "", id);
267-#endif
268-
269- return id;
270-}
271-
272-//! @brief サウンドを再生(非3D再生)
273-//! @param id 認識番号
274-//! @param volume 再生ボリューム
275-//! @param pan <無効>
276-//! @return 成功:1 失敗:0
277-//! @note 用途:プレイヤー自身が発生する音・ゲーム空間全体で均一に鳴らす音・BGM
278-int SoundControl::PlaySound(int id, int volume, int pan)
279-{
280- if( pDSound == NULL ){ return 0; }
281- if( (id < 0)||(MAX_LOADSOUND -1 < id) ){ return 0; }
282- if( pDSBuffer[id][0] == NULL ){ return 0; }
283-
284- DWORD status = 0;
285-
286- for(int i=0; i<MAX_SOUNDLISTS; i++){
287- //再生状況を取得
288- pDSBuffer[id][i]->GetStatus(&status);
289-
290- //サウンドが停止中ならば
291- if( (status & DSBSTATUS_PLAYING) == 0x00 ){
292- LPDIRECTSOUND3DBUFFER pDS3DBuffer;
293- DWORD status = 0;
294- if( FAILED(pDSBuffer[id][i]->QueryInterface(IID_IDirectSound3DBuffer8,(VOID**)&pDS3DBuffer)) ){
295- //IDirectSound3DBuffer8を取得できない
296- return 0;
297- }
298-
299- //3D再生を無効
300- pDS3DBuffer->SetMode(DS3DMODE_DISABLE, DS3D_IMMEDIATE);
301-
302- //ボリュームを設定し再生
303- pDSBuffer[id][i]->SetVolume( GetDSVolume(volume) );
304- pDSBuffer[id][i]->Play(NULL, 0, NULL);
305- return 1;
306- }
307- }
308-
309- return 0;
310-}
311-
312-//! @brief サウンドを再生(3D再生)
313-//! @param id 認識番号
314-//! @param x 音源のX座標
315-//! @param y 音源のY座標
316-//! @param z 音源のZ座標
317-//! @param volume 再生ボリューム
318-//! @return 成功:1 失敗:0
319-//! @note 用途:絶対的な位置を持ち距離により減衰する、一般的な効果音。
320-int SoundControl::Play3DSound(int id, float x, float y, float z, int volume)
321-{
322- if( pDSound == NULL ){ return 0; }
323- if( (id < 0)||(MAX_LOADSOUND -1 < id) ){ return 0; }
324- if( pDSBuffer[id][0] == NULL ){ return 0; }
325-
326- DWORD status = 0;
327-
328- for(int i=0; i<MAX_SOUNDLISTS; i++){
329- //再生状況を取得
330- pDSBuffer[id][i]->GetStatus(&status);
331-
332- //サウンドが停止中ならば
333- if( (status & DSBSTATUS_PLAYING) == 0x00 ){
334-
335- LPDIRECTSOUND3DBUFFER pDS3DBuffer;
336- if( FAILED(pDSBuffer[id][i]->QueryInterface(IID_IDirectSound3DBuffer8,(VOID**)&pDS3DBuffer)) ){
337- //IDirectSound3DBuffer8を取得できない
338- return 0;
339- }
340-
341- //最小距離と最大距離の設定
342- pDS3DBuffer->SetMinDistance(1, DS3D_IMMEDIATE);
343- pDS3DBuffer->SetMaxDistance(MAX_SOUNDDIST, DS3D_IMMEDIATE);
344-
345- //音源の座標を設定
346- pDS3DBuffer->SetPosition(x, y, z, DS3D_IMMEDIATE);
347-
348- //3D再生を有効
349- pDS3DBuffer->SetMode(DS3DMODE_NORMAL, DS3D_IMMEDIATE);
350-
351- //ボリュームを設定し再生
352- pDSBuffer[id][i]->SetVolume( GetDSVolume(volume) );
353- pDSBuffer[id][i]->Play(NULL, 0, NULL);
354- return 1;
355- }
356- }
357-
358- return 0;
359-}
360-
361-//! @brief サウンドを解放
362-//! @param id 認識番号
363-void SoundControl::CleanupSound(int id)
364-{
365- if( pDSound == NULL ){ return; }
366- if( (id < 0)||(MAX_LOADSOUND -1 < id) ){ return; }
367- if( pDSBuffer[id][0] == NULL ){ return; }
368-
369- //対象の全セカンダリバッファーを解放
370- for(int i=0; i<MAX_SOUNDLISTS; i++){
371- if( pDSBuffer[id][i] != NULL ){ pDSBuffer[id][i]->Release(); }
372- pDSBuffer[id][i] = NULL;
373- }
374-
375-#ifdef ENABLE_DEBUGLOG
376- //ログに出力
377- OutputLog.WriteLog(LOG_CLEANUP, "サウンド", id);
378-#endif
379-}
380-
381-//! @brief Waveファイルの情報を調べる
382-//! @param filename ファイル名
383-//! @param filesize ファイルサイズを受け取るポインタ
384-//! @param fileoffset データオフセットを受け取るポインタ
385-//! @param pwfex WAVEFORMATEX型を受け取る二重ポインタ
386-//! @return 成功:false 失敗:true
387-bool SoundControl::CheckSoundFile(char* filename, int *filesize, int *fileoffset, WAVEFORMATEX** pwfex)
388-{
389- HMMIO hMmio = NULL;
390- MMCKINFO ckInfo;
391- MMCKINFO riffckInfo;
392- PCMWAVEFORMAT pcmWaveFormat;
393- bool errorflag;
394-
395- hMmio = mmioOpen(filename, NULL, MMIO_ALLOCBUF | MMIO_READ);
396- if( hMmio == NULL ){
397- //ファイルがない
398- return true;
399- }
400-
401- //WAVEファイルか確認
402- errorflag = true;
403- if( mmioDescend( hMmio, &riffckInfo, NULL, 0 ) == MMSYSERR_NOERROR ){
404- if( (mmioFOURCC('R','I','F','F') == riffckInfo.ckid) && (mmioFOURCC('W','A','V','E') == riffckInfo.fccType) ){
405- errorflag = false;
406- }
407- }
408- if( errorflag == true ){
409- mmioClose(hMmio, MMIO_FHOPEN);
410- return true; //WAVEファイルでない
411- }
412-
413- //フォーマット情報取得
414- *pwfex = NULL;
415- ckInfo.ckid = mmioFOURCC('f','m','t',' ');
416- if( mmioDescend(hMmio, &ckInfo, &riffckInfo, MMIO_FINDCHUNK) == MMSYSERR_NOERROR ){
417- if( mmioRead(hMmio, (HPSTR) &pcmWaveFormat, sizeof(pcmWaveFormat)) == sizeof(pcmWaveFormat) ){
418- if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ){
419- if( (pcmWaveFormat.wf.nChannels == 1)||(pcmWaveFormat.wf.nChannels == 2) ){
420- *pwfex = new WAVEFORMATEX;
421- if( *pwfex != NULL ){
422- memcpy( *pwfex, &pcmWaveFormat, sizeof(pcmWaveFormat) );
423- //pwfex->cbSize = 0;
424- }
425- }
426- }
427- }
428- }
429- if( *pwfex == NULL ){
430- mmioClose(hMmio, MMIO_FHOPEN);
431- return true; //ファイルフォーマットが対応してない
432- }
433- if( mmioAscend(hMmio, &ckInfo, 0) != MMSYSERR_NOERROR ){
434- delete pwfex;
435- mmioClose(hMmio, MMIO_FHOPEN);
436- return true; //チャンク制御失敗
437- }
438-
439- //データ領域を調べる
440- ckInfo.ckid = mmioFOURCC('d','a','t','a');
441- if( mmioDescend(hMmio, &ckInfo, &riffckInfo, MMIO_FINDCHUNK) != MMSYSERR_NOERROR ){
442- mmioClose(hMmio, MMIO_FHOPEN);
443- return true; //ファイルフォーマットが対応してない
444- }
445-
446- mmioClose(hMmio, MMIO_FHOPEN);
447-
448- *filesize = ckInfo.cksize;
449- *fileoffset = ckInfo.dwDataOffset;
450- return false;
451-}
452-
453-//! @brief SetVolume()用 1/100 dB (デシベル) を計算
454-//! @param volume 音量(-50〜100)
455-//! @return 1/100 dB (デシベル).
456-//! @attention 引数に 156 以上が渡された場合は無音になります。
457-int SoundControl::GetDSVolume(int volume)
458-{
459- if( volume >= 156 ){ return DSBVOLUME_MIN; }
460- if( volume <= -50 ){ return DSBVOLUME_MIN; }
461- if( volume >= 100 ){ return DSBVOLUME_MAX; }
462-
463- float volume2 = 1.0f/150 * (volume + 50);
464- int retn = (int)((DSBVOLUME_MIN-DSBVOLUME_MAX) * (1.0f - volume2));
465- return retn;
466-}
467-
468-#else
469-
470-//! @brief コンストラクタ
471-SoundControl::SoundControl()
472-{
473- lib = NULL;
474-
475- //使用済みフラグを初期化
476- for(int i=0; i<MAX_LOADSOUND; i++){
477- useflag[i] = false;
478- }
479-}
480-
481-//! @brief ディストラクタ
482-SoundControl::~SoundControl()
483-{
484- DestroySound();
485-}
486-
487-//! @brief 初期化@n
488-//! (DLLのロード、初期化関数の実行)
489-//! @param WindowCtrl WindowControlクラスのポインタ
490-//! @return 成功:0 失敗:1
491-int SoundControl::InitSound(WindowControl *WindowCtrl)
492-{
493-#ifdef ENABLE_DEBUGLOG
494- //ログに出力
495- OutputLog.WriteLog(LOG_INIT, "サウンド", "ezds.dll");
496-#endif
497-
498- if( lib != NULL ){
499- return 1;
500- }
501-
502- //DLLを読み込む
503- lib = LoadLibrary("ezds.dll");
504- if (lib == NULL){
505- return 1;
506- }
507-
508- //関数を割り当て
509- DSver = GetProcAddress(lib, "DSver");
510- DSinit = (FARPROCH)GetProcAddress(lib, "DSinit");
511- DSend = GetProcAddress(lib, "DSend");
512- DSload = (FARPROCCI)GetProcAddress(lib, "DSload");
513- DSplay = (FARPROCIII)GetProcAddress(lib, "DSplay");
514- DSrelease = (FARPROCI)GetProcAddress(lib, "DSrelease");
515-
516- //DLL初期化を実行
517- if( DSinit == NULL ){
518- //DLLを開放
519- FreeLibrary(lib);
520- lib = NULL;
521- //return 1;
522- }
523- if( DSinit(WindowCtrl->GethWnd()) == 0 ){
524- //DLLを開放
525- FreeLibrary(lib);
526- lib = NULL;
527- //return 1;
528- }
529-
530-#ifdef ENABLE_DEBUGLOG
531- //ログに出力
532- OutputLog.WriteLog(LOG_COMPLETE, "", "");
533-#endif
534-
535- return 0;
536-}
537-
538-//! @brief 解放
539-//! @attention 本関数は自動的に呼び出されますが、明示的に呼び出すことも可能です。
540-void SoundControl::DestroySound()
541-{
542- if( lib == NULL ){ return; }
543-
544- //使用中のサウンドデータ数を数える
545- int total = 0;
546- for(int i=0; i<MAX_LOADSOUND; i++){
547- if( useflag[i] == true ){ total += 1; }
548- }
549-
550- //サウンドデータを開放し、DLLを終了
551- if( DSrelease != NULL ){ DSrelease(total); }
552- if( DSend != NULL ){ DSend(); }
553-
554- //DLLを開放
555- FreeLibrary(lib);
556- lib = NULL;
557-
558-#ifdef ENABLE_DEBUGLOG
559- //ログに出力
560- OutputLog.WriteLog(LOG_CLEANUP, "サウンド", "ezds.dll");
561-#endif
562-}
563-
564-//! @brief 再生音量を設定
565-//! @param volume 再生音量 (0.0=無音 1.0=100%)
566-void SoundControl::SetVolume(float volume)
567-{
568- mastervolume = volume;
569-}
570-
571-//! @brief カメラの座標と角度を設定
572-//! @param x カメラのX座標
573-//! @param y カメラのY座標
574-//! @param z カメラのZ座標
575-//! @param rx カメラのX軸角度 (予約)
576-//! @warning 毎フレーム呼び出して、最新のカメラ座標を設定(適用)してください。
577-void SoundControl::SetCamera(float x, float y, float z, float rx)
578-{
579- camera_x = x;
580- camera_y = y;
581- camera_z = z;
582- camera_rx = rx;
583-}
584-
585-//! @brief サウンドを読み込む
586-//! @param filename ファイル名
587-//! @return 成功:0以上の認識番号 失敗:-1
588-int SoundControl::LoadSound(char* filename)
589-{
590- if( lib == NULL ){ return -1; }
591-
592-#ifdef ENABLE_DEBUGLOG
593- //ログに出力
594- OutputLog.WriteLog(LOG_LOAD, "サウンド", filename);
595-#endif
596-
597- //使用していないデータ番号を探す
598- for(int i=0; i<MAX_LOADSOUND; i++){
599- if( useflag[i] == false ){
600-
601-#ifdef PATH_DELIMITER_SLASH
602- //パス区切り文字を変換
603- filename = ChangePathDelimiter(filename);
604-#endif
605-
606- //読み込みを試みる
607- if( DSload == NULL ){ return -1; }
608- if( DSload(filename, i) == 0 ){ return -1; }
609-
610- //小さい音量で一度再生しておく
611- if( DSplay == NULL ){ return -1; }
612- DSplay(i, -99, 0);
613-
614- //使用中を表すフラグをセット
615- useflag[i] = true;
616-
617-#ifdef ENABLE_DEBUGLOG
618- //ログに出力
619- OutputLog.WriteLog(LOG_COMPLETE, "", i);
620-#endif
621- return i;
622- }
623- }
624-
625- return -1;
626-}
627-
628-//! @brief サウンドを再生(非3D再生DLL呼び出し)
629-//! @param id 認識番号
630-//! @param volume 再生ボリューム
631-//! @param pan パン(左右バランス)
632-//! @return 成功:1 失敗:0
633-//! @note 用途:プレイヤー自身が発生する音・ゲーム空間全体で均一に鳴らす音・BGM
634-int SoundControl::PlaySound(int id, int volume, int pan)
635-{
636- if( lib == NULL ){ return 0; }
637- if( (id < 0)||(MAX_LOADSOUND -1 < id) ){ return 0; }
638- if( useflag[id] == false ){ return 0; }
639-
640- //サウンドを再生
641- if( DSplay == NULL ){ return 0; }
642- return DSplay(id, (int)(mastervolume * volume), pan);
643-}
644-
645-//! @brief サウンドを再生(3D再生)
646-//! @param id 認識番号
647-//! @param x 音源のX座標
648-//! @param y 音源のY座標
649-//! @param z 音源のZ座標
650-//! @param volume 再生ボリューム
651-//! @return 成功:1 失敗:0
652-//! @note 用途:絶対的な位置を持ち距離により減衰する、一般的な効果音。
653-int SoundControl::Play3DSound(int id, float x, float y, float z, int volume)
654-{
655- if( (id < 0)||(MAX_LOADSOUND -1 < id) ){ return 0; }
656- if( useflag[id] == false ){ return 0; }
657-
658- float dist;
659- int playvolume;
660- int pan = 0;
661-
662- //距離による再生音量決定
663- if( CheckSourceDist(x, y, z, false, &dist) == false ){
664- return 0;
665- }
666- playvolume = CalculationVolume(volume, dist, false);
667-
668- /*
669- //左右のパン(再生バランス)の決定
670- float vx = x - camera_x;
671- float vz = z - camera_z;
672- float rx = (atan2(vz, vx) - camera_rx) * -1;
673- for(; rx > (float)M_PI; rx -= (float)M_PI*2){}
674- for(; rx < (float)M_PI*-1; rx += (float)M_PI*2){}
675- pan = (int)((float)10 / M_PI * rx);
676- */
677-
678- //DLL呼び出し
679- return PlaySound(id, playvolume, pan);
680-}
681-
682-//! @brief サウンドを解放
683-//! @param id 認識番号
684-void SoundControl::CleanupSound(int id)
685-{
686- if( lib == NULL ){ return; }
687- if( (id < 0)||(MAX_LOADSOUND -1 < id) ){ return; }
688- if( useflag[id] == false ){ return; }
689-
690- //読み込みを意図的に失敗させ、強制的に初期化
691- if( DSload != NULL ){ DSload("", id); }
692-
693- //使用中フラグを解除
694- useflag[id] = false;
695-
696-#ifdef ENABLE_DEBUGLOG
697- //ログに出力
698- OutputLog.WriteLog(LOG_CLEANUP, "サウンド", id);
699-#endif
700-}
701-
702-//! @brief 音源との距離を調べる
703-//! @param x 音源のX座標
704-//! @param y 音源のY座標
705-//! @param z 音源のZ座標
706-//! @param snear 近距離音源
707-//! @param out_dist 距離
708-//! @return 有効(内):true 無効(外):false
709-bool SoundControl::CheckSourceDist(float x, float y, float z, bool snear, float *out_dist)
710-{
711- float dx, dy ,dz, dist;
712- int max_dist;
713-
714- if( snear == false ){
715- max_dist = MAX_SOUNDDIST;
716- }
717- else{
718- max_dist = 30;
719- }
720-
721- dx = camera_x - x;
722- dy = camera_y - y;
723- dz = camera_z - z;
724- dist = dx*dx + dy*dy + dz*dz;
725- if( dist > max_dist * max_dist ){
726- *out_dist = 0.0f;
727- return false;
728- }
729-
730- *out_dist = sqrt(dist);
731- return true;
732-}
733-
734-//! @brief 音量を計算
735-//! @param MaxVolume 音源の最大音量
736-//! @param dist 音源との距離
737-//! @param snear 近距離音源
738-int SoundControl::CalculationVolume(int MaxVolume, float dist, bool snear)
739-{
740- int max_dist;
741- if( snear == false ){
742- max_dist = MAX_SOUNDDIST;
743- }
744- else{
745- max_dist = 30;
746- }
747- return (int)( (float)MaxVolume/max_dist*dist*-1 + MaxVolume );
748-}
749-
750-#endif
\ No newline at end of file
--- trunk/sound-directsound.cpp (nonexistent)
+++ trunk/sound-directsound.cpp (revision 137)
@@ -0,0 +1,468 @@
1+//! @file sound-directsound.cpp
2+//! @brief SoundControlクラスの定義(DirectSound版)
3+
4+//--------------------------------------------------------------------------------
5+//
6+// OpenXOPS
7+// Copyright (c) 2014-2016, OpenXOPS Project / [-_-;](mikan) All rights reserved.
8+//
9+// Redistribution and use in source and binary forms, with or without
10+// modification, are permitted provided that the following conditions are met:
11+// * Redistributions of source code must retain the above copyright notice,
12+// this list of conditions and the following disclaimer.
13+// * Redistributions in binary form must reproduce the above copyright notice,
14+// this list of conditions and the following disclaimer in the documentation
15+// and/or other materials provided with the distribution.
16+// * Neither the name of the OpenXOPS Project nor the names of its contributors
17+// may be used to endorse or promote products derived from this software
18+// without specific prior written permission.
19+//
20+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+// DISCLAIMED. IN NO EVENT SHALL OpenXOPS Project BE LIABLE FOR ANY
24+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30+//--------------------------------------------------------------------------------
31+
32+#include "sound.h"
33+
34+#ifdef SOUND_DIRECTSOUND
35+
36+//! @brief コンストラクタ
37+SoundControl::SoundControl()
38+{
39+ pDSound = NULL;
40+}
41+
42+//! @brief ディストラクタ
43+SoundControl::~SoundControl()
44+{
45+ DestroySound();
46+}
47+
48+//! @brief 初期化
49+//! @param WindowCtrl WindowControlクラスのポインタ
50+//! @return 成功:0 失敗:1
51+int SoundControl::InitSound(WindowControl *WindowCtrl)
52+{
53+#ifdef ENABLE_DEBUGLOG
54+ //ログに出力
55+ OutputLog.WriteLog(LOG_INIT, "サウンド", "DirectSound");
56+#endif
57+
58+ //DirectSoundオブジェクトを生成
59+ if( FAILED( DirectSoundCreate8(NULL, &pDSound, NULL) ) ){
60+ return 1;
61+ }
62+
63+ //協調レベルの設定
64+ if( FAILED( pDSound->SetCooperativeLevel(WindowCtrl->GethWnd(), DSSCL_EXCLUSIVE) ) ){
65+ return 1;
66+ }
67+
68+ //プライマリ バッファを作成し、リスナーインターフェイスを取得する
69+ LPDIRECTSOUNDBUFFER pPrimary;
70+ DSBUFFERDESC dsbd;
71+ ZeroMemory(&dsbd, sizeof(DSBUFFERDESC));
72+ dsbd.dwSize = sizeof(DSBUFFERDESC);
73+ dsbd.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER;
74+ if( SUCCEEDED(pDSound->CreateSoundBuffer(&dsbd, &pPrimary, NULL)) ){
75+ pPrimary->QueryInterface(IID_IDirectSound3DListener8,(LPVOID *)&p3DListener);
76+ pPrimary->Release();
77+ }
78+
79+ //ドップラー効果を無効に
80+ p3DListener->SetDopplerFactor(DS3D_MINDOPPLERFACTOR, DS3D_IMMEDIATE);
81+
82+ //ロール・オフ(減衰度合い)設定
83+ p3DListener->SetRolloffFactor(0.05f, DS3D_IMMEDIATE);
84+
85+#ifdef ENABLE_DEBUGLOG
86+ //ログに出力
87+ OutputLog.WriteLog(LOG_COMPLETE, "", "");
88+#endif
89+
90+ return 0;
91+}
92+
93+//! @brief 解放
94+//! @attention 本関数は自動的に呼び出されますが、明示的に呼び出すことも可能です。
95+void SoundControl::DestroySound()
96+{
97+ if( pDSound == NULL ){ return; }
98+
99+ for(int i=0;i<MAX_LOADSOUND; i++){
100+ for(int j=0; j<MAX_SOUNDLISTS; j++){
101+ if( pDSBuffer[i][j] != NULL ){
102+ pDSBuffer[i][j]->Release();
103+ pDSBuffer[i][j] = NULL;
104+ }
105+ }
106+ }
107+ if( pDSound != NULL ){
108+ pDSound->Release();
109+ pDSound = NULL;
110+ }
111+
112+#ifdef ENABLE_DEBUGLOG
113+ //ログに出力
114+ OutputLog.WriteLog(LOG_CLEANUP, "サウンド", "DirectSound");
115+#endif
116+}
117+
118+//! @brief 再生音量を設定
119+//! @param volume 再生音量 (0.0=無音 1.0=100%)
120+void SoundControl::SetVolume(float volume)
121+{
122+ //
123+}
124+
125+//! @brief カメラの座標と角度を設定
126+//! @param x カメラのX座標
127+//! @param y カメラのY座標
128+//! @param z カメラのZ座標
129+//! @param rx カメラのX軸角度 (予約)
130+//! @warning 毎フレーム呼び出して、最新のカメラ座標を設定(適用)してください。
131+void SoundControl::SetCamera(float x, float y, float z, float rx)
132+{
133+ p3DListener->SetPosition(x, y, z, DS3D_IMMEDIATE);
134+ p3DListener->SetOrientation(cos(rx), 0.0f, sin(rx), 0.0f, 1.0f, 0.0f, DS3D_IMMEDIATE);
135+}
136+
137+//! @brief サウンドを読み込む
138+//! @param filename ファイル名
139+//! @return 成功:0以上の認識番号 失敗:-1
140+//! @attention 2チャンネル(ステレオ)データが指定された場合、右側のデータだけ取得され、左側のデータは無視されます。
141+int SoundControl::LoadSound(char* filename)
142+{
143+ if( pDSound == NULL ){ return -1; }
144+
145+#ifdef ENABLE_DEBUGLOG
146+ //ログに出力
147+ OutputLog.WriteLog(LOG_LOAD, "サウンド", filename);
148+#endif
149+
150+ //開いている番号を探す
151+ int id=0;
152+ for(id=0; id<MAX_LOADSOUND; id++){
153+ if( pDSBuffer[id][0] == NULL ){ break; }
154+ }
155+ if( id == MAX_LOADSOUND ){ return -1; }
156+
157+ WAVEFORMATEX* pwfex;
158+ int WavSize = 0;
159+ int Wavoffset = 0;
160+ bool d2channels = false;
161+
162+ //Waveファイルの情報を取得
163+ if( CheckSoundFile(filename, &WavSize, &Wavoffset, &pwfex) == true ){
164+ return -1;
165+ }
166+ pwfex->cbSize = 0;
167+
168+ //もしステレオデータなら
169+ if( pwfex->nChannels == 2 ){
170+ d2channels = true; //フラグを設定
171+ WavSize /= 2; //サイズを半分に
172+
173+ //モノラルとして強制的に再計算
174+ pwfex->nChannels = 1;
175+ pwfex->nAvgBytesPerSec /= 2;
176+ pwfex->nBlockAlign /= 2;
177+ }
178+
179+ // DirectSoundセカンダリーバッファー作成
180+ DSBUFFERDESC dsbd;
181+ ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
182+ dsbd.dwSize = sizeof(DSBUFFERDESC);
183+ dsbd.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME;
184+ dsbd.dwBufferBytes = WavSize;
185+ dsbd.guid3DAlgorithm = DS3DALG_NO_VIRTUALIZATION;
186+ dsbd.lpwfxFormat = pwfex;
187+ if( FAILED( pDSound->CreateSoundBuffer(&dsbd, &pDSBuffer[id][0], NULL) ) ){
188+ return -1; //セカンダリバッファー作成失敗
189+ }
190+
191+ //ロックする
192+ VOID* pBuffer = NULL;
193+ DWORD dwBufferSize = 0;
194+ if( FAILED(pDSBuffer[id][0]->Lock(0, WavSize, &pBuffer, &dwBufferSize, NULL, NULL, 0) ) ){
195+ return -1; //バッファのロック失敗
196+ }
197+
198+ //一時領域を確保
199+ BYTE* pWavData;
200+ int dwSize = dwBufferSize;
201+ if( dwSize > WavSize ){ dwSize = WavSize; }
202+ if( d2channels == true ){
203+ dwSize = dwSize * 2;
204+ }
205+ pWavData = new BYTE[dwSize];
206+ if( pWavData == NULL ){
207+ //WAVEファイルを読み込むメモリーが確保できない
208+ return -1;
209+ }
210+
211+#ifdef PATH_DELIMITER_SLASH
212+ //パス区切り文字を変換
213+ filename = ChangePathDelimiter(filename);
214+#endif
215+
216+ //波形データを取り込む
217+ FILE* fp;
218+ fp = fopen(filename,"rb");
219+ fseek(fp, Wavoffset, SEEK_SET);
220+ fread(pWavData, 1, dwSize, fp);
221+ fclose(fp);
222+
223+ //一時領域からセカンダリバッファーへコピー
224+ if( d2channels == false ){
225+ //モノラルデータなら1バイトづつコピーする
226+ for(int i=0; i<dwSize; i++){
227+ *((BYTE*)pBuffer+i) = *((BYTE*) pWavData+i);
228+ }
229+ }
230+ else{
231+ //サンプリングバイト数を取得
232+ int samplingbytes = pwfex->wBitsPerSample/2;
233+
234+ //ステレオデータなら、右側のデータだけ格納
235+ int byte = 0;
236+ for(int i=0; i<dwSize; i++){
237+ *((BYTE*)pBuffer+byte) = *((BYTE*) pWavData+i);
238+ byte += 1;
239+ if( i%samplingbytes == samplingbytes-1 ){ i += samplingbytes; } //左側のデータはスキップ
240+ }
241+ }
242+
243+ //ロック解除
244+ pDSBuffer[id][0]->Unlock(pBuffer, dwBufferSize, NULL, 0);
245+
246+ //一時領域を解放
247+ delete pWavData;
248+
249+ //フォーマット情報解放
250+ delete pwfex;
251+
252+ //セカンダリバッファーのコピーを作成
253+ for(int i=1; i<MAX_SOUNDLISTS; i++){
254+ if( pDSound->DuplicateSoundBuffer(pDSBuffer[id][0], &(pDSBuffer[id][i])) != DS_OK ){
255+ CleanupSound(id);
256+ return -1;
257+ }
258+ }
259+
260+ //音量最小で一度再生しておく
261+ pDSBuffer[id][0]->SetVolume(DSBVOLUME_MIN);
262+ pDSBuffer[id][0]->Play(NULL, 0, NULL);
263+
264+#ifdef ENABLE_DEBUGLOG
265+ //ログに出力
266+ OutputLog.WriteLog(LOG_COMPLETE, "", id);
267+#endif
268+
269+ return id;
270+}
271+
272+//! @brief サウンドを再生(非3D再生)
273+//! @param id 認識番号
274+//! @param volume 再生ボリューム
275+//! @param pan <無効>
276+//! @return 成功:1 失敗:0
277+//! @note 用途:プレイヤー自身が発生する音・ゲーム空間全体で均一に鳴らす音・BGM
278+int SoundControl::PlaySound(int id, int volume, int pan)
279+{
280+ if( pDSound == NULL ){ return 0; }
281+ if( (id < 0)||(MAX_LOADSOUND -1 < id) ){ return 0; }
282+ if( pDSBuffer[id][0] == NULL ){ return 0; }
283+
284+ DWORD status = 0;
285+
286+ for(int i=0; i<MAX_SOUNDLISTS; i++){
287+ //再生状況を取得
288+ pDSBuffer[id][i]->GetStatus(&status);
289+
290+ //サウンドが停止中ならば
291+ if( (status & DSBSTATUS_PLAYING) == 0x00 ){
292+ LPDIRECTSOUND3DBUFFER pDS3DBuffer;
293+ DWORD status = 0;
294+ if( FAILED(pDSBuffer[id][i]->QueryInterface(IID_IDirectSound3DBuffer8,(VOID**)&pDS3DBuffer)) ){
295+ //IDirectSound3DBuffer8を取得できない
296+ return 0;
297+ }
298+
299+ //3D再生を無効
300+ pDS3DBuffer->SetMode(DS3DMODE_DISABLE, DS3D_IMMEDIATE);
301+
302+ //ボリュームを設定し再生
303+ pDSBuffer[id][i]->SetVolume( GetDSVolume(volume) );
304+ pDSBuffer[id][i]->Play(NULL, 0, NULL);
305+ return 1;
306+ }
307+ }
308+
309+ return 0;
310+}
311+
312+//! @brief サウンドを再生(3D再生)
313+//! @param id 認識番号
314+//! @param x 音源のX座標
315+//! @param y 音源のY座標
316+//! @param z 音源のZ座標
317+//! @param volume 再生ボリューム
318+//! @return 成功:1 失敗:0
319+//! @note 用途:絶対的な位置を持ち距離により減衰する、一般的な効果音。
320+int SoundControl::Play3DSound(int id, float x, float y, float z, int volume)
321+{
322+ if( pDSound == NULL ){ return 0; }
323+ if( (id < 0)||(MAX_LOADSOUND -1 < id) ){ return 0; }
324+ if( pDSBuffer[id][0] == NULL ){ return 0; }
325+
326+ DWORD status = 0;
327+
328+ for(int i=0; i<MAX_SOUNDLISTS; i++){
329+ //再生状況を取得
330+ pDSBuffer[id][i]->GetStatus(&status);
331+
332+ //サウンドが停止中ならば
333+ if( (status & DSBSTATUS_PLAYING) == 0x00 ){
334+
335+ LPDIRECTSOUND3DBUFFER pDS3DBuffer;
336+ if( FAILED(pDSBuffer[id][i]->QueryInterface(IID_IDirectSound3DBuffer8,(VOID**)&pDS3DBuffer)) ){
337+ //IDirectSound3DBuffer8を取得できない
338+ return 0;
339+ }
340+
341+ //最小距離と最大距離の設定
342+ pDS3DBuffer->SetMinDistance(1, DS3D_IMMEDIATE);
343+ pDS3DBuffer->SetMaxDistance(MAX_SOUNDDIST, DS3D_IMMEDIATE);
344+
345+ //音源の座標を設定
346+ pDS3DBuffer->SetPosition(x, y, z, DS3D_IMMEDIATE);
347+
348+ //3D再生を有効
349+ pDS3DBuffer->SetMode(DS3DMODE_NORMAL, DS3D_IMMEDIATE);
350+
351+ //ボリュームを設定し再生
352+ pDSBuffer[id][i]->SetVolume( GetDSVolume(volume) );
353+ pDSBuffer[id][i]->Play(NULL, 0, NULL);
354+ return 1;
355+ }
356+ }
357+
358+ return 0;
359+}
360+
361+//! @brief サウンドを解放
362+//! @param id 認識番号
363+void SoundControl::CleanupSound(int id)
364+{
365+ if( pDSound == NULL ){ return; }
366+ if( (id < 0)||(MAX_LOADSOUND -1 < id) ){ return; }
367+ if( pDSBuffer[id][0] == NULL ){ return; }
368+
369+ //対象の全セカンダリバッファーを解放
370+ for(int i=0; i<MAX_SOUNDLISTS; i++){
371+ if( pDSBuffer[id][i] != NULL ){ pDSBuffer[id][i]->Release(); }
372+ pDSBuffer[id][i] = NULL;
373+ }
374+
375+#ifdef ENABLE_DEBUGLOG
376+ //ログに出力
377+ OutputLog.WriteLog(LOG_CLEANUP, "サウンド", id);
378+#endif
379+}
380+
381+//! @brief Waveファイルの情報を調べる
382+//! @param filename ファイル名
383+//! @param filesize ファイルサイズを受け取るポインタ
384+//! @param fileoffset データオフセットを受け取るポインタ
385+//! @param pwfex WAVEFORMATEX型を受け取る二重ポインタ
386+//! @return 成功:false 失敗:true
387+bool SoundControl::CheckSoundFile(char* filename, int *filesize, int *fileoffset, WAVEFORMATEX** pwfex)
388+{
389+ HMMIO hMmio = NULL;
390+ MMCKINFO ckInfo;
391+ MMCKINFO riffckInfo;
392+ PCMWAVEFORMAT pcmWaveFormat;
393+ bool errorflag;
394+
395+ hMmio = mmioOpen(filename, NULL, MMIO_ALLOCBUF | MMIO_READ);
396+ if( hMmio == NULL ){
397+ //ファイルがない
398+ return true;
399+ }
400+
401+ //WAVEファイルか確認
402+ errorflag = true;
403+ if( mmioDescend( hMmio, &riffckInfo, NULL, 0 ) == MMSYSERR_NOERROR ){
404+ if( (mmioFOURCC('R','I','F','F') == riffckInfo.ckid) && (mmioFOURCC('W','A','V','E') == riffckInfo.fccType) ){
405+ errorflag = false;
406+ }
407+ }
408+ if( errorflag == true ){
409+ mmioClose(hMmio, MMIO_FHOPEN);
410+ return true; //WAVEファイルでない
411+ }
412+
413+ //フォーマット情報取得
414+ *pwfex = NULL;
415+ ckInfo.ckid = mmioFOURCC('f','m','t',' ');
416+ if( mmioDescend(hMmio, &ckInfo, &riffckInfo, MMIO_FINDCHUNK) == MMSYSERR_NOERROR ){
417+ if( mmioRead(hMmio, (HPSTR) &pcmWaveFormat, sizeof(pcmWaveFormat)) == sizeof(pcmWaveFormat) ){
418+ if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ){
419+ if( (pcmWaveFormat.wf.nChannels == 1)||(pcmWaveFormat.wf.nChannels == 2) ){
420+ *pwfex = new WAVEFORMATEX;
421+ if( *pwfex != NULL ){
422+ memcpy( *pwfex, &pcmWaveFormat, sizeof(pcmWaveFormat) );
423+ //pwfex->cbSize = 0;
424+ }
425+ }
426+ }
427+ }
428+ }
429+ if( *pwfex == NULL ){
430+ mmioClose(hMmio, MMIO_FHOPEN);
431+ return true; //ファイルフォーマットが対応してない
432+ }
433+ if( mmioAscend(hMmio, &ckInfo, 0) != MMSYSERR_NOERROR ){
434+ delete pwfex;
435+ mmioClose(hMmio, MMIO_FHOPEN);
436+ return true; //チャンク制御失敗
437+ }
438+
439+ //データ領域を調べる
440+ ckInfo.ckid = mmioFOURCC('d','a','t','a');
441+ if( mmioDescend(hMmio, &ckInfo, &riffckInfo, MMIO_FINDCHUNK) != MMSYSERR_NOERROR ){
442+ mmioClose(hMmio, MMIO_FHOPEN);
443+ return true; //ファイルフォーマットが対応してない
444+ }
445+
446+ mmioClose(hMmio, MMIO_FHOPEN);
447+
448+ *filesize = ckInfo.cksize;
449+ *fileoffset = ckInfo.dwDataOffset;
450+ return false;
451+}
452+
453+//! @brief SetVolume()用 1/100 dB (デシベル) を計算
454+//! @param volume 音量(-50〜100)
455+//! @return 1/100 dB (デシベル).
456+//! @attention 引数に 156 以上が渡された場合は無音になります。
457+int SoundControl::GetDSVolume(int volume)
458+{
459+ if( volume >= 156 ){ return DSBVOLUME_MIN; }
460+ if( volume <= -50 ){ return DSBVOLUME_MIN; }
461+ if( volume >= 100 ){ return DSBVOLUME_MAX; }
462+
463+ float volume2 = 1.0f/150 * (volume + 50);
464+ int retn = (int)((DSBVOLUME_MIN-DSBVOLUME_MAX) * (1.0f - volume2));
465+ return retn;
466+}
467+
468+#endif //SOUND_DIRECTSOUND
\ No newline at end of file
--- trunk/sound-ezds.cpp (nonexistent)
+++ trunk/sound-ezds.cpp (revision 137)
@@ -0,0 +1,316 @@
1+//! @file sound-directsound.cpp
2+//! @brief SoundControlクラスの定義(ezds.dll版)
3+
4+//--------------------------------------------------------------------------------
5+//
6+// OpenXOPS
7+// Copyright (c) 2014-2016, OpenXOPS Project / [-_-;](mikan) All rights reserved.
8+//
9+// Redistribution and use in source and binary forms, with or without
10+// modification, are permitted provided that the following conditions are met:
11+// * Redistributions of source code must retain the above copyright notice,
12+// this list of conditions and the following disclaimer.
13+// * Redistributions in binary form must reproduce the above copyright notice,
14+// this list of conditions and the following disclaimer in the documentation
15+// and/or other materials provided with the distribution.
16+// * Neither the name of the OpenXOPS Project nor the names of its contributors
17+// may be used to endorse or promote products derived from this software
18+// without specific prior written permission.
19+//
20+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+// DISCLAIMED. IN NO EVENT SHALL OpenXOPS Project BE LIABLE FOR ANY
24+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30+//--------------------------------------------------------------------------------
31+
32+#include "sound.h"
33+
34+#ifndef SOUND_DIRECTSOUND
35+
36+//! @brief コンストラクタ
37+SoundControl::SoundControl()
38+{
39+ lib = NULL;
40+
41+ //使用済みフラグを初期化
42+ for(int i=0; i<MAX_LOADSOUND; i++){
43+ useflag[i] = false;
44+ }
45+}
46+
47+//! @brief ディストラクタ
48+SoundControl::~SoundControl()
49+{
50+ DestroySound();
51+}
52+
53+//! @brief 初期化@n
54+//! (DLLのロード、初期化関数の実行)
55+//! @param WindowCtrl WindowControlクラスのポインタ
56+//! @return 成功:0 失敗:1
57+int SoundControl::InitSound(WindowControl *WindowCtrl)
58+{
59+#ifdef ENABLE_DEBUGLOG
60+ //ログに出力
61+ OutputLog.WriteLog(LOG_INIT, "サウンド", "ezds.dll");
62+#endif
63+
64+ if( lib != NULL ){
65+ return 1;
66+ }
67+
68+ //DLLを読み込む
69+ lib = LoadLibrary("ezds.dll");
70+ if (lib == NULL){
71+ return 1;
72+ }
73+
74+ //関数を割り当て
75+ DSver = GetProcAddress(lib, "DSver");
76+ DSinit = (FARPROCH)GetProcAddress(lib, "DSinit");
77+ DSend = GetProcAddress(lib, "DSend");
78+ DSload = (FARPROCCI)GetProcAddress(lib, "DSload");
79+ DSplay = (FARPROCIII)GetProcAddress(lib, "DSplay");
80+ DSrelease = (FARPROCI)GetProcAddress(lib, "DSrelease");
81+
82+ //DLL初期化を実行
83+ if( DSinit == NULL ){
84+ //DLLを開放
85+ FreeLibrary(lib);
86+ lib = NULL;
87+ //return 1;
88+ }
89+ if( DSinit(WindowCtrl->GethWnd()) == 0 ){
90+ //DLLを開放
91+ FreeLibrary(lib);
92+ lib = NULL;
93+ //return 1;
94+ }
95+
96+#ifdef ENABLE_DEBUGLOG
97+ //ログに出力
98+ OutputLog.WriteLog(LOG_COMPLETE, "", "");
99+#endif
100+
101+ return 0;
102+}
103+
104+//! @brief 解放
105+//! @attention 本関数は自動的に呼び出されますが、明示的に呼び出すことも可能です。
106+void SoundControl::DestroySound()
107+{
108+ if( lib == NULL ){ return; }
109+
110+ //使用中のサウンドデータ数を数える
111+ int total = 0;
112+ for(int i=0; i<MAX_LOADSOUND; i++){
113+ if( useflag[i] == true ){ total += 1; }
114+ }
115+
116+ //サウンドデータを開放し、DLLを終了
117+ if( DSrelease != NULL ){ DSrelease(total); }
118+ if( DSend != NULL ){ DSend(); }
119+
120+ //DLLを開放
121+ FreeLibrary(lib);
122+ lib = NULL;
123+
124+#ifdef ENABLE_DEBUGLOG
125+ //ログに出力
126+ OutputLog.WriteLog(LOG_CLEANUP, "サウンド", "ezds.dll");
127+#endif
128+}
129+
130+//! @brief 再生音量を設定
131+//! @param volume 再生音量 (0.0=無音 1.0=100%)
132+void SoundControl::SetVolume(float volume)
133+{
134+ mastervolume = volume;
135+}
136+
137+//! @brief カメラの座標と角度を設定
138+//! @param x カメラのX座標
139+//! @param y カメラのY座標
140+//! @param z カメラのZ座標
141+//! @param rx カメラのX軸角度 (予約)
142+//! @warning 毎フレーム呼び出して、最新のカメラ座標を設定(適用)してください。
143+void SoundControl::SetCamera(float x, float y, float z, float rx)
144+{
145+ camera_x = x;
146+ camera_y = y;
147+ camera_z = z;
148+ camera_rx = rx;
149+}
150+
151+//! @brief サウンドを読み込む
152+//! @param filename ファイル名
153+//! @return 成功:0以上の認識番号 失敗:-1
154+int SoundControl::LoadSound(char* filename)
155+{
156+ if( lib == NULL ){ return -1; }
157+
158+#ifdef ENABLE_DEBUGLOG
159+ //ログに出力
160+ OutputLog.WriteLog(LOG_LOAD, "サウンド", filename);
161+#endif
162+
163+ //使用していないデータ番号を探す
164+ for(int i=0; i<MAX_LOADSOUND; i++){
165+ if( useflag[i] == false ){
166+
167+#ifdef PATH_DELIMITER_SLASH
168+ //パス区切り文字を変換
169+ filename = ChangePathDelimiter(filename);
170+#endif
171+
172+ //読み込みを試みる
173+ if( DSload == NULL ){ return -1; }
174+ if( DSload(filename, i) == 0 ){ return -1; }
175+
176+ //小さい音量で一度再生しておく
177+ if( DSplay == NULL ){ return -1; }
178+ DSplay(i, -99, 0);
179+
180+ //使用中を表すフラグをセット
181+ useflag[i] = true;
182+
183+#ifdef ENABLE_DEBUGLOG
184+ //ログに出力
185+ OutputLog.WriteLog(LOG_COMPLETE, "", i);
186+#endif
187+ return i;
188+ }
189+ }
190+
191+ return -1;
192+}
193+
194+//! @brief サウンドを再生(非3D再生DLL呼び出し)
195+//! @param id 認識番号
196+//! @param volume 再生ボリューム
197+//! @param pan パン(左右バランス)
198+//! @return 成功:1 失敗:0
199+//! @note 用途:プレイヤー自身が発生する音・ゲーム空間全体で均一に鳴らす音・BGM
200+int SoundControl::PlaySound(int id, int volume, int pan)
201+{
202+ if( lib == NULL ){ return 0; }
203+ if( (id < 0)||(MAX_LOADSOUND -1 < id) ){ return 0; }
204+ if( useflag[id] == false ){ return 0; }
205+
206+ //サウンドを再生
207+ if( DSplay == NULL ){ return 0; }
208+ return DSplay(id, (int)(mastervolume * volume), pan);
209+}
210+
211+//! @brief サウンドを再生(3D再生)
212+//! @param id 認識番号
213+//! @param x 音源のX座標
214+//! @param y 音源のY座標
215+//! @param z 音源のZ座標
216+//! @param volume 再生ボリューム
217+//! @return 成功:1 失敗:0
218+//! @note 用途:絶対的な位置を持ち距離により減衰する、一般的な効果音。
219+int SoundControl::Play3DSound(int id, float x, float y, float z, int volume)
220+{
221+ if( (id < 0)||(MAX_LOADSOUND -1 < id) ){ return 0; }
222+ if( useflag[id] == false ){ return 0; }
223+
224+ float dist;
225+ int playvolume;
226+ int pan = 0;
227+
228+ //距離による再生音量決定
229+ if( CheckSourceDist(x, y, z, false, &dist) == false ){
230+ return 0;
231+ }
232+ playvolume = CalculationVolume(volume, dist, false);
233+
234+ /*
235+ //左右のパン(再生バランス)の決定
236+ float vx = x - camera_x;
237+ float vz = z - camera_z;
238+ float rx = (atan2(vz, vx) - camera_rx) * -1;
239+ for(; rx > (float)M_PI; rx -= (float)M_PI*2){}
240+ for(; rx < (float)M_PI*-1; rx += (float)M_PI*2){}
241+ pan = (int)((float)10 / M_PI * rx);
242+ */
243+
244+ //DLL呼び出し
245+ return PlaySound(id, playvolume, pan);
246+}
247+
248+//! @brief サウンドを解放
249+//! @param id 認識番号
250+void SoundControl::CleanupSound(int id)
251+{
252+ if( lib == NULL ){ return; }
253+ if( (id < 0)||(MAX_LOADSOUND -1 < id) ){ return; }
254+ if( useflag[id] == false ){ return; }
255+
256+ //読み込みを意図的に失敗させ、強制的に初期化
257+ if( DSload != NULL ){ DSload("", id); }
258+
259+ //使用中フラグを解除
260+ useflag[id] = false;
261+
262+#ifdef ENABLE_DEBUGLOG
263+ //ログに出力
264+ OutputLog.WriteLog(LOG_CLEANUP, "サウンド", id);
265+#endif
266+}
267+
268+//! @brief 音源との距離を調べる
269+//! @param x 音源のX座標
270+//! @param y 音源のY座標
271+//! @param z 音源のZ座標
272+//! @param snear 近距離音源
273+//! @param out_dist 距離
274+//! @return 有効(内):true 無効(外):false
275+bool SoundControl::CheckSourceDist(float x, float y, float z, bool snear, float *out_dist)
276+{
277+ float dx, dy ,dz, dist;
278+ int max_dist;
279+
280+ if( snear == false ){
281+ max_dist = MAX_SOUNDDIST;
282+ }
283+ else{
284+ max_dist = 30;
285+ }
286+
287+ dx = camera_x - x;
288+ dy = camera_y - y;
289+ dz = camera_z - z;
290+ dist = dx*dx + dy*dy + dz*dz;
291+ if( dist > max_dist * max_dist ){
292+ *out_dist = 0.0f;
293+ return false;
294+ }
295+
296+ *out_dist = sqrt(dist);
297+ return true;
298+}
299+
300+//! @brief 音量を計算
301+//! @param MaxVolume 音源の最大音量
302+//! @param dist 音源との距離
303+//! @param snear 近距離音源
304+int SoundControl::CalculationVolume(int MaxVolume, float dist, bool snear)
305+{
306+ int max_dist;
307+ if( snear == false ){
308+ max_dist = MAX_SOUNDDIST;
309+ }
310+ else{
311+ max_dist = 30;
312+ }
313+ return (int)( (float)MaxVolume/max_dist*dist*-1 + MaxVolume );
314+}
315+
316+#endif //SOUND_DIRECTSOUND
\ No newline at end of file