u-he UHM言語 学習01 概要と基本波形
UHM言語は、ウェーブテーブル記述用のu-he社独自スクリプト言語で、おそらく2018年に発表されたスクリプト。 現在利用できるソフトシンセはu-he社のHiveのみだが、将来リリースされるZebra3でも利用できるようになる。そこでUHMの基本を少し学習しつつ、可能性を探れたらと思っている。
そもそもウェーブテーブルはwavなどのPCMサンプリングが基本で、これを言語的に記述するという発想が今までほとんどなかったと思う。 周期的な波であれば数学的な波形の記述は可能だが、あまり利用しやすい有用なものになりにくい気がする。 実際PCMで困ることがほとんどなかったというのが、言語化されなかった理由だと思う。 他には数学的な知識が必須となるため、開発者ならともかく、一般的には不要というか、むしろマイナスかもしれない。
ただFM音源は、数学的な記述がしやすく、わりと有効かもしれない。 少しUHMを触ってみると、やはりFMとは相性がよいと思えた。 数式の方が本質を言い当てている場合は、言語であるUHMは簡潔に表現できて応用しやすい。 そして言語ならではの柔軟性に期待したい。 現状において、何ができるのか未知数なところが魅力なのかもしれない。
またPCMデータは音質向上のたびに巨大になり、データ容量問題になっている。 UHMはテキストなので、そのような心配とは無縁。 個人的にシンセサイザーは音の抽象表現だと思っているので、リアルな音を追求するよりも、 余計な部分をそぎ落とし本質をむき出しにしたい。 そういう意味でもUHMは合っていると感じている。
さらに年内にリリースされるであろうu-he社のZebralette3、そして、おそらく2024年中にリリースされるであろうZebra3では、UHMだけでなく画像のベクター形式であるSVGにも変換可能となる。これが意味するものも興味深い。 いよいよ音と図形の本格的な行き来が可能になるような気がしている。
Urs Heckmann
新しいプラグイン規格であるCLAPの開発者でもあり、発表される開発内容には先見の明を感じることが多い。 その内容はユーザーから望まれているわけでないのに、ガンガン未知の方向に突き進む印象で、ある意味ユーザーは戸惑っているんじゃないかな? 実際、このUHMにしても今後出るSVG対応にしても、市場から出た要求ではないと思うし、それによって明らかなメリットが提示されているわけでもない。ただし向かう方向としては正しいという気がする。 個人的にZebraを所有しているが、始めはとっつきにくく難解であるが、慣れてくとその設計思想の素晴らしさに気づくという感じ。 他と大きく違う視点がある。マーケティングとか関係なく、もっと未来を見ているのは明らか。 世の中いろんなタイプの天才がいるが、Ursさんは、コンセプトと、それを形にする両面で明らかな天才。 たぶんユーザーの理解がいつも追いついていないと思う。
UHMで作るウェーブテーブルはオシレータに徹する
UHMで、どこまで作りこむかということを考えてみると、やはりオシレータとして使いやすい波形でありたい。つまりエンベロープやフィルターは後からかけることが多いので、それらの加工を前提とした波形ということ。ただし減衰するだけの打楽器においては、最終的な音までUHMで作りこむのもありだと思う。
ウェーブテーブルならではの活用
所有しているZebra Legacyは、ウェーブテーブルも利用できるのだが、その効果的な使い方を知らないので、ウェーブテーブルを駆使するような使い方をしたことがなかった。
UHMの学習では、ウェーブテーブルの効果的な使い方も考えてみたいと思っている。 古くはPPG、最近ではSerumやVitalなどの使い方を探ることで、ウェーブテーブルの活用方法が見えてくるかもしれない。
UHMで作るウェーブテーブルの構造
ここから具体的にUHMについて書いていく。ウェーブテーブルと呼ばれているフォーマットの一般的な構造は、1周期分の波形を1フレームとし、それらを複数束ねたものとなっている。機種ごとに仕様が違うので、基本的に互換性はない。
UHMでは1周期分が2048サンプルで、最大256フレームのセットが可能。 これは最近流行りのソフトシンセSerum、Vitalと同等のようだ。
ちなみにZebra Legacyは1周期128サンプルで、16フレームとかなり小さい。リアルな音を求める場合は少し厳しいように思う。 初期のPPG Waveなどは1周期64サンプル程度だったようだ。
このウェーブテーブルをどのように使うかというと、様々な方法が考えられるが、短い時間でフレームを切り替えていくことにより、変化する音を作り出すことができる。 アコースティック楽器などではアタックに癖がある場合が多いので、ウェーブテーブルによってそれらしく再現することが可能になる。とくに初期のころはメモリが高価だったため、メモリの有効利用としては、よい方法だったと思う。
またその構造からアコースティック楽器の再現から離れ、現実離れした音を作ることも可能。 現在ではメモリの有効利用というよりは、その独自の音作りなどが進化し、EDMなどで多用されるようになった。 フィルタなどでは難しい、過激に変化する音作りにウェーブテーブル方式は便利なのだろう。
UHM 公式ドキュメント
基本的にこのドキュメントとHive付属のプリセットで学習。
以下はエディタで書いたUHMファイルをHiveに読み込ませながら基本波形を生成してみた。UHMは拡張子を.uhmとするだけで中身は普通のtxtとなっている。エディタで保存すると、起動中のHiveに即反映されるので、動作チェックなどはストレスがない。
サイン波
まずは、基本的な波形を作ってみる。 数学的には以下のようになる。
y=sin(2pi*x)
uhmではxがphaseに置き換わり、1周期を0~1と遷移している。 注意点としてはラジアンで考えること。
Wave "sin(2*pi*phase)"
また以下のように書くと位相が180度ズレたサイン波になる。
Wave "sin(2*pi*phase+pi)"
さらに位相をずらしてコサイン波を作ってみる。
Wave "sin(2*pi*phase+0.5*pi)"
Spectrumコマンドを使って周波数領域で操作し倍音をコントロールできる。 下の式は基音を振幅1とし、サイン波を実現している。
Spectrum lowest=1 highest=1 "1"
空にすると-sinの音が鳴るのだが、実はエラー。 メッセージもちゃんと表示されるのでバグ出しに使える。
Wave ""
ノコギリ波
これも数学的な書き方だけど、周期関数ということは考える必要がないから、よりシンプルになる。 実際の波形はエッジがナイキスト周波数を意識したようないい感じになっているが、数式は理想形なので、Hiveの仕業。 ナイキスト周波数について何も考えなくてよい!
Wave "2*phase-1"
数学的には以下のようになる。
y=2x-1
反対向きのノコギリ波はこんな感じ。
Wave "1-2*phase"
教科書的だが、整数倍音の周波数のサイン波を合成してノコギリ波を作ってみる。いわゆる加算式。 振幅は倍音と同じ数で割って、小さくしていくことで、きれいなノコギリ波となる。 下は60倍音まで合成したノコギリ波。 コマンドオプションのlowest=1 highest=60が倍音に相当する。
倍音は最高で1023まで扱えるようだ。 例えばピアノの最低音であるA0の27.5Hzの1023倍音は28132.5Hz。つまり可聴域を完全に超えている。これだけあれば、低音でも倍音豊かな音を作り出すことが可能になる。
スクリプトは倍音ごとに整数を使いたかったのでindexを用いている。indexはWaveでは1周期のサンプル単位で0~2047となっているが、Spectrumでは倍音に対応している。 エッジの細かな波は計算上出るもので、Hiveの仕業ではない。 たったこれだけの式で面倒な内部処理を書けてしまうのはステキかもしれない。
Spectrum lowest=1 highest=60 "1 / index"
矩形波
矩形波はいろいろな書き方ができると思う。とりあえず以下のように書いてみた。 selectという条件文を使っている。 1周期をphaseは0~1と変化する。その0~0.5までがレベル1、それ以外がレベル-1となっている。
Wave "select((phase<=0.5),1,-1)"
加算合成で書く場合はSpectrumコマンドを使う。奇数倍音のサイン波を合成し、振幅は倍音と同じ数で割ってる。 以下のスクリプトは60倍音まで計算している。
Spectrum lowest=1 highest=60
"select((index % 2 != 0), 1 / index, 0)"
三角波
絶対値を使ってノコギリを無理やり三角にしている。そしてSpectrumコマンドを使ってDCノイズをカットし、上下を整えてみた。lowestとhighestは倍音を表し、0はDC直流成分となるので、そのレベルを0にしたという意味。
Wave "abs(2*phase-1)"
Spectrum lowest=0 highest=0 "0"
これも加算合成で生成してみる。奇数倍音を60倍音までの合成。 各倍音の振幅は2乗の逆数でプラスマイナスの符号が入れ替わり続ける。やや難解な式。 条件文は、真であれば1で、そうでなければ0となる。
Spectrum lowest=1 highest=60
"1/(index^2) * ((index % 2)==1) * (1-2*((index % 4)==3))"
ノイズ
ノイズのつくり方はいろいろあると思う。とりあえずランダムを使って、こんな感じにしてみた。 ランダムはおそらく0~1までの範囲でランダムな値が生成される。 三角波と同じようにDCノイズをカットして上下を整えている。
Wave "rand"
Spectrum lowest=0 highest=0 "0"
ノイズはウェーブテーブルとの相性があまりよくない。構造上どうしても周期性が出てしまうので、音程感がある。 ノイズはアタック音に混ぜるような使い方がよいと思った。
またウェーブテーブルのノイズは物理音源的な発想で利用できると思われる。
ファーストインプレッション
概要を理解してしまえば、後は数学的にいろいろ表現すればよいだけなので、かなりお手軽な波形生成スクリプトと言えるかも。 特に周期関数を真面目に作らなくても、自動で周期関数にしてくれるので、すごく気楽に作れる。 ただ、波形を数学的に考えられない人は手を出さないほうが良いかもしれない。時間領域、周波数領域、位相などの概念を理解していないと使いこなすことは不可能だと思う。
難点としてはu-heのHive付属uhmドキュメントが簡易的なので、いろいろ不明点が多いということ。 Hiveのプリセットを参考にすれば何とかなるかな? 上記波形を作るにあたっても、コマンドをひとつひとつ試しつつ、整理して理解したもので、何が起きているか理解するまで結構時間がかかってしまった。もう少し分かりやすいドキュメントは必須だと思った。
またZebra2、Zebraletteのオシレータの使い方とも酷似しているので、u-heの考え方に馴染んでないと、ちょっと戸惑うかもしれない。 コマンドオプションなどは同じワードでもコマンドによって解釈が違ったりするで。