しかし、今のパソコンやスマートフォンであれば、少なくとも石(H/W)の違いを意識する必要はありません。Windows、Mac OS X、Linux、UNIX、Android、iOSなどで、音を鳴らす基本的な仕組みは全部同じですが、それぞれのOSが提供する「音を鳴らす方法」が以下のように多様にあります。
- Windows: WaveMapper や DirectSound
- Mac OS X, iOS: AudioUnit や OpenAL
- Linux: ALSA; Advanced Linux Sound Architecture
- Android: OpenSL/ES (他)
- UNIX: OSS; Open Sound System
VGSではこの辺りの実装を Sound Abstraction Layer (SAL) という形で抽象化しましたが、今回、その SAL を更に汎用的な形で独立させてみました。
VGS - Sound Processing Unit (SPU)
https://github.com/suzukiplan/vgs-spu
まだこの記事を書いている段階では WIP にしていますが、とりあえず Windows と Mac OS X では動きました。VGS-SPUは、全OS共通の「音を鳴らす方法」を提供します。これを使えば、敷居が高いと思われがちな サウンドプログラミング の敷居が幾分か低くなります。
どの程度低いかは、VGS-SPUの example を見ていただければ分かると思います。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifdef _WIN32 | |
#include <windows.h> | |
#else | |
#include <unistd.h> | |
#endif | |
#include <stdio.h> | |
#include "vgsspu.h" | |
#ifdef _WIN32 | |
static void usleep(int usec) | |
{ | |
Sleep(usec / 1000); | |
} | |
#endif | |
static unsigned int hz; | |
static unsigned int pw = 22050; | |
static void buffering(void* buffer, size_t size) | |
{ | |
short* sbuf = (short*)buffer; | |
size_t s2 = size >> 1; | |
size_t s1; | |
for (s1 = 0; s1 < s2; s1++, sbuf++, hz++) { | |
if (hz % 440 < 220) { | |
*sbuf = (short)((16384 * pw) / 22050); | |
} else { | |
*sbuf = (short)((-16384 * pw) / 22050); | |
} | |
if (pw) pw--; | |
} | |
} | |
int main(int argc, char* argv[]) | |
{ | |
void* context = vgsspu_start(buffering); | |
if (NULL == context) { | |
puts("failed"); | |
return -1; | |
} | |
usleep(1000000); | |
vgsspu_end(context); | |
return 0; | |
} |
この example では、buffering というコールバック関数で波形(440Hz = ラ の矩形波)を書き、main関数で VGS-SPU を起動、スリープ、停止という手続きを実行しています。
「音を鳴らす」というのは要するに波形データの変化(PCM)を書くことです。その辺のことは情報処理の教科書的なもので見たことがあると思いますが、「そのデータを何処に書くの?」ということは恐らく情報処理の教科書的なものには書いてないと思います。「何処に書くのか」は、前述の各OSが提供しているサウンドAPI毎に異なるし、また、あまり纏まった資料も無い(個々のAPI毎にかなり無駄に分厚い専門書とかなら少ないがある)ので、実際に音(PCM)を書くところまで辿り着くのが結構大変です。
しかし、VGS-SPUなら「vgsspu_startを呼ぶ」「コールバックで音を書く」「vgsspu_endで終わる」という極めてシンプルな3ステップだけでサウンドプログラミングの入り口に辿り着くことができます。
そして、VGS-SPUを通して音の鳴らし方のイメージが掴めてきたら、VGS BGM Decoderを見てみると良いです。
VGS BGM Decoder
https://github.com/suzukiplan/vgs-bgm-decoder
VGS-SPUは音を書くための方法で、VGS BGM Decoderは書く音を生成するコーデックと呼ばれるものです。コーデックという言葉はマルチメディア系に詳しい方なら聞いたことがあるかもしれませんが、サウンドの世界では符号化されたデータ(VGSなら .BGM形式)をリニアPCMへ変換するもの(デコーダ)や、何がしかのデータを符号化するもの(エンコーダ)があります。
VGS BGM Decoderにとってのエンコーダは MML(テキスト)を .BGM形式に変換するMMLコンパイラのことですね。VGSのMMLコンパイラについても独立したリポジトリに切り出してみました。
VGS MML Compiler (encoder)
https://github.com/suzukiplan/vgs-mml-compiler
0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。