のみながら聞くDSPの話 NTS-1 初級編
2020.02.12@二水
誰?
斉田です。@kazbo です。
電子楽器を作って売ったり、フリーランスでソフトやハードを作っています。
たまに二水で話したりします。前回は1年前に�「シンセを作ってる人たちの生々しい話を聞く」で話をしました。
よく骨折している気がします
誰?
DSP簡単かも?!という話をしに来ました。
一応、専門だったかもしれない。はるか昔、2004年とか。
NTS-1を買ったはいいけど・・・
最初のとっかかりどうしよう?中のサンプル難しい・・�という人向けの話をします。
DSPて何?
色々な物事を数字で表して、アレコレいじって、色々な物事に戻す!
社会の色々なところで使われている技術�- プロジェクターに画像が出るのもDSP�- 携帯電話もDSP
いろいろ
(数字)
いろいろ
(数字)
アレコレ
音だと?
音を数字で表して、アレコレいじって、音に戻す!�logue-sdkを使ってやるのはこれです。
音
(数字)
音
(数字)
アレコレ
音だと?
音の波形をPCで見るとこんな風になってる。これが数字で表された姿。
もっと拡大すると?
一定の時間ごとの音の大きさが記録されている。これが「サンプル」。�棒と丸で表しがち。
つまり?
「サンプル」をアレコレして「サンプル」にするのが、音のDSP
アレコレ
いじり方いろいろ
サンプルをいじるけど、直接ではない方式
max/mspやpdなど �出来上がっているモジュール�を組み合わせる方式。もちろんこれもDSP
いじり方いろいろ
直接いじる方式
サンプル「そのもの」をいじる。logue-sdkはこちら。�VSTやAUなどのソフトシンセもそう。割と硬派。�こちらの方が細かく、いろいろなことができる。
が、色々知っておく必要がある。今日はここの入口の話をします。
NTS-1 何からはじめれば?
最初はエフェクトを作るのがオススメ。�簡単なところから入れる。��オシレーターは結構難しい(やることが多い)�- 完全な無の状態から、音がある状態にしなければいけない�- ノート番号ごとに、別の波形をつくらないといけない�- 波形をうまく作らないと変な感じになったりする(エイリアシングとか)��ということで、今日はエフェクトを例にして、話をします。
今日話す内容のサンプルソースコード
今日話す内容のサンプルソースコード
重要なのはここだ!詳しくはせんとれさん(?)
void REVFX_PROCESS(float *xn, uint32_t frames)
その1 何もしない
入ってきた音をそのまま出す!
その1 何もしない
なぜ「何もしないエフェクト」が大事なのか?
その1 何もしない
何もしない の 「処理」
出力 = 入力� *l_input = *l_input; // L CHのサンプルはL CHのサンプルそのまま�
何もしない
その2 ボリュームを変える
出力 = 入力 x ノブの値(0.0 ~ 1.0)
*l_input = *l_input * volume; // L CHのサンプルはL CHにボリュームを掛けたもの
ノブの値を掛け算
ボリュームの応用でエフェクトっぽく!
雑なクリッパー 掛け算を大きな値にして、1より大きくなったら1にする
*l_input = *l_input * volume; // L CHのサンプルはL CHにボリュームを掛けたもの(デカい)
// デカい場合は+-1.0にする
if (*l_input > 1.0) {
*l_input = 1.0;
} else if (*l_input < -1.0) {
*l_input = -1.0;
}
ノブの値を掛け算�大きすぎたら小さくする
その3 フィルター
1個のサンプルを大きくしたり小さくしたりすると、�エフェクトっぽいことができるのはわかった。
例えばフィルター、どうやるの?
その3 フィルター
フィルターって? �高い音だけ削ったり、低い音だけ削ったりするエフェクト。
サンプルが次々とやってくる。その大きさの変化のうち、素早いものを無視、ゆっくりした変化だけを取り出せば、高い音が消える。これがローパスフィルター。
その3 フィルター
どうやって? �直観的に簡単なのは、平均をとること。�全体がなめらかになる = 素早い変化が消える。�株とかFXのチャートとかで見たことあるかも。
その3 フィルター
平均をとるプログラムを書いて、NTS-1で動かしてみる�こんな感じ�const float l_filtered = movingAverage(*l_input, lch_buffer, num_samples_to_use);
今までに来たサンプルと並べて、平均をとる
メモリーに覚えておく
逆にハイパスは?
素早い変化だけを取り出せばOK�前のサンプルと、今のサンプルの差=変化
逆にハイパスは?
元の信号から、ローパスフィルタをかけた信号を引き算してもよい。
*l_input = *l_input - l_filtered; // LCH ローパスフィルタしたものを引く = 高い信号が残る
(本当は位相がズレてるので思ったようにはならないが、まあまあそれっぽくなる)
ここまでのまとめ
入ってきた信号をあれこれいじると、音が変わる。つまりエフェクト。
過去のサンプルを使うと、「変化」を利用したエフェクトが作れる。
ここまでのまとめ
ここまで見てきた感じのDSPの処理のやり方を、FIRフィルターといいます。�入ってきたサンプル、それを遅らせたサンプルを足したり掛けたりします。
ここまでのまとめ
他にFIRでできるもの
サンプリングリバーブ など。
別の方式
IIRというのもある。入ってきた信号、それを遅らせた信号だけでなく、�出力も使う。
IIRの簡単な例
aが大きい=>最新の信号の比率が高くなって、サンプルそのものに近づく�aが小さい=>過去の信号の比率が高くなって、変化がおさえられる
IIRの簡単な例
aが大きい=>最新の信号の比率が高くなって、サンプルそのものに近づく�aが小さい=>過去の信号の比率が高くなって、変化がおさえられる
つまり、aの大きさで特性が変わる、ローパスフィルタ!
IIRの簡単な例
logue-sdkでやるとこんな感じ
const float l_filtered = a * (*l_input) + (1-a) * lch_buffer;
logue-sdkのサンプル biquad
IIRの一種で、こんな形。(他もある)�aとbを色々な値にすることで、�ローパス、ハイパス、バンドパスなど�色々作れる。便利。
logue-sdkでは、�APIが最初から用意されてる。�中でやってることは、これまで説明�したような感じ。
サンプルコードが読めるかも?
DSP難しい?
-> 結局はサンプルを掛けたり足したり、貯めたりしているだけ。�ここまで話したことだけでも、工夫次第でいろいろできる。
今日話さなかったこと
難し目のこと
など、ガチな数式が出てくるもの
今日話さなかったこと
知っていればできることは増えるが、まずできることはたくさんある。
とりあえず、音を出そう!
参考になるかもしれない情報
- music dsp(コピペできるものも多数) https://www.musicdsp.org/en/latest/
- やる夫で学ぶディジタル信号処理(かなりガチ寄り) http://www.ic.is.tohoku.ac.jp/~swk/lecture/yaruodsp/main.html
以上です。
ありがとうございました!
質問などあればどうぞ!!