Skip to content

Instantly share code, notes, and snippets.

@keijiro
Created September 30, 2012 11:10
Show Gist options
  • Save keijiro/3806478 to your computer and use it in GitHub Desktop.
Save keijiro/3806478 to your computer and use it in GitHub Desktop.
Unity でシンセを作る

Unity でシンセを作る

Harmoni という名前の iOS アプリを App Store にサブミットしました。このシンセアプリはゲームエンジン Unity を使って実装されています。

ここでは Unity を使ってシンセを実装するにあたっての心得(?)について記します。

前提

サンプリングベースのリズムマシン等であれば basic 版でも実装可能ですが、スクリプトで合成した波形を使うには、Pro 版でないとキツいです。後述しますが、実装にオーディオフィルタを使うためです。

スクリプトで波形を合成するには

合成した波形を Unity 側に食わせる方法は色々ありますが、レイテンシを考慮した場合に最も優れているのはオーディオフィルタとして実装する方法です。他の方法では、どうしても大きなレイテンシが生じてしまいます。オーディオフィルタであれば、これを防ぐことが可能です。

実装

まず、次のようにしてダミーのオーディオクリップを再生します。

function Start() {
    audio.clip = AudioClip.Create("(null)", 0xfffffff, 1,
                                  kSampleRate, false, true,
                                  function(data:float[]){});
    audio.Play();
}

同スクリプト内に OnAudioFilterRead を実装します。通常はこの中でオーディオをフィルタリングすることになりますが、ここでは入力を全く無視して、合成した波形を出力します。

function OnAudioFilterRead(data : float[], channels : int) {
    for (var i = 0; i < data.Length; i += 2) {
        synth.Run();
        data[i  ] = synth.l_out;
        data[i+1] = synth.r_out;
    }
}

どの程度のことが可能か?

Harmoni ではディオフォニックの FM シンセを実装しました(紹介文ではモノフォニックとなっていますが、リリースを奇麗にするために内部的にはディオフォニックにしています)。iPhone 4S や new iPad であれば問題無く動きますが、iPhone 4 ではサンプリングレートを半分に落とす必要がありました。

iOS ではこのようにモデル毎のチューニングが可能ですが、Android 版を作るとなれば、かなりのマージンを設ける必要が生じるでしょう。

正直なところ、スクリプトによる波形合成には非常に大きな無駄があります。ネイティブで実装するのと比較して 1/10 のスペックも実現できないでしょう。

でも逆に言えば、多大な労力を払ってネイティブ実装したとしても、得られるのは 10 倍のスペックだけです。例えば Smule の Ocarina が 10 倍のスペックになったとして、同時に 10 音鳴らせるようになって喜ぶユーザーがいるでしょうか?

スペックが必要なアプリを作りたい場合は、覚悟してネイティブに走りましょう。そうでなければ、スクリプト言語や Unity を使ってシンセを開発するというのは、許される選択肢だと思います。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment