ウエーブテーブルシンセサイザをlogue SDKで作ってみた(追記あり)

minilogue xdやNTS-1には、カスタムオシレータのサンプルとしてウエーブテーブルオシレータ「waves」が付属してきます。ソースコードも公開されています。このオシレータは、logue SDKに含まれるウエーブテーブルの90個の波形から、前半46個の中から1つ、後半44個の中から1つの波形を選び、2つのミックス(リングモジュレーションも可)の比率をShapeパラメータで調整しつつ、サブオシレータとして16個の波形から選んだ3つ目の波形もミックスできるようになっていました。

今回作成したのは、このサンプルオシレータ「waves」よりもシンプルな、一つの波形を鳴らすだけのオシレータ「Waves2」です。コードは以下のリポジトリで公開しています。バイナリはこちらです。

boochow/Waves2
a simple wavetable synthesizer for logue SDK. Contribute to boochow/Waves2 development by creating an account on GitHub.

使い方は、波形をオシレータの第一パラメータで選択します。また、Shapeノブで倍音成分を付加することができます。矩形波のPWMが変化するような感じで音色が変化します。

logue SDKで内蔵ウエーブテーブルを使う場合、コードは非常に単純です。
内蔵ウエーブテーブルはA~Fの6つのファミリに分かれています。各ファミリの実体はポインタの配列wavesA, wavesB, … wavesFです。これらの配列は15個前後のポインタを保持しており、それぞれのポインタが一つの波形のウエーブテーブルを指しています。ファミリごとのウエーブテーブルの個数はSDK内で定数として定義されています

ウエーブテーブルを読み出すには、ウエーブテーブルと位相を指定するとサンプルを返す関数osc_wave_scanf()を使います。ループ内で位相の値を増やしながらこの関数を呼び出し、出力バッファを埋めていきます。この処理は鋸波等のウエーブテーブルを使う場合と大差ありません。なお、鋸波や矩形波ではピッチに合わせて複数のウエーブテーブルから最適なものを選択していましたが、今回使用しているlogue SDK内蔵の波形では音高ごとのウエーブテーブルは用意されていません。

本オシレータのオリジナル機能であるShapeノブによる倍音付加ですが、最初はまず矩形波のPWMのように、波形の時間軸方向の幅を狭めることで、元波形の倍音構造を維持したまま、倍音をより高音域に変化させてみました。
こんな感じです。

大体思った通りの音色変化ができましたが、波形そのものは一周期分しか再生していないので、無音区間があります。しかし、この無音区間を同じ波形で埋めてしまうと、単なるピッチ変換になってしまいます。

そこで、最初の一周期分はそのまま再生し、下図のように二周期目以降はだんだん減衰させてみました。


そこそこの倍音成分が得られたので、これでよしとしました。ただ、波形1つにつきウエーブテーブルが一つしかなく、最大で基音の3オクターブ上(8倍の周波数)で使っていますので、高音域でエイリアスノイズが出たり、低音域で上記の減衰関数それ自体の音が耳についたり、といった欠点はあります。

2020/7/24~25追記:
波形によっては倍音成分が耳に付きすぎる気もし、かといってこれをフィルタで削るのも何か違うだろうと思いましたので、二周期目以降をより大きく減衰させるパラメータをShift-Shape(NTS-1ではノブB)に追加してみました。
こんな感じになります。


また、Shapeパラメータが等比級数になっていなかったので修正しました。さらに、Shapeパラメータの変化に対して、音色が一定の変化量を超えないよう線形補間で追随するコードを追加しました。倍音の変化がよりスムーズかつノイズレスになったはずです。

***

ところで、今回用いている「1波長分のデータを高速に再生することで、倍音成分全体をその比率を保ったままでより高い周波数や低い周波数に移行し、かつ再生する周波数自体はそのまま」という手法ですが、フィルタを使わずに倍音成分を変化させられるので、なかなか便利です。(とパッチをいくつか作ってみて実感しました。)

フィルタは倍音成分を追加することができませんが、今回の音源は元の波形に無い高次の倍音を追加することができます。倍音を追加するシンセシス方式をAdditive Synthesisといいます(フィルタで削る方式はSubtractive Synthesis)。伝統的なAdditive Synthesisは、基音の周波数の整数倍の周波数のサイン波を手動で追加していくものです。

Harmonic Waveform Generator :: Electronic Measurements
Waveform generator with additive synthesis

Additive方式の音源の最近の有名なものでは、Mutable Instrumentsの製品にAdditive modeが搭載されています。以前ちょっと記事にしましたが、このモードはlogue SDKにも移植されています。「MO2 add」がそれです。他には、最近ではNektar社のBoltという音源がちょっと話題になりました。これも算術的に倍音成分を追加していく方式のようです。

Nektar Bolt harmonics synthesizer review

Additive方式は倍音の分布をどう制御するかが鍵だと思いますが、どちらかというと過去はFM音源方式や、波形の変形による倍音付加のように、倍音分布を直接は制御しない方式のほうが主流であったと思います。これらも結果的には倍音を付加しますが、Additive方式と呼べるのかどうかはちょっと分かりません。

今回作った音源方式は、倍音の分布自体は元のウエーブテーブルの波形を元にして、それを変形(高域へシフト)するという位置づけになります。これも純粋なAdditiveとは言えない(倍音を自由に追加できず、元波形の倍音分布に縛られるので)のですが、FM音源方式と比べると倍音成分の制御がやりやすく、波形変形方式と比べると波形ごとの変形方法を考える必要が無いので汎用性が高いのではないかと思います。

では今回作った音源の方式がまったく新しいかというとそうでもなく、男声と女声を変換するボイスチェンジャーでは似たようなことが行われています。

今回作ったオシレータはピッチ自体は変換せずに倍音成分だけを周波数軸で移動していますが、ボイスチェンジャーでは、ピッチを変換しつつ、それとは独立に倍音成分を移動しています。人声をピッチシフトしてみた方はご存知と思いますが、ピッチを上げたら男声を女声にできるかというと、そうではないですね。

人声における倍音の分布をフォルマントと言いますが、フォルマントは喉や口の物理的な構造による共鳴が影響しているので、基本周波数の高低とは独立の要因で決まってきます。ピッチを上げる場合、倍音分布はピッチよりも少し少な目に上昇させないと、自然な声になりません。

そのためボイスチェンジャーでは、今回の音源方式のように、声の波形の1周期分の再生速度を速めたり遅くしたりして倍音分布全体を制御しています。同時に、その1周期分を毎秒再生する回数を変化させて、ピッチを制御しています。シンセサイザと違って、まず音声から1周期分の波形を切り出さないといけないので、ボイスチェンジャーのほうが処理は複雑です。以下のリンクにあるTD-PSOLAというのがその処理の具体的な内容になります。

恋声の技術

なお、ボイスチェンジャーではピッチはせいぜい2倍~1/2倍の範囲での変更だと思いますので、今回の音源方式のように1周期内で同じ波形を減衰させながら繰り返す処理は行わないと思います。

というわけで全くの新方式というわけではありませんが、今回作った音源は、ブライトな元気のいい音色が作りやすく、ある意味デジタルの良さみたいなところがあるものができたような気もします。まあシンセサイザーの歴史は長いので、同じような方式は過去に発明されていて私が知らないだけかもしれませんが。

2020/8/11追記:
minilogue xdで他のVCOと組み合わせて使うことを考えると、シンセ本体のLFOやエンベロープを使わずに音作りできるほうが便利なので、簡単なAttack-Decayタイプのエンベロープを内蔵させて、以下のパラメータを追加しました。

・エンベロープをShapeパラメータにかける強度(-100%~100%)
・エンベロープのAttackタイム(0~8sec)
・エンベロープのDecayタイム(0~8sec)
・LFOのShapeパラメータへの影響を弱める度合い(0%~100%)
・エンベロープを音量パラメータにかける強度(0%~100%)

他のVCOと組み合わせる場合、例えばアタック成分だけをこのオシレータで作り、メインの部分はVCOで作る、といったことがやりたくなります。そうすると、エンベロープもフィルタもLFOもこのオシレータとVCOとで独立しているほうが音作りがやりやすくなります。

エンベロープとLFOをShapeパラメータにかける場合、LFOの影響が大きすぎると邪魔になることがあります。しかしLFOはすべてのオシレータで共通なので、LFOを弱めると全てのオシレータに影響が出てしまいます。現状のlogueシリーズはLFOをShapeパラメータにかけるときに、対象のオシレータ(VCO1/2/Multi)は選択できますが、個別の強度は設定できませんので、LFOを弱めるパラメータを追加しました。

また、Ampにかけるエンベロープも全オシレータで共通ですが、アタックをこのオシレータで作って、ゆっくり減衰する成分をVCO1/2で作成したくなる場合がありますので、内蔵エンベロープをAmpにかけるパラメータを追加しました。こちらは外部エンベロープの影響を弱めることはできません。

パラメータの数がもう少しあればLFOも内蔵させたかったところですが、エンベロープだけでも結構役に立つと思います。

コメント