2015年8月15日土曜日

ソフトシンセの作り方(7) - VGS-SAL

VGSのソフトシンセ(波形メモリ音源)の開発で得られた知見を元に、PCやスマートフォンで動くソフトシンセの作り方を解説していきます。一冊の本が書ける程度の分量なので、幾つかのパートに区切って解説していきます。このシリーズを一通り読めば、サウンドプログラミングについて全くの素人でも、PCやスマホなどのプラットフォームで動くオリジナルのソフトシンセが作れる程度になります(たぶん)

なお、このシリーズで扱うプログラミングの例題のビルドには、パソコンが必要です。OSは私が使っているMac OS X向けに解説を記述しますが、Linux(※ALSAに対応しているもの)やWindowsでも問題ありません。

今回は、VGS-SALについて解説します。

VGS-SAL

前回の記事で紹介した低レベルAPIのひとつひとつを解説すると、それだけで膨大な量の解説が必要になってしまいます。そこで、低レベルを直接叩くのではなく、VGSSALSound Abstraction Layout)を利用することにします。
VGS-SALは、WindowsDirectSound)、LinuxALSA)、MaciOSAndroidの低レベルAPIを抽象化したものです。これを用いることで、全OS共通実装で「波形直書き」の実装ができます。

sal-sample

vgs2リポジトリの sample/sal-sample ディレクトリにVGS-SALを用いたサンプルプログラムが格納されています。
このサンプルプログラムでは、VGS-SALを用いて440Hzのサイン波を鳴らし続けます。
サンプルプログラムは、ターミナルで以下のコマンドを実行すれば、ビルドできます。
$ cd ~/vgs2/sample/sal-sample/ && make
sample/sal-sample ディレクトリに格納されている makefile と saltest.c を見てみましょう

(1)makefile

  • saltest.cをビルドする手続きが書かれています

    (2)初期化: init_sound_cli

    • SALの初期化をします
    • cliとは Command Line Interface(コマンド) の略です
    • Windowsの場合、GUI用の初期化処理が別にありますが、その点についての解説は省略します
    • UNIXOSの場合、CLI用とGUI用の間に違いはありません

    (3)終了: term_sound

    • SALが用いているシステムリソースを解放します
    • かならずプログラムの最後で呼び出すようにしてください

    (4)バッファリング: sndbuf

    • 一定間隔毎にSALからコールバックされるバッファリング処理です
    • C++で実装する場合は、必ず extern "C" で宣言するようにしてください
    • 引数 buf : 波形情報を格納するバッファです
    • 引数 size : 波形情報を格納すべきサイズです
    • buf の内容を変更する処理は、必ず lock()  unlock() で囲まなければなりません
    • 上記サンプルでは、440Hzのサイン音 が鳴り続けることになります

    (5)バッファリング処理の内容

    sndbuf  lock()  unlock() で囲まれた範囲(バッファリング処理)の実装内容をもう少しブレイクダウンして見ていきましょう。
    1行目: for(i=0; i < size16; i++, ptr++) {
    2行目:    *ptr = (short)(sin(r) * 16384);
    3行目:    r += PI2 / (22050 / 440); /* 440Hz */
    4行目: }
    1行目
    • size16  引数buf (8bit array)  16bit array とした時の長さです
    • そして、i = 0  size16-1 の間、ptr をインクリメントしながらループすることになります
    • ptr  引数buf  16bit array にしたものです
    • ptr のインクリメントとは、__サンプリング周期のインクリメント(+1Hz)と等価ですね
    2行目
    • sin(r)  16384 にした数値を ptr に代入しています
    • sin関数 の戻り値は -1.0  1.0 の範囲の実数です
    • なので、ptr に代入している値は -16384  16384 の範囲の値です
    • つまり、この 16384 というマジックナンバーは 鳴らす音の大きさ を意味しています
    • 16bit -32768  32767 の範囲の数値なので、限界音量の 50% がこのプログラムで鳴らす音の最大音量となります
    3行目

    • r  2π ÷ ( 22050 ÷ 440 ) で加算しています
    • r  スタティック変数 なので、関数が return しても値が維持され続けます
    • そのため、sndbuf が呼び出され続けると 440Hz のサイン波 が発音され続けることになります

    追記
    umm...
    ここから先はコードベースの解説が多くなるのですが、bloggerだと結構辛いので、GitBook辺りを使ってイチから書き直すか。

    0 件のコメント:

    コメントを投稿

    注: コメントを投稿できるのは、このブログのメンバーだけです。

    合理的ではないものを作りたい

    ここ最近、実機版の東方VGSの開発が忙しくて、東方VGSの曲追加が滞っています。 東方VGS(実機版)のデザインを作りながら検討中。基本レトロUIベースですがシークバーはモダンに倣おうかな…とか pic.twitter.com/YOYprlDsYD — SUZUKI PLAN (...