#はじめに
この記事は筑波大学情報メディア創成学類「プログラミング実習II」履修者向けの記事で、その最終課題であるglutを使ったゲーム開発の際に、ゲームにBGM・効果音を付ける方法を解説したものです。ここでの説明はすべて全学計算機システム上での動作を前提としています。
透過画像を表示する方法の記事も書いています。こちらもよければどうぞ
【プロ実II】openGLで透過画像(BB)を表示する
この記事ではFreealutならびにopenALというライブラリを使って全学計算機で音を出す方法を説明します。(音を止める方法は説明しません。ドキュメントなど読んでください。筆者も分かり次第追記するかもです。)
同科目履修の方は、音をつけようとするなら必ず動くものを完成させてからにしましょう。この方法がうまくいかないからといって頑張っていると時間を吸われます。
Freealutを導入したい
2019年2月現在の全学計算機の環境では、Freealutライブラリを生成するためにopenALライブラリが必要です。また、openALライブラリを生成するためにALSAライブラリが必要です。
ALSA
, openAL
, Freealut
の順番でライブラリをコンパイルし、最終的に共有ライブラリlibalut.so
とlibopenal.so
が得られればプログラムから音が出せるようになります。
ただこれらのライブラリを自力でコンパイルするのは面倒なので、予めコンパイルしておいたライブラリをダウンロードして使えるようにしておきました。自力でコンパイルする方法も後述しています。
コンパイル済みライブラリの導入
最終的に、プログラムを開発しているディレクトリを以下のような構成にします。それからMakefileを書き換えることでFreealut
ならびにopenAL
が導入できます。
作業ディレクトリ/
├ AL/
│ └ al.h alc.h alext.h alut.h efx-creative.h efx-presets.h efx.h
├ lib/
│ └ libalut.so libalut.so.0 libopenal.so libopenal.so.1 libopenal.so.1.16.0
├ Makefile
├ A.h B.h C.h
└ A.c B.c C.c
コンパイル済みのライブラリをダウンロード
まずは、openAL-alut.zipをダウンロードして、プログラムを開発しているディレクトリに展開します。するとそのディレクトリに AL
とlib
というディレクトリができます。
Makefileを書き換える
授業のサンプルコードのMakefileを改変したものです。
TARGET=main
$(TARGET): main.o A.o B.o C.o
cc -o $(TARGET) main.o A.o B.o C.o -L. -L./lib -Wl,-rpath ./lib -lglut -lGLU -lGL -lXi -lXrandr -lm -lopenal -lalut
.c.o:
cc -c $< -I. -Wall
run: $(TARGET)
./$(TARGET)
clean:
rm -f *.c~ *.o *.h~ $(TARGET)
ポイントは以下の2点です。
-
cc -o
のオプションに-Wl,-rpath ./lib
-L./lib
-lopenal -lalut
をつけること -
cc -c
のオプションに-I.
をつけること
-Wl,-rpath ./lib
はコンパイルされたプログラムが動的ライブラリの在り処(./lib
)を知ることができるようにするための引数です。これがないとコンパイルできても実行時にエラーを吐きます。
-L./lib
はコンパイル(リンク)時、コンパイラ(リンカ)に対しライブラリの在り処(./lib
)を知らせるための引数です。
-lopenal -lalut
はライブラリlibopenal.so
とlibalut.so
とをプログラムに対してリンクするための引数です。ライブラリはlib***.so
という特別な名前になっていて、***
の部分を-l
に続けて指定する必要があります。
glut / alutを組み合わせてBGMを再生する
大雑把なサンプルコードを示します。(そのままコピーしても動作しません)
#include <GL/glut.h>
#include <AL/alut.h>
int main(int argc, char *argv[])
{
alutInit(&argc, argv);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutCreateWindow("main");
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
init();
glutMainLoop();
return 0;
}
void game_start(void) {
ALuint bgmBuffer, bgmSource;
bgmBuffer = alutCreateBufferFromFile("BGMファイル.wav"); // 音声ファイルを読み込む. WAV限定.
alGenSources(1, &bgmSource);
alSourcei(bgmSource, AL_BUFFER, bgmBuffer);
alSourcei(bgmSource, AL_LOOPING, AL_TRUE); // BGMがループするようにする
alSourcePlay(bgmSource); // 音声を再生する. bgmSource番に登録された音を再生するみたいな感じでしょうね(適当)
}
void game_exit(void)
{
alutExit();
exit(0);
}
glutと同じように main
関数内で alutInit(&argc, argv)
を呼ぶ必要があります。また、プログラムを終了する前にalutExit()
を呼ぶ必要があります。
game_start()
関数が呼ばれたと仮定すると、そこでBGMファイル.wav
の再生が始まります。 alutCreateBufferFromFile()
関数の引数に渡すファイルは.wav
ファイルである必要があります。
alSourcei(bgmSource, AL_LOOPING, AL_TRUE);
によって音楽がループ再生されるようになります。
効果音を再生する
上のBGMを再生するサンプルとあまり変わりありません。上のサンプルのalSourcei(bgmSource, AL_LOOPING, AL_TRUE);
の記述を取り除くと音声の再生が単発になり、効果音として再生できます。
ただし、効果音を鳴らすタイミングで毎回 alutCreateBufferFromFile()
を呼び出すのは避けるべきです。この関数は実行のたびにファイルを2次記憶から読み出すのでプログラムの実行が一時的に中断されてしまいます。
したがって、上のサンプルの
ALuint bgmBuffer, bgmSource;
を大域(グローバル)変数にしておいた上で、プログラムの初期化の際に、先に
bgmBuffer = alutCreateBufferFromFile("音声ファイル.wav");
alGenSources(1, &bgmSource);
alSourcei(bgmSource, AL_BUFFER, bgmBuffer);
を呼び出しておき、効果音を再生するタイミングで
alSourcePlay(bgmSource);
のみが呼ばれるようにしましょう。
Freealut, openAL, ALSAライブラリを自力でコンパイルする
先に述べたように、2019年2月現在の全学計算機の環境では、Freealutライブラリを生成するためにopenALライブラリが必要です。また、openALライブラリを生成するためにALSAライブラリが必要です。
ALSA
, openAL
, Freealut
の順番でライブラリを自力でインストールしていく方法を説明します。
以下の手順は、筆者が10時間くらいかけてトライアンドエラーをうんざりするほど繰り返した挙げ句にたどり着いた解で、ちょっとでも改変するとビルドできない可能性が高いです。
インストールディレクトリを作る
~
(ホームディレクトリ, /home/sXXXXXXX/
)にmylibs
というディレクトリを作って、また、その中にlib
, include
というディレクトリを作って作業したいと思います。
~$ mkdir mylibs
~$ cd mylibs/
~/mylibs$ mkdir lib include
~/mylibs
の中に include
, lib
ができます。
ALSAライブラリの生成
alsa-libのソースファイルをダウンロードし、それをビルドして libasound.so
, libasound.so.2
, libasound.so.2.0.0
を生成します。これは次にopenALをビルドするのに必要です。
~/mylibs$ wget ftp://ftp.alsa-project.org/pub/lib/alsa-lib-1.1.8.tar.bz2
~/mylibs$ tar -xjf alsa-lib-1.1.8.tar.bz2
~/mylibs$ cd alsa-lib-1.1.8/
~/mylibs/alsa-lib-1.1.8$ mkdir build
~/mylibs/alsa-lib-1.1.8$ cd build/
~/mylibs/alsa-lib-1.1.8/build$ ../configure --prefix=`pwd`
~/mylibs/alsa-lib-1.1.8/build$ make install
~/mylibs/alsa-lib-1.1.8/build$ cd ../../
openALライブラリの生成
openal-soft_1.16のソースファイルをダウンロードし、それをビルドして、libopenal.so
, libopenal.so.1
, libopenal.so.1.16.0
を生成します。これは次にFreealutをビルドするのに必要になるほか、音を鳴らすプログラムをコンパイルするときに直接必要になります。
~/mylibs$ wget http://archive.ubuntu.com/ubuntu/pool/universe/o/openal-soft/openal-soft_1.16.0.orig.tar.bz2
~/mylibs$ tar -xjf openal-soft_1.16.0.orig.tar.bz2
~/mylibs$ cd openal-soft-1.16.0/
~/mylibs/openal-soft-1.16.0$ cp -r include/AL ../include/
~/mylibs/openal-soft-1.16.0$ cd build
~/mylibs/openal-soft-1.16.0/build$ cmake .. -DALSA_LIBRARY=~/mylibs/lib/libasound.so -DALSA_INCLUDE_DIR=~/mylibs/alsa-lib-1.1.8/include
~/mylibs/openal-soft-1.16.0/build$ make all
~/mylibs/openal-soft-1.16.0/build$ cp -r libopenal.so* ../../lib/
~/mylibs/openal-soft-1.16.0/build$ cd ../../
Freealutライブラリの生成
freealutのリポジトリをGithubからcloneして、それをビルドし、libalut.so
, libalut.so.0
を生成します。これは音を鳴らすプログラムをコンパイルするときに直接必要になります。
~/mylibs$ git clone https://github.com/vancegroup/freealut.git
~/mylibs$ cd freealut/
~/mylibs/freealut$ cp -r include/AL ../include/
~/mylibs/freealut$ mkdir build
~/mylibs/freealut$ cd build/
~/mylibs/freealut/build$ cmake .. -DOPENAL_LIBRARY=~/mylibs/lib/libopenal.so -DOPENAL_INCLUDE_DIR=~/mylibs/openal-soft-1.16.0/include/
~/mylibs/freealut/build$ make all
~/mylibs/freealut/build$ cp -r src/libalut.so* ../../lib/
~/mylibs/freealut/build$ cd ../../
生成したライブラリの確認
最終的に lib/
include/AL/
が以下のようになればライブラリの用意は完了です。
~/mylibs$ ls -l lib/
合計 2088
lrwxrwxrwx 1 s8101919 student1919 12 2月 7 02:53 libalut.so -> libalut.so.0
-rwxr-xr-x 1 s8101919 student1919 44432 2月 7 02:53 libalut.so.0
lrwxrwxrwx 1 s8101919 student1919 14 2月 7 02:52 libopenal.so -> libopenal.so.1
lrwxrwxrwx 1 s8101919 student1919 19 2月 7 02:52 libopenal.so.1 -> libopenal.so.1.16.0
-rwxr-xr-x 1 s8101919 student1919 2079504 2月 7 02:52 libopenal.so.1.16.0
~/mylibs$ ls include/
AL
~/mylibs$ ls include/AL
al.h alc.h alext.h alut.h efx-creative.h efx-presets.h efx.h
用意したライブラリとインクルードファイル群を以下のようにして、プログラムを開発しているディレクトリにコピーします。
~/mylibs$ cp -r lib (プログラムを開発しているディレクトリのパス)
~/mylibs$ cp -r include/AL (プログラムを開発しているディレクトリのパス)
プログラムを開発しているディレクトリにAL
というディレクトリとlib
というディレクトリができます。
こうすることで #include <AL/alut.h>
を読み込めるようになります。
おまけ
筆者はゲームを作るにあたって音楽から最初に作りましたが、音の再生の難易度が高すぎて結局音を付けて提出することができませんでした。
作成したゲームのソースコードは以下のリポジトリにアップロードしてあります。(音は付けていません)
スズメバチに気をつけよう - https://github.com/iciclize/Suzumebachi
また、先に作ったBGMはSoundCloudにアップロードしました(蛇足)
夜の都会を飛ぶ - https://soundcloud.com/icesofticon30th/e1kmhhkhzsdb
参考文献
UbuntuでALSAライブラリを使って音のプログラミング -
工房便り〜TSUBAKI GUITARS & LEATHER
OpenAL/alutでサウンドを鳴らしてみる(実践編) - とど。
Stack Overflowなどその他たくさん(絶望)