概要
C/C++ にて オーディオファイルを再生する方法をまとめた。
オーディオファイルを再生するためには、
大きく2つの機能が必要です。
- 1つ目の機能
サウンドデバイスを使って、音を鳴らす機能。 - 2つ目の機能
オーディオファイルを解析して、音の波形データを取り出す機能。
1つ目の機能は、サウンドデバイスを管理するOSに依存している。
OSごとに固有の方法があるが、OS依存度の小さいクロスプラットフォームのミドルウェアを使う方法を紹介する。
具体的には、 OpenAL, PulseAudio, SDL、irrKlang など。
2つ目の機能は、オーディオファイルの種類ごとに、専用のオーディオコーデックがある。
具体的には、 libmod, libvorbis, libflac など。
MAC にて動作確認したコードを Github に公開した。
https://github.com/ohwada/MAC_cpp_Samples/blob/master/AudioPlayer.md
OpenAL
OpenAL (Open Audio Library)
クロスプラットフォームのオーディオAPIである。
APIのスタイルと慣習は意図的にOpenGLと似せてある。
利用可能なプラットフォームOS
https://www.openal.org/platforms/
macOS では、プリインストールされている。
下記のように、g++ のコマンドオプションにOpenAL を指定する。
g++ sample.cpp -framework OpenAL
まずは、簡易的に音を鳴らす。
(1) 音の波形データを作成する。
// 16ビット モノラル
# include <math.h>
# include<limits.h>
const int SAMPLINGRATE = 44100; // CD規格
int freq = 440; // 楽器の基準周波数 (Hz)
int duration = 1; // 音の長さ (秒)
int data_size = SAMPLINGRATE * duration;
int16_t* data = new int16_t[data_size];
// radian per sample rate
double delta = (2 * M_PI * freq ) / SAMPLINGRATE;
// Generate Sin wave
for (int i = 0; i < data_size; i++) {
data[i] = SHRT_MAX * sin(delta * i);
}
(2) OpenAL を初期化する
ALCdevice *device = alcOpenDevice(NULL);
ALCcontext *context = alcCreateContext(device, NULL);
alcMakeContextCurrent(context);
ALuint buffer;
ALuint source;
alGenBuffers(1, &buffer);
alGenSources(1, &source);
(3) 波形データを関連づけて、音を鳴らす
alBufferData(buffer, AL_FORMAT_MONO16, &data[0], data_size, SAMPLINGRATE);
alSourcei(source, AL_BUFFER, buffer);
alSourcePlay(source);
サンプルコードはこちらに。
https://github.com/ohwada/MAC_cpp_Samples/blob/master/OpenAL/play_tone.cpp
wav ファイルを再生する
OpenALの拡張ライブラリである alure を使用する
https://kcat.strangesoft.net/alure.html
パッケージ管理ツールでインストールできる。
macOS の例:
brew install alure
alure の使い方の例
char *filename = "sample.wav"; // ファイル名
alureInitDevice(NULL, NULL);
ALuint source;
alGenSources(1, &source);
ALuint buffer = alureCreateBufferFromFile(filename);
alSourcei(source, AL_BUFFER, buffer);
alSourcePlay(source);
サンプルコードはこちらに。
https://github.com/ohwada/MAC_cpp_Samples/blob/master/OpenAL/play_wav.cpp
wav はファイル構造が簡単で非圧縮なので、
alure を使用せずに、
C++ の標準関数で作成することもできる。
サンプルコードはこちらに。
https://github.com/ohwada/MAC_cpp_Samples/blob/master/wav/play_wav_with_openal.cpp
mp3 ファイルを再生する
mp3 のオーディオコーデッックである libmad を使う
https://www.underbit.com/products/mad/
パッケージ管理ツールでインストールできる。
macOS の例:
brew install libmad
libmad の使い方
サンプルコード minimad.c が公開されている。
http://m.baert.free.fr/contrib/docs/libmad/doxy/html/minimad_8c-source.html
minimad.c は、
標準入力から mp3 を読み込んで、標準出力に raw pcm を出力する。
ビルドしたあと、下記のように使用する。
./a.out < sample.mp3 > out.raw
raw ファイルを再生するには、sox コマンドを使用する。
http://sox.sourceforge.net/
パッケージ管理ツールでインストールできる。
macOS の例:
brew install sox
sox コマンドで raw 形式を wav 形式に変換する。
sox -r 44100 -e signed -b 16 -c 2 out.raw output.wav
C++ と libmad を使って、
mp3 ファイル を wav ファイルに変換するコードはこちら。
https://github.com/ohwada/MAC_cpp_Samples/blob/master/libmad/conv_wav.cpp
C++ と libmad を使って、
mp3 ファイルを再生するには、
raw pcm を OpenAL に関連づける。
切れ目なく再生するように、raw pcm をキューに積む。
alBufferData(buffer, AL_FORMAT_STEREO16, pcm_data, pcm_data_size, 44100);
alSourceQueueBuffers(source, 1, &buffer);
サンプルコードはこちらに。
https://github.com/ohwada/MAC_cpp_Samples/blob/master/libmad/play_mp3_with_openal.cpp