LoginSignup
15
16

More than 3 years have passed since last update.

C/C++ にて オーディオファイルを再生する

Last updated at Posted at 2020-05-28

概要

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

15
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
16