DXライブラリとC言語で3Dゲーム制作。今回はBGMや効果音を鳴らす方法について。BGMのループ再生にも対応。
BGMや効果音を鳴らしたい
3Dモデルや画像の表示も大事だがBGMや効果音を鳴らすこともゲームを支える大事な要素。雰囲気づくりのためには欠かせない。アセットフリップを乱用した粗悪なゲームにはないことも多いが
BGMや効果音などの音声ファイルを読み込みには LoadSoundMem() を使用する。読み込める音声ファイルの形式はwav, mp3, ogg, opusの4つ。
| 宣言 | int LoadSoundMem(char *FileName); | |
| 概要 | 音声ファイルをメモリに読み込む | |
| 引数 | char *FileName | 読み込みたい音声ファイルのファイル名のポインタ |
| 戻り値 | -1以外 | サウンドハンドル |
| -1 | エラー発生 | |
読み込んだ音声ファイルを再生するには PlaySoundMem() を使用する。
| 宣言 | int PlaySoundMem(int SoundHandle ,int PlayType ,int TopPositionFlag); | |
| 概要 | メモリに読み込んだ音声データを再生する | |
| 引数 | int SoundHandle | 再生したいサウンドハンドル |
| int PlayTime | 再生形式 | |
| int TopPositionFlag | 再生位置を音データの先頭に移動するかどうか TRUE:移動する FALSE:移動しない |
|
| 戻り値 | 0 | 成功 |
| -1 | エラー発生 | |
| 再生形式 | |
| DX_PLAYTYPE_NORMAL | ノーマル再生 |
| DX_PLAYTYPE_BACK | バックグラウンド再生 |
| DX_PLAYTYPE_LOOP | ループ再生 |
読み込んだ音声ファイルを削除したい場合は DeleteSoundMem() を使用する。
| 宣言 | int DeleteSoundMem(int SoundHandle); | |
| 概要 | メモリに読み込んだ音声ファイルを削除する | |
| 引数 | int SoundHandle | 削除するサウンドハンドル |
| 戻り値 | 0 | 成功 |
| -1 | エラー発生 | |
サンプルコード
それでは実装。とりあえず1つの効果音を鳴らすコード。
まず音声ファイルを扱う専用の SoundMng.cpp/h を作成して以下のようにする。
SoundMng.h
#ifndef DEF_SOUNDMNG_H #define DEF_SOUNDMNG_H void SoundMng_Initialize(); void SoundMng_Update(); void SoundMng_Play(); void SoundMng_Finalize(); #endif
SoundMng.cpp
#include "DxLib.h"
#include "SoundMng.h"
#include "Define.h"
const static int SOUND_NUM = 4; //音声ハンドルの最大数
static int SrcSoundHandle; //音声ファイルハンドル
static int SoundHandle[SOUND_NUM]; //実際に鳴らす音声ハンドル
//初期化
void SoundMng_Initialize() {
//音声ファイルの読み込み
SrcSoundHandle = LoadSoundMem("読み込みたい音声ファイルのパス");
for (int i = 0; i < SOUND_NUM; i++) {
SoundHandle[i] = DuplicateSoundMem(SrcSoundHandle);
}
}
//更新
void SoundMng_Update() {
}
//再生
void SoundMng_Play() {
//音声を再生する。すでに再生中だった場合はしない
for (int i = 0; i < SOUND_NUM; i++) {
if (CheckSoundMem(SoundHandle[i]) == 0) {
PlaySoundMem(SoundHandle[i], DX_PLAYTYPE_BACK);
break;
}
}
}
//終了処理
void SoundMng_Finalize() {
//音声ハンドルの削除
for (int i = 0; i < SOUND_NUM; i++) {
DeleteSoundMem(SoundHandle[i]);
}
DeleteSoundMem(SrcSoundHandle);
}
音を鳴らすとき1つのサウンドハンドルを連続で鳴らすと音がぶつ切りに鳴るのでサウンドハンドルは複数用意している。サウンドハンドルを複製するときは DuplicateSoundMem() を使って複製する。
| 宣言 | int DuplicateSoundMem(int SrcSoundHandle) | |
| 概要 | サウンドハンドルを複製する | |
| 引数 | int SrcSoundHandle | 複製したいサウンドハンドル |
| 戻り値 | -1以外 | サウンドハンドル |
| -1 | エラー発生 | |
次に CheckSoundMem() で再生中かどうかを確認し、再生中であれば次のサウンドハンドルを鳴らすようにしている。音を鳴らすときは再生形式にDX_PLAYTYPE_BACKと指定すること(NORMALだと他の処理が行われない)。
| 宣言 | int CheckSoundMem(int SoundHandle); | |
| 概要 | 指定のサウンドハンドルが再生中かどうか調べる | |
| 引数 | int SoundHandle | 再生中か調べたいサウンドハンドル |
| 戻り値 | 1 | 再生中 |
| 0 | 再生されていない | |
| -1 | エラー発生 | |
最後に DeleteSoundMem() でサウンドハンドルを削除する。
次にGame.cppに以下のコードを追加する。
//以下のヘッダーファイルをインクルードに追加
#include "SoundMng.h"
//略
//初期化関数に以下のコードを追加
void Game_Initialize() {
//略
//音声の情報初期化
SoundMng_Initialize();
}
//略
//終了処理関数に以下のコードを追加
void Game_Finalize() {
//音声の終了処理
SoundMng_Finalize();
}
あとは音を鳴らしたい部分に SoundMng_Play() を書く。SoundMng.h のインクルードを忘れないように。
BGMをループ再生したい場合
BGMをループ再生したい場合は読み込みたいBGMの音声ファイルと同じ場所に「(音声ファイルの名前)_loop.txt」を作成し、そのtxtファイル内にループ開始位置となるLOOPSTARTとループ範囲の長さとなるLOOPLENGTHを半角文字で書きこむ。あとは音声ファイルを読み込むときに勝手にtxtファイルが読み込まれる。
開始位置とループ範囲で指定する値は秒数*サンプル数(44.1kHzなら44100)となっている。
例:44.1kHzのBGMのループ開始位置を10秒後、ループ範囲を60秒にしたい場合は以下のようにする。
LOOPSTART=441000
LOOPLENGTH=2646000
あとはループ再生したいサウンドハンドルをPlaySoundMem()で再生する際に再生形式をDX_PLAYTYPE_LOOPと指定する。
BGMのサンプル数わからん!という人は無料の音声編集ソフト(SoundEngineなど)を使って確認。

コメント