いぬおさんのおもしろ数学実験室

おいしい紅茶でも飲みながら数学、物理、工学、プログラミング、そして読書を楽しみましょう

Unityでサウンドファイル(mp3)の音量をファイル毎に変える方法

ゲームのBGMや効果音を自分で作れる人は限られています。ぼくにそういう能力はないので、ゲームを作るときは何とか調達しなければなりません。ありがたいことに色々なサイトからmp3などのサウンドファイルをダウンロードでき、ぼくはこれを使わせてもらっています(その際のルールはありますが)。それはよいのですが、ゲーム内で鳴らすとき、音源(ファイル)によって音量が異なることが少なくありません。UnityではAudioSourceにサウンドファイル(音源。AudioClip)をセットして演奏できますが、AudioSource毎に音量を変えられます。だから、AudioSourceをいくつも用意しておき、それぞれで適切な音量を設定しておけばそれでOKです。しかしAudioSourceをひとつだけ用意し、AudioClipを交換しながら鳴らしたいときだってあるでしょう。この場合、交換のたびに音量を設定し直すことになります。これでも大丈夫です。しかし各サウンドファイルを読み込んだ時点でそれぞれの音量を適切にセットすれば、以降でファイル毎の音量を気にする必要はありません。つまり、「あ、このサウンドファイルは小さい音で録音されている!」というときはそのファイルだけ、オーディオクリップを作成するときにサウンドデータを大きめにすればよいのです。
ここではサウンドファイル(mp3)をResourceフォルダに入れておき、それぞれの音量をゲーム開始時に好きな値にセットする方法を紹介します。近いことはすでに書いています。

www.omoshiro-suugaku.com

が、あらためてまとめておきます。実験の結果、以下の関数を実行すれば、Resourceフォルダ取り込んでおいたfname(mp3ファイル)の音量をrate倍にセットできます。以降、acをAudioClipとして使えばOKです。

 

void soundFileVolSet(string fname,
                            float rate, out AudioClip ac) {
    ac = (AudioClip)Resources.Load<AudioClip>(fname);
    int dataSize = ac.samples * ac.channels;
    var samples = new float[dataSize];
    var buf = new float[dataSize];
    ac.GetData(samples, 0);
    for (int i = 0; i < dataSize; i++) {
        buf[i] = samples[i] * rate;
    } 
    ac.SetData(buf, 0);
}

 

ac.channelsは音源がモノラルかステレオかに応じて1,2の値になります。ac.samplesはサンプリング時刻の数、といったところでしょう。モノラルなら1データ、ステレオなら2データをサンプリング時刻にサンプリングするわけです。そうするとdataSizeがサンプリングした総データ数ということになります。コードの他の部分は特に問題ないでしょう。
ぼくはこうして音量の小さいAudioClipはデータの大きさを1.2倍とかにして使っています。ここまでのところ、無事に目的を果たせています。

 

この春で職場が変わります。学校は春休みで、学期末の仕事が終わってから数日間、ボンヤリして休んでいました。この先しばらくは開発作業に専念できます。集中しなければ!