物理モデル
内蔵シンセサイザーのエンジンの多くは、波形から出発してそれを加工します。一方、アコースティック系のエンジンは楽器そのものから出発します。ハンマーで叩かれる弦、リードに駆動される管、スロットを行き来する金属の舌、フォルマントを通る声門音源がその例です。録音を再生するのではなく、機構から 1 音を計算します。1 音ごとにサンプルレートで小さなシミュレーションが走り、そのシミュレーションが放射したものがそのまま音になります。
このページではこれらのエンジンを扱います。モデルが実際に何を計算しているのか、各ボイスがどの物理量を軸にしているのか、各ボイスをどこまで信頼できるかを説明します。
どの方式をいつ使うか
そもそも物理モデルが適切な選択なのか、つまり SoundFont、サンプリング、減算方式と比べてどうかという点は 音源方式 の話題です。このページは方式を選び終えた前提で書かれています。これらのボイスが収まっている共通パッチ層は 内蔵シンセサイザー、用語は シンセシスの基礎 を参照してください。
導波路モデルとは何か
振動する弦や気柱の中では、波が進み、両端で反射して戻ってきます。導波路モデルは、それを計算するいちばん素直な方法です。進行を遅延線で、反射端での損失をフィルターで表し、この 2 つをループに配線する。あとはエネルギーを注ぎ込めば、ループはそれ自身の長さだけで決まる音高で鳴りはじめます。
仕掛けはこれだけですが、使う前に知っておきたい帰結が 2 つあります。
録音データが不要です。 サンプリングされたグランドピアノは、音域・ベロシティレイヤー・アーティキュレーションの録音を多数収めるため、大きなデータになります。モデルはコンパクトなパラメータ集合を持ち、モデル化した範囲内の音高や演奏値を計算します。SoundFont を一切伴わずに届いた MIDI ファイルの受け皿をこれらのボイスが担えるのは、そのためです。
ボイスごとに計算コストがかかります。 サンプラーがメモリを読みながら再生ボイスを進めるのに対して、モデルは 1 サンプルごと・1 ボイスごとに物理を解きます。ボイスはそれぞれ自前の遅延線、損失フィルター、ボディ共鳴器を抱えます。ここで制約になるのはディスク容量ではなく同時発音数です。擦弦を厚く重ねたアレンジは、同じものをサンプルで鳴らすより重いレンダリングになります。
そして、これは録音ではなくモデルです。 機構を再現するので、サンプルには出せない振る舞いが出ます。たとえば強打が明るいのは、明るいサンプルを別に録ったからではなく、フェルトがより深く潰れるからです。ただし特定の 1 台の個性は自動的には手に入りません。そのためには調整と較正が必要です。
ループとモデル固有の段
- 共通する導波路の抽象化
- モデル固有の段
- ループの外側にある出力タップ
導波路モデルでは、左から読むと、励振部が遅延線にエネルギーを注ぎ、波が進み、向こう端で折り返して損失フィルターを通り、励振部のところへ戻ってきます。この 1 往復の長さがこの抽象化での音高を決めるため、導波路系のボイスには別のチューニング用オシレーターが要りません。弦や開管では 1 往復がちょうど 1 周期なので、ループの長さはサンプルレートを基音で割った値になります。例外は片側が閉じた円筒管、つまりクラリネットの管です。開いた端は波を反転させて返すので、波が元の形に戻るには 2 往復かかります。そのため reed エンジンの円筒管は、周期の半分の長さのループに反転する反射を組み合わせています。同じ長さの開管より 1 オクターブ低く鳴り、奇数倍音が強く出るのはこのためです。ホストのレートでは音高を保てないほど短いループ(低いレートでの高音)は、内部で 48 kHz 以上のレートで動かしてから戻すので、最高音も 8、16、24、44.1、48 kHz のどれでも同じ音高で鳴ります。放射段はループの外側から取り出したタップで、ボディやベルが内部の波をマイクに届く音へ変える場所にあたります。
モデルがこれらを公開する場合、brightness と damping は伝搬段や放射段のスペクトルの開きとエネルギー損失を表します。具体的な効き方はモデルごとに異なります。擦弦や吹奏のボイスでは励振部が損失を補えるため、音を持続させながら色と減衰を変えられます。
励振部は楽器間で変わる重要な要素ですが、それだけではありません。弓は弦に対するスティックスリップ摩擦、リードは口腔圧と管内圧で開閉するバルブです。唇には固有の共振があり、ジェットには固有の通過時間があります。遅延トポロジー、損失、放射、ボディ結合もエンジンごとに異なります。
打弦・撥弦のボイス(piano、plucked-string、karplus-strong、harpsichord)は導波路または遅延線の構造と短い励振部を使います。ハンマー、ピック、爪がエネルギーを渡したあとは、残った状態が鳴り止みます。そのため発音中に動かしたコントロールは、持続する擦弦ボイスには届いても、打撃系では受け取る励振軸が残っていないことがあります。
下の表で使う用語
- 管(ボア):管楽器の管の中の空気柱。形(円筒か円錐か)が、どの共鳴を支えるかを決めます。
- アンブシュア:マウスピースに当てる奏者の唇の構え。金管では唇自身の共振を調律します。
- ヘルムホルツ運動:弓で擦った弦の定常的な動き。1 つの折れ目が弦の上を回り、1 周期ごとに弦が弓に貼り付き、それから滑って戻ります。
- t60:弦の振動が 60 dB 下がるまでの時間。ルームの残響に使う RT60 と同じ尺度です。
- 8′ と 4′:オルガンとハープシコードのレジストレーション。パイプの長さ(フィート)に由来する呼び方で、8′ は記譜どおりの音高、4′ は 1 オクターブ上で鳴ります。
アコースティックモデル
| エンジンモード | 何をモデル化しているか | 軸に据えている物理量 | 識別子 |
|---|---|---|---|
piano | フェルトハンマー、連成したユニゾン弦、響板 | ハンマーが弦を打つ位置 | piano.strike_position |
pipe-organ | 共通の風箱から風を受けるフルー管 | 歌口での風圧 | pipe_organ.breath |
bowed-string | 弦に食いついては滑る松脂つきの弓 | 接触位置と弓圧 | bowed_string.bow_position |
reed | 円筒管・円錐管を開閉するケーンリード | 吹奏圧とリードの硬さ | reed.breath_pressure |
brass | 朝顔付きの管に対する唇バルブ | 吹奏圧とアンブシュア | brass.lip_tension |
flute | エッジを横切って開管を駆動する空気ジェット | 管の周期に対するジェット通過時間 | flute.jet_ratio |
plucked-string | 湾曲した駒をかすめ続ける弦 | 撥弦位置と駒のびびり | plucked_string.pick_position |
vocal | 声門音源と 5 つの母音フォルマント | どの母音か | vocal.vowel |
free-reed | スロットを行き来する金属の舌 | 蛇腹の圧力と舌の硬さ | free_reed.breath_pressure |
harpsichord | クイルで弾く弦列と駒の後ろの短い区間 | 撥弦位置と後部結合 | harpsichord.pluck_8a |
上の多くのモデルは、図が示した意味での導波路です。vocal はループを持たないソースフィルターモデル、free-reed は連成する気柱を持たない駆動舌です。harpsichord は弦列ごとに独立した遅延線を使い、駒の後ろに短い区間を持ちます。いずれも録音を再生するのではなく機構から解くため、このページで扱います。
以下の識別子はエンジン側のフィールド名です。各モデルはこれらで音づくりされており、名前付きプリセットが設定しているのもこれらですが、パッチからは engineParams で、lowerCamelCase のキーを使って 1 つずつ上書きできます。詳しくは コードから触る を参照してください。
構造体の既定値の列は、プリセットを適用する前にボイスが始まる値です。synthEngineParamInfo(mode) が default として返すのは別の値で、エンジンの基本プリセット(bowed-string ならヴァイオリン)の値です。音づくりされたフィールドの多くで、構造体の既定値とは異なります。範囲はどちらも同じです。
piano:ハンマー、ユニゾン弦、響板
| フィールド | 構造体の既定値 | 範囲 | 意味 |
|---|---|---|---|
piano.strike_position | 0.085 | 0 – 0.5 | ハンマーが弦に当たる位置を弦長に対する比率で。そこに節を持つ倍音に櫛型のノッチが入ります。既定値は弦長のおよそ 12 分の 1 で、実際のグランドは音域によって約 7 分の 1 から 12 分の 1 の間を叩きます。 |
piano.hammer_exponent | 2.5 | 1.5 – 4 | フェルトの圧縮則(変位に対する力)。強打が弱打よりどれだけ短く明るくなるかを決めます。 |
piano.hammer_contact_ms | 1.2 | 0.2 – 10 | A4・mf でフェルトが接触している時間。ハンマーが弦に T 秒触れ続けると、エネルギーを押し込める上限はおおよそ 1/T になります。1.2 ms なら打鍵は 1 kHz 付近で頭打ちになり、硬く短い接触ならもっと高くまで届きます。 |
piano.strings | 3 | 1 – 3 | 1 音あたりの連成ユニゾン弦の本数。 |
piano.detune_cents | 1.6 | 0 – 50 | ユニゾン内のマイクロデチューン。弦どうしが歩調を崩し、プロンプトサウンドが長いアフターサウンドへ移ります。 |
piano.dispersion | 1.0 | 0 – 1 | 鍵盤位置で段階づけられた剛性ストレッチへの係数。0 は完全に調和的な弦。 |
つまみ駆動の撥弦モデルには真似できないことが 2 つあります。インハーモニシティは U 字カーブを描き、高音側へ単調に増えるのではなく C2 付近で最小になります。低音の巻線が下端で再び持ち上げるので、鍵盤のいちばん下はそのすぐ上の音より非調和です。縦振動モードが計算されており、打たれた弦は横だけでなく長さ方向にも伸び縮みし、その張力変化が低音のアタックを埋めるうなりを放射します。これが無いと低音は聴こえるより「感じる」ものになります。
pipe-organ:共通の風箱に乗ったフルー管
| フィールド | 構造体の既定値 | 範囲 | 意味 |
|---|---|---|---|
pipe_organ.breath | 0.35 | 0 – 1 | ジェットを駆動する歌口の圧力。音量ではなく音色を決めます。管は帯域全体で自励振動し、音量はアンプエンベロープ側が持ちます。 |
pipe_organ.brightness | 0.5 | 0 – 1 | 開口端が上の倍音をどれだけ明るく反射するか。上端がプリンシパル、下端がストップトフルート。 |
pipe_organ.stopped | false | — | 蓋つき管。基音優位でオクターブポンプが抑えられ、反射が暗くなります。 |
pipe_organ.rank_count | 0 | 0 – 8 | 同時に鳴るランク数。0 は上の 2 フィールドから作られる暗黙の 8′ 1 ランク。 |
pipe_organ.wind_sag | 0.0 | 0 – 1 | 引かれる管が増えたとき共通風圧がどれだけ落ちるか。和音を張ると少し沈み、また戻ります。 |
pipe_organ.tremulant_rate_hz | 0.0 | 0 – 12 | 風圧のうねり。音高と音量が一緒に揺れます。0 でオフ。 |
風の供給は 1 音ごとではなくランク間で共有されます。wind_sag に意味があるのはそのためで、これは風箱の性質であり、複数の管が同時に鳴ったときにだけ現れます。
bowed-string:食いついて、滑る
| フィールド | 構造体の既定値 | 範囲 | 意味 |
|---|---|---|---|
bowed_string.bow_position | 0.13 | 0.02 – 0.5 | 駒からの接触位置を弦長比で。小さいほど駒寄り(スル・ポンティチェロ、明るく硬い)。0.13 が自然な運弓位置です。そこから指板寄り(スル・タスト)へ動かしても、このモデルでは音は柔らかくなりません。ヴァイオリンのプリセットでは再び明るくなります。 |
bowed_string.bow_force | 0.5 | 0 – 1 | 弓圧。摩擦曲線の固着領域の幅を決めます。低いと弦をつかみきれない細い音、高いとしっかりした、やや粗い音。 |
bowed_string.bow_speed | 0.5 | 0 – 1 | 運弓速度、すなわちダイナミクス。 |
bowed_string.brightness | 0.5 | 0 – 1 | 駒側の反射の開き具合。 |
bowed_string.damping | 0.4 | 0 – 1 | 駒ループの損失。どちらにせよ弓が補うので音は持続します。 |
bowed_string.rosin | 0.0 | 0 – 1 | 松脂の食いつきの粗さを、弓速に乗る決定的な微小ノイズとして。 |
弓の位置と圧力は奏者が実際に操作している対です。そして互いの代わりにはなりません。位置が決めるのは「どの倍音が立つか」、圧力が決めるのは「擦弦を擦弦たらしめるヘルムホルツ運動へどれだけきれいにロックするか」です。放射タップにはヴァイオリン属のボディ共鳴が乗ります。実測されたヴァイオリンの胴体であり、bowed_string.corpus_scale で置けるのは最低次のモードだけです。チェロは拡大されたヴァイオリンではないからです。
下のデモは、ヴァイオリンのプリセット自身の弓から始めて、2 つのうち 1 つずつを動かします。
reed:息が開けるバルブ
| フィールド | 構造体の既定値 | 範囲 | 意味 |
|---|---|---|---|
reed.breath_pressure | 0.6 | 0 – 1 | 定常口腔圧、すなわちダイナミクス。リードはしきい値を超えないと発音しないので、極端に低い値は無音に近づきます。 |
reed.reed_stiffness | 0.5 | 0 – 1 | リードテーブルの傾き。柔らかく暗い側から、硬く明るくバジーな側まで。 |
reed.reed_opening | 0.5 | 0 – 1 | 静止時にリード先端がどれだけ開いているか。低いと早く閉じ切り、鼻にかかった音になります。 |
reed.conical | false | — | false はリード側が閉じた円筒管、つまりクラリネットで、奇数倍音が主体になります。true は円錐管で、開管近似により全倍音列が出ます(サックス、オーボエ、ファゴット)。 |
reed.brightness | 0.5 | 0 – 1 | ベル側の反射の開き具合。 |
reed.chiff | 0.4 | 0 – 1 | リードが発音しはじめる瞬間の短い明るいノイズ。音が膨らんで始まるのではなく、輪郭を持って立ち上がります。 |
conical は管体が支える共鳴モードを変えます。あとから EQ カーブをかけるのではなく、発音の段階で共鳴と倍音バランスが変わります。
brass:唇がバルブそのもの
| フィールド | 構造体の既定値 | 範囲 | 意味 |
|---|---|---|---|
brass.breath_pressure | 0.7 | 0 – 1 | 唇バルブを駆動する定常口腔圧。 |
brass.lip_tension | 0.5 | 0 – 1 | アンブシュア。唇の共振が管に対してどこに位置するか。締めれば少し上に位置し、金管のエッジを生む外向き振動点へ。緩めれば下側の、広く安定した中心へ。 |
brass.lip_damping | 0.5 | 0 – 1 | 唇の共振の幅。共振器の Q を 0 で 30、1 で 8 に設定します。Q は音域によらず一定なので、低い音でも高い音でも共振は音高に対して同じ割合の細さを保ちます。低いと鋭くバジーな唇、高いと幅の広い丸い唇。 |
brass.conical | false | — | 円筒系(トランペット、トロンボーン)と円錐系(ホルン、チューバ、コルネット、フリューゲルホルン)。どちらも全倍音列を放射し、このフラグはベル反射の色づけを変えます。 |
brass.brightness | 0.5 | 0 – 1 | ベル反射の開き具合。 |
brass.damping | 0.4 | 0 – 1 | 管ループの損失。 |
リードと違い、金管の唇は自分の共振を持っています。音高は唇と管が折り合った場所に立つので、lip_tension は音色であると同時にイントネーションのコントロールでもあり、同じ運指で複数の音がスロットに入るのもそのためです。
flute:エッジを横切るジェット
| フィールド | 構造体の既定値 | 範囲 | 意味 |
|---|---|---|---|
flute.jet_ratio | 0.5 | 0.1 – 0.9 | ジェットの通過時間を管の周期に対する比で。0.5 付近でジェットは基音を駆動し、小さくするとオクターブ以上を駆動します。音域を物理的に決めているのがこの値です。 |
flute.breath_pressure | 0.55 | 0 – 1 | 口腔圧で、ダイナミクスとジェット駆動力を決めます。 |
flute.jet_reflection | 0.5 | 0 – 1 | 管から戻る圧力が歌口でジェットをどれだけ偏向させるか。 |
flute.end_reflection | 0.5 | 0 – 1 | 開口端が波をどれだけ強く管内へ戻すか。 |
flute.damping | 0.35 | 0 – 1 | 管の損失。低ければフルート、高ければオカリナや瓶で、オーバーブローしません。 |
flute.breath_noise | 0.15 | 0 – 1 | ジェットの乱流。フルートの持ち味です。尺八では高く、ティンホイッスルでは低く。 |
フルートの軸になる物理量は、圧力でも位置でもなく「2 つの時間の比」です。ジェットが歌口を渡る時間を、管が 1 往復する時間で割った比が、管の音域を決める要因になります。
plucked-string:弦がかすめる駒
| フィールド | 構造体の既定値 | 範囲 | 意味 |
|---|---|---|---|
plucked_string.pick_position | 0.2 | 0 – 0.5 | 撥弦位置を周期に対する比率で。そこに節を持つ倍音が励振側の櫛型フィルターで抜かれます。0 で櫛は無し。 |
plucked_string.buzz | 0.0 | 0 – 1 | 湾曲した駒が戻る波をどれだけ制限し、上の倍音へ撒き散らすか。0 はきれいに終端されたハープや箏、上げていくとシタールのジャワリや三味線のサワリの、きらめくびびりになります。 |
plucked_string.brightness | 0.7 | 0 – 1 | ループローパスの開き具合。基音に対して上の倍音がどれだけゆっくり減衰するか。 |
plucked_string.decay_s | 4.0 | 0.05 – 60 | A4 における弦の t60。 |
plucked_string.decay_stretch | 0.5 | 0 – 1 | 低音弦がどれだけ長く鳴るか。t60 が「2 の(stretch × A4 からのオクターブ数)乗」でスケールします。 |
plucked_string.release_damp_s | 0.12 | 0.01 – 10 | ノートオフ時に適用される減衰 t60。指や掌が弦に戻って触れる瞬間にあたります。 |
このエンジンが素の撥弦ループと別に存在する理由は、まるごと buzz にあります。湾曲した駒は弦を一点で終端しません。弦は駒をかすめ続け、かすめるたびにエネルギーが倍音列の上へ投げ返されるので、音はなめらかに減衰するのではなく鳴っている間ずっときらめき続けます。
vocal:音源と 5 つのフォルマント
| フィールド | 構造体の既定値 | 範囲 | 意味 |
|---|---|---|---|
vocal.vowel | 0 | 0 – 4 | /a/、/e/、/i/、/o/、/u/。フォルマントテーブルを選びます。 |
vocal.brightness | 0.5 | 0 – 1 | 声門音源を傾け、上側のフォルマントを開きます。 |
vocal.breath_noise | 0.1 | 0 – 1 | 音源に混ぜる気息成分。0 は締まった声、上げるほど息っぽくなります。 |
vocal.vibrato_rate_hz | 5.5 | 0.1 – 12 | 歌手自身のビブラート速度。ノートオンで読まれます。 |
vocal.vibrato_depth | 0.3 | 0 – 1 | ビブラート量。0 なら LFO 自体が省かれます。 |
これは導波路ではありません。 ソースフィルターモデルであり、声門音源(1 次のチルトで整形された鋸歯波に気息成分を足したもの)を、母音に合わせた 5 つの共振バンドパスに通しています。ループが無いので反射するものも無く、信号経路は完全にフィードフォワードです。音源は PolyBLEP で帯域制限したのこぎり波なので、高い音でもオシレーターでエイリアシングは起きません。
下のデモは、フォルマントのバンドがスペクトルに何をするかを示すために、パッドを別物の母音フィルターに通します。vocal エンジンそのものではありません。
free-reed:スロットを抜ける舌
| フィールド | 構造体の既定値 | 範囲 | 意味 |
|---|---|---|---|
free_reed.breath_pressure | 0.7 | 0 – 1 | 蛇腹の圧力で、ダイナミクスと駆動力を決めます。 |
free_reed.reed_stiffness | 0.5 | 0 – 1 | 舌の非線形性の非対称さ。柔らかいほど丸く、硬いほどバジーに。 |
free_reed.detune | 0.3 | 0 – 1 | 1 音に配された 2 枚の舌のうなり、いわゆるミュゼット。0 で 1 枚に戻ります。 |
free_reed.brightness | 0.6 | 0 – 1 | リードプレートがどれだけ高域を放射するか。下端は穏やかなリードオルガン、上端はバジーなハーモニカ。 |
free_reed.slot_duty | 0.0 | 0 – 0.9 | 舌の往路がスロットを開けている時間の割合。実測リファレンスが共通して持つ第 7 倍音付近のヌルは、これが置きます。0 では単純な整形鋸歯波の音源が使われます。 |
free_reed.radiation | 1.0 | 0 – 1 | プレートが自由な単極子(あらゆる方向へ等しく空気を押し出す小さな音源)にどれだけ近いか。0 は流量そのもの、1 はその時間微分を放射します。ハルモニウムは 1、手で包んだハーモニカは 0 で実測されます。 |
こちらも導波路ではありません。 フリーリードの音高は連成する気柱ではなく舌そのものから来るので、遅延線も往復もありません。アコーディオンが蛇腹の加減によらず同じ音高で鳴り、フルートは強く吹くとオクターブ跳びます。その違いは、まさにここです。
撥弦系のもう 2 つのモデル
karplus-strong:素の撥弦ループ
| フィールド | 構造体の既定値 | 範囲 | 意味 |
|---|---|---|---|
ks.pick_position | 0.18 | 0 – 0.5 | 撥弦位置を周期に対する比率で。 |
ks.decay_s | 3.0 | 0.05 – 60 | A4 における弦の t60。 |
ks.decay_stretch | 0.5 | 0 – 1 | 低音弦がどれだけ長く鳴るか。 |
ks.mute_harmonic | 0.0 | 0 – 16 | ハンドミュート。固定周波数ではなく、その音自身の基音の何倍かで指定します。掌は音高によらず同じ倍音のところに切れ目を作るからです。2 前後で詰まった音、6 で軽いパームミュート、0 で開放。 |
ks.exc_brightness | 0.85 | 0 – 1 | 最大ベロシティにおける励振ローパスの開き具合。 |
ks.release_damp_s | 0.08 | 0.01 – 10 | ノートオフ時の減衰 t60。 |
きれいに終端された撥弦弦で、かなり多くの GM プログラム(ギター、ベース、ハープ)がここにフォールバックします。plucked-string との違いは駒です。こちらは反射するだけなので、音はきらめかずになめらかに減衰します。このエンジンにはより凝った挙動もいくつか入っていますが既定ではオフで、フレットスラップ、第 2 偏波、2 平面間の駒結合などがそれにあたります。
harpsichord:爪と、3 組の弦
| フィールド | 構造体の既定値 | 範囲 | 意味 |
|---|---|---|---|
harpsichord.pluck_8a | 0.14 | 0 – 0.5 | 第 1 の 8′ 弦列を弾く位置を弦長比で。 |
harpsichord.pluck_8b | 0.22 | 0 – 0.5 | 第 2 の 8′ 弦列。弾く位置が違うことが、2 つのレジストレーションを「音量違い」ではなく別の音にしています。 |
harpsichord.pluck_4 | 0.11 | 0 – 0.5 | 4′ のオクターブ弦列。 |
harpsichord.plectrum_edge | 0.8 | 0 – 1 | 爪が離れる瞬間の鋭さ。 |
harpsichord.velocity_range_db | 5.0 | 0 – 24 | 打鍵速度で得られるダイナミックレンジの幅。実物は 3〜6 dB 程度で、しかも単調ですらありません。ある速度を超えると爪が早く外れるため、音はかえって小さくなります。 |
harpsichord.rear_coupling | 0.35 | 0 – 1 | 駒の向こう側にあるダンプされない短い区間がどれだけ出力に届くか。この楽器の非調和なきらめきの出どころで、発音部の倍音自体は数セント以内で調和的なままです。 |
レジストレーションは別々の弦列です。2 組の 8′ ユニゾンと 1 組の 4′ オクターブは、3 つの周期を持つ 3 本の独立した遅延線であって、1 本の弦にミックスつまみが付いたものではありません。
A/B する前にゲインを下げてください
エンジン間で生の出力レベルはそろっていないため、harpsichord が隣の音源より大きく聞こえることがあります。ほかのエンジンと並べる前にパッチの gain を下げ、同じレベルで聴き比べてください。
聴き比べる
下のデモは、サンプルバンクなしで鳴る 16 個のエンジンすべてで同じ 1 音を鳴らします。このページの導波路モデルと、それ以外のエンジンの両方です。何より聴いてほしいのは、立ち上がりです。モデルと波形の差が最も大きく出るのはそこです。減算方式は大きく始まってから削られ、撥弦ループはバーストで始まって即座にエネルギーを失いはじめ、擦弦は数周期かけて食いついてから音がロックし、吹奏系は圧力を立ち上げて発音の立ち上がりにチフを伴います。カットオフは共通フィルターに効くので、これらのボイスで同じ意味を持ちます。エンジン間の生のレベルはそろっていないため、音色を判断する前に gain を合わせてください。
この一族の境界
上のデモで鳴る導波路以外のエンジンのうち、次の 3 つはこの一族に近いので触れておきます。説明はここではなく 内蔵シンセサイザー 側にあります。modal は同時に叩かれる同調共振器のバンクで、モードが既知でどれも伝搬しない棒や鐘にはこちらが正しいモデルです。percussion は理想的な円形の太鼓の膜の振動モード(1 つの音高の整数倍にはなりません)にフィルタードノイズを重ねたもので、シェーカーやギロには確率的な粒子音源も加わります。ノイズ層を持つモーダルモデルであって、ループではありません。additive は物理モデルではなく、ドローバーの倍音を足し合わせる加算合成です。
ただしパーカッションエンジンには、ここで触れておきたいフィールドが 1 組あります。古いビルドに合わせて追い込んだキットは、調整し直しが必要になるからです。
| フィールド | 構造体の既定値 | 範囲 | 意味 |
|---|---|---|---|
percussion.wire_threshold | 0.1 | 0 – 1 | スナッピーが接触するまでにヘッドがどれだけ振れる必要があるか。基準は絶対レベルではなく、そのピースで最大ベロシティの打撃が到達する振幅に対する比率です。0 は常に接触、1 は決して接触しない。だから区間全体がどのピースでも同じ意味を持ちます。打撃の強さも同じ比較に入ります。ストレイナーという機構そのものが持つ非線形性であり、弱い打撃は最後までしきい値を下回ったままでいられます。 |
percussion.wire_decay_ms | 0.0 | 0 – 2000 | スナッピー自体の減衰。ヘッドが先に止まってもびびりだけが残ります。スネアのテールがヘッドの音色より後まで広帯域なのは、これが理由です。0 では単なるゲートとして振る舞い、ストレイナーを持たないピースはすべてこの値です。 |
そのほかのエンジンキー
上の音作りのフィールドに加えて、各エンジンは engineParams のキーをさらに持っています。すべて synthEngineParamInfo(engineMode) で一覧できます。範囲と単位はエンジン側のもので、既定値の列はベースプリセットの値です。既定値でその機能がオフになっているキーは、値を上げるまで音を変えません。ゲート付きのキーは、activeWhen に挙がっているキーの条件が成り立つあいだだけ音に届きます。
velocityExponent(0 – 4)は、ノートオン時のレベルカーブ (velocity / 127)^exponent です。bowed-string、reed、brass、flute、plucked-string、karplus-strong、free-reed、vocal、modal、subtractive、fm の各エンジンにあるキーです。
| エンジン | キー | 範囲 | 既定値 | 内容 |
|---|---|---|---|---|
reed | bellRadiationHz | 0 – 8000 | 0 | ベル放射のコーナー。出力側だけに掛かり、ループと音程は音作りのままです。0 でオフ。 |
brass、flute、free-reed | onsetBreathOvershootDb | 0 – 8 | brass は 6.89、ほかは 0 | ベロシティ 127 のとき、発音の際に口の圧力(free-reed ではベローズの圧力)が保持レベルを超える量。そのあと保持レベルに落ち着きます。0 でオフ。 |
onsetBreathSettleMs | 1 – 500 | brass は 134、ほかは 40 | オーバーシュートが保持レベルに落ち着くまでの時間(約 95%)。オーバーシュートでゲートされます。 | |
onsetBreathOvershootVelDb | -3 – 6 | brass は 1.35、ほかは 0 | オーバーシュートのベロシティ依存。オーバーシュートでゲートされます。 | |
free-reed | onsetBreathOvershootKeyDb | -6 – 6 | 0 | オーバーシュートの鍵盤位置依存。オーバーシュートでゲートされます。 |
bowed-string | hyperbolicFriction | オン/オフ | false | 接合部を、弦の特性線に対して解く双曲線の摩擦則に切り替えます。弓の軸はニュートンとメートル毎秒で読まれます。 |
stringTensionN | 1 – 500 N | 60 | 弦の張力。stringLengthM と合わせて特性インピーダンスが決まります。hyperbolicFriction でゲートされます。 | |
stringLengthM | 0.1 – 2 m | 0.325 | 弦の長さ。hyperbolicFriction でゲートされます。 | |
forceRatio | 0 – 12 | 0 | 弓の力を、インピーダンスと弓速の積に対する倍率で指定します。シェレングの窓が描かれる動作点です。0 でオフ。hyperbolicFriction でゲートされます。 | |
bowWidthM | 0 – 0.05 m | 0 | 弦に沿った弓毛の接触幅。0 は点の弓です。 | |
bowPositionFf | 0 – 0.5 | 0 | ベロシティ 127 での弓の位置。強い弓ほど駒寄りに動き、bowPosition は最弱音の位置になります。0 でオフ。 | |
bowPositionSpread | 0 – 0.25 | 0 | 音ごとの接触点のばらつきの半幅。弓が節にする倍音が音ごとに変わります。 | |
sectionSpreadCents | 0 – 50 cents | 0 | セクションのビブラートの深さ。複数の奏者がそれぞれ独立にビブラートをかけます。0 でオフ。 | |
sectionRateHz | 0.5 – 12 Hz | 5 | セクションのビブラートの速さ。sectionSpreadCents でゲートされます。 | |
stringLossHarmonic | 0 – 1000 | 0 | Hz ではなく倍音次数に固定された往復損失のコーナー。A3 での値で指定します。0 でオフ。 | |
stringLossPerOctave | 0 – 4 | 0 | そのコーナーがオクターブごとに動く量。stringLossHarmonic でゲートされます。 | |
corpusSeries | 0 – 4 | 0 | 駒の信号を、並列バンクの代わりに直列で通すバイオリン族の胴の種類。0 は並列バンクのままです。body: 'violin' かつ bodyMix > 0 でゲートされます。 | |
flute | jetDrive | オン/オフ | false | 3 次のジェットテーブルを、ラビウムでの流れの分岐を音源とする方式に置き換えます。息が強まるほど対流の遅れが短くなります。 |
jetOffset | 0 – 2 | 0 | ラビウムからのジェット中心線のずれ(ジェット半幅単位)。偶数次倍音を鳴らす非対称です。jetDrive でゲートされます。 | |
jetReceptivityWindow | 0 – 0.7 | 0 | ジェットが戻りの流れを読むときの平均窓の半幅。jetDrive でゲートされます。 | |
jetCycleMean | オン/オフ | false | ジェットのたわみをゼロ平均にします。jetDrive でゲートされます。 | |
jetDeflectionLimit | 0 – 8 | 0 | ラビウムでの振れの上限(ジェット半幅単位)。0 で無制限。jetDrive と jetCycleMean でゲートされます。 | |
jetCentringPerOctave | 0 – 4 | 0 | 第 1 レジスターより上でオクターブごとに取り除く、ジェットの静止時オフセットの割合。オーバーブローしたレジスターは偶数次倍音を失います。 | |
vortexLoss | 0 – 400 | 0 | 口元の渦損失。ジェットが振幅を抑えないとき、発振を抑えるのはこの項です。 | |
latticeCutoffHz | 0 – 20000 Hz | 0 | 音孔格子のカットオフ。どの音でも同じです。0 でオフ。 | |
breathRadiation | 0 – 1 | 0 | 口元の乱流の直接放射。基音の下にある広帯域のフロアを担います。 | |
loopPhaseServo | オン/オフ | false | 非線形音源の位相が音程を引っ張らないようにします。jetDrive がオフのときにゲートされます。 | |
free-reed | musetteFlat | オン/オフ | false | ミュゼットの相方が高い分だけ低い 3 本目の舌を足し、トレモロが正しい音程の舌をまたぐようにします。detune でゲートされます。 |
musettePartnerLevel | 0 – 1 | 1 | 正しい音程の舌に対する各ミュゼットの相方のレベル。detune でゲートされます。 | |
musetteTaper | 0 – 1 | 0 | ミュゼットのずれが音域に沿ってどう変わるか。0 はセント数を保ち、1 はうなりの Hz を保ちます。detune でゲートされます。 | |
slotSwing | 0 – 16 | 0 | A4 での舌の振れ(プレート厚単位)。1/f0 に比例して変わります。slotDuty でゲートされます。 | |
radiationKeytrack | 0 – 1 | 0 | モノポールの +6 dB/oct のうち、音域全体で保つ割合。slotDuty と radiation でゲートされます。 | |
karplus-strong | sympathetic | オン/オフ | true | 共鳴して鳴る開放弦のハロー。 |
haloDampS | 0 – 10 s | 0 | パートの全キーとサステインペダルが上がったあとの、ハローの減衰 t60。ハローバンク自身の響きの長さより短い範囲でだけ音が変わり、それ以上ではハローは減衰しないままです。sympathetic でゲートされます。 | |
bodyAirHz | 0 – 400 Hz | 0 | ギターボディの空気モードの周波数。0 ならバンクの 100 Hz のまま。body: 'guitar' かつ bodyMix > 0 でゲートされます。 | |
bodyAirT60S | 0 – 2 s | 0.1 | ギターボディの空気モードの t60。同じゲート。 | |
bodyKnock | 0 – 4 | 1.6 | 撥弦がボディの空気モードを叩く量。撥弦自身の基音に対する比です。0 は叩かない。同じゲート。 | |
karplus-strong、plucked-string | pickPositionPerOctave | 0 – 4 | 0 | 音高が 1 オクターブ上がるごとにピック位置が上がるオクターブ数。A2 での値で指定し、弦の中点で頭打ちです。pickPosition でゲートされます。 |
excBrightnessPerOctave | 0 – 4 | 0 | 音高が 1 オクターブ上がるごとに励振ローパスのコーナーが上がるオクターブ数。0 ならコーナーは Hz のままです。 | |
plucked-string | hfDecayS | 0 – 60 s | 0 | 4 kHz での部分音の t60。損失フィルターはこれと decayS から解かれます。0 でオフ。 |
midDecayS | 0 – 60 s | 0 | 任意の 1 kHz での t60。hfDecayS でゲートされます。 | |
inharmonicityB | 0 – 0.01 | 0 | 非調和係数 B。どの音でも同じです。0 は調和的な弦。 | |
pickNoise | 0 – 1 | 0 | ノートオン時のピックやプレクトラムの接触クリック。 | |
harpsichord | rippleLossShare | 0 – 0.4 | 0 | 損失コムの深さ。ループ 1 周あたりの損失に対する割合で、基音の t60 は保たれます。 |
rippleRatio | 0.05 – 0.95 | 0.5 | コムの長さを、ループ周期に対する割合で指定します。rippleLossShare でゲートされます。 | |
polCoupling | 0 – 1 | 0 | 弦の第 2 の振動面との結合。うなりと 2 段の減衰として聞こえます。0 なら第 2 面を飛ばします。 | |
polDetuneCents | -50 – 50 cents | 1 | 第 2 面のずれ。polCoupling でゲートされます。 | |
polT60Ratio | 0.05 – 2 | 0.55 | 第 1 面の t60 に対する第 2 面の t60 の割合。polCoupling でゲートされます。 | |
modal | malletMs | 0 – 50 ms | 0 | 最大ベロシティでのマレットの接触時間。0 でオフ。 |
malletVelExp | 0 – 1 | 0 | 強く叩くほど接触が短くなる度合い。malletMs * velocity^-exponent。malletMs でゲートされます。 | |
contact | 0 – 16 | 0 | マレットの直接接触放射(エンベロープの外にあるパルス)のレベル。0 でオフ。 | |
contactMs | 0.02 – 20 ms | 0.5 | そのパルスの接触時間。contact でゲートされます。 | |
pipe-organ | pipeDetuneCents | 0 – 30 cents | 4 | C4 以下での管ごとの調律誤差。ランクと音ごとに固定で、そこから残るランク間の遅いうなりがコーラスです。 |
loopPhaseServo | オン/オフ | true | 各ランクのジェットの位相が音程を引っ張らないようにします。 | |
windRegulated | オン/オフ | true | 調圧された風。サグは需要が増えた瞬間の落ち込みだけで、一定の消費では音程とレベルが保たれます。 | |
vocal | sectionSpreadCents | 0 – 50 cents | 0 | セクションの歌い手のビブラートの深さ。ソースフィルター連鎖の外側で掛かります。0 でオフ。 |
sectionRateHz | 0.5 – 12 Hz | 5 | セクションのビブラートの速さ。sectionSpreadCents でゲートされます。 |
synthEngineParamInfo(...).unit は、none、cents、Hz、ratio、ms、s、count、m、dB、N(ニュートン。stringTensionN 用)、mm、dBPerOct のいずれかです。
コードから触る
上に挙げた深い階層のフィールドは、どのバインディングからも engineParams で設定できます。 表ではエンジン内部の名前で書いています。パッチが受け取るキーはセクションのフィールド名を lowerCamelCase にしたもの(bowForce、ranks2.level。harpsichord.pluck_8a は pluck8a)で、正確なキーと範囲・単位・既定値は synthEngineParamInfo(engineMode) で取得できます。
したがって、実際にできることは 4 つです。
プリセットを選び、その物理的な音づくりをまるごと受け取る。 物理モデル系のプリセットは深いフィールドが設定済みで出荷されており、それを使うには名前でプリセットを選びます。カタログはハードコードせず、ランタイムから取得してください。
const names = synthPresetNames();
// 'violin', 'cello', 'clarinet', 'alto-sax', 'trumpet', 'french-horn',
// 'concert-flute', 'shakuhachi', 'koto', 'sitar', 'accordion', 'harmonica',
// 'choir-aah', 'acoustic-piano', 'church-organ', 'harpsichord', ...
const patch = synthPresetPatch('cello');
// 返るのはラッパー層だけ。patch.engineMode は 'bowed-string' になり、
// 弓そのものの音づくりは返らないので、上書きするには engineParams を使います。
const audio = project.bounceWithSynthInstrument(
{ preset: 'cello', cutoffHz: 3600, ampAttackMs: 40 },
{ totalFrames: 48000, numChannels: 2 },
);names = sonare.synth_preset_names()
patch = sonare.synth_preset_patch("clarinet")
audio = project.bounce_with_synth_instrument(
sonare.SynthPatch(preset="clarinet", cutoff_hz=3600.0),
total_frames=48000,
num_channels=2,
)エンジン固有のフィールドを上書きする。 パッチの engineParams(Python では engine_params)に入れます。指定しなかったキーはプリセットの値を保ちます。未知のキー、別のエンジンのキー、有限でない値、整数フィールドへの小数、範囲外の値は、キー名つきで拒否されます。値はプリセットごとに較正されているので、1〜2 個ずつ変えて聴いてください。
const audio = project.bounceWithSynthInstrument(
{ preset: 'cello', engineParams: { bowForce: 0.7, bowPosition: 0.1 } },
{ totalFrames: 48000, numChannels: 2 },
);
const keys = synthEngineParamInfo('bowed-string'); // name, min, max, default, unitaudio = project.bounce_with_synth_instrument(
sonare.SynthPatch(preset="cello", engine_params={"bowForce": 0.7, "bowPosition": 0.1}),
total_frames=48000,
num_channels=2,
)
keys = sonare.synth_engine_param_info("bowed-string") # name, min, max, default, unitPython でもキーは lowerCamelCase のままです。擦弦の一部のフィールドはゲートされています。stribeck は elastoPlastic がオンのときだけ、corpusScale と corpusTiltHz は body: 'violin' かつ bodyMix > 0 のときだけボイスに届きます。この条件がエントリの activeWhen です(Python の SynthParamInfo でも同じ camelCase のキーです)。詳しくはゲートされるフィールドを参照してください。
その上から共通層を上書きする。 ラッパーにあるもの(フィルターのカットオフとレゾナンス、両方のエンベロープ、LFO、グライド、ボディミックス、ステレオスプレッド、ゲイン)はプリセットが選んだエンジンの上に乗ります。percussion エンジンだけは例外で、このうち効くのは gain、busDrive、polyphony だけです。同じフィールドは resolveInstrumentAutomationId で連続オートメーションの対象としても解決できます。そこで動かせないのは構造にあたるもので、プリセット、エンジンモード、波形、フィルターモデル、同時発音数、モッドルーティングは平滑化されるのではなく拒否されます。アンプとフィルターのエンベロープ時間については エンベロープとモジュレーション を参照してください。パッチの gain は有限で [0, 4] の範囲でなければならず、範囲外の値は名前を挙げて拒否されます。
励振軸を通じて、励振部を演奏する。 発音中に物理モデルを動かせる経路はこれです。静的な engineParams のフィールドに加えて、エンジンは force・position・brightness・morph という 4 つの抽象的な軸を定義しており、コントローラーの操作やモッドマトリクスのルートが発音中にこれらを動かせます。どの軸を読むかは各エンジンが宣言します。
| エンジンモード | 読む軸 |
|---|---|
bowed-string | force、position |
pipe-organ、reed、brass、flute、free-reed | force、brightness |
vocal | brightness |
additive | morph(発音中ではなくパッチ単位) |
piano、plucked-string、karplus-strong、harpsichord、percussion、subtractive、fm、modal、sample | なし |
打弦・撥弦のボイスが発音中の励振軸を宣言しないのは、励振部がワンショットだからです。ノート開始後に励振ルートを受け取る対象がありません。
軸を動かす方法は 2 つあります。ひとつは、コントローラープロファイル。デバイスの操作を軸へ割り当てるもので、既定の gm プロファイルは CC2(ブレス)を force へ、CC74 をそのエンジンが読むほうの brightness または position へ送ります。選択と拡張はリアルタイムエンジンの setControllerProfile と bindController で行います。もうひとつは、モッドマトリクスのルーティング。パッチの内側から同じことをします。breath、aftertouch、expressionCc、pitchBend のいずれかを excitationForce、excitationPosition、excitationBrightness、spectrumMorph へ結べば、パッチと一緒に持ち運ばれ、バインドし直す必要もありません。
聴き比べる前にもうひとつ。モードだけを指定したパッチは、そのエンジンの基本プリセットで鳴ります(fm は e-piano、modal はベル、percussion は GM ドラムキット)。バンクをバインドするまで無音なのは sample だけです。詳しくは 内蔵シンセサイザー を参照してください。
関連: 内蔵シンセサイザー · 音源方式 · GM / GS フォールバックバンク