【DXライブラリ】音を鳴らす

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など)を使って確認。

コメント

タイトルとURLをコピーしました