1 of 38

のみながら聞くDSPの話 NTS-1 初級編

2020.02.12@二水

2 of 38

誰?

斉田です。@kazbo です。

電子楽器を作って売ったり、フリーランスでソフトやハードを作っています。

たまに二水で話したりします。前回は1年前に�「シンセを作ってる人たちの生々しい話を聞く」で話をしました。

よく骨折している気がします

3 of 38

誰?

DSP簡単かも?!という話をしに来ました。

一応、専門だったかもしれない。はるか昔、2004年とか。

4 of 38

NTS-1を買ったはいいけど・・・

最初のとっかかりどうしよう?中のサンプル難しい・・�という人向けの話をします。

5 of 38

DSPて何?

色々な物事を数字で表して、アレコレいじって、色々な物事に戻す!

社会の色々なところで使われている技術�- プロジェクターに画像が出るのもDSP�- 携帯電話もDSP

いろいろ

(数字)

いろいろ

(数字)

アレコレ

6 of 38

音だと?

音を数字で表して、アレコレいじって、音に戻す!�logue-sdkを使ってやるのはこれです。

(数字)

(数字)

アレコレ

7 of 38

音だと?

音の波形をPCで見るとこんな風になってる。これが数字で表された姿。

8 of 38

もっと拡大すると?

一定の時間ごとの音の大きさが記録されている。これが「サンプル」。�棒と丸で表しがち。

9 of 38

つまり?

「サンプル」をアレコレして「サンプル」にするのが、音のDSP

アレコレ

10 of 38

いじり方いろいろ

サンプルをいじるけど、直接ではない方式

max/mspやpdなど �出来上がっているモジュール�を組み合わせる方式。もちろんこれもDSP

11 of 38

いじり方いろいろ

直接いじる方式

サンプル「そのもの」をいじる。logue-sdkはこちら。�VSTやAUなどのソフトシンセもそう。割と硬派。�こちらの方が細かく、いろいろなことができる。

が、色々知っておく必要がある。今日はここの入口の話をします。

12 of 38

NTS-1 何からはじめれば?

最初はエフェクトを作るのがオススメ。�簡単なところから入れる。��オシレーターは結構難しい(やることが多い)�- 完全な無の状態から、音がある状態にしなければいけない�- ノート番号ごとに、別の波形をつくらないといけない�- 波形をうまく作らないと変な感じになったりする(エイリアシングとか)��ということで、今日はエフェクトを例にして、話をします。

13 of 38

今日話す内容のサンプルソースコード

14 of 38

今日話す内容のサンプルソースコード

重要なのはここだ!詳しくはせんとれさん(?)

void REVFX_PROCESS(float *xn, uint32_t frames)

15 of 38

その1 何もしない

入ってきた音をそのまま出す!

16 of 38

その1 何もしない

なぜ「何もしないエフェクト」が大事なのか?

  • ハードウェアなど、基本的な部分が正しく動いているか?を確認できる。
  • サンプルの扱いかたが間違っていないか?を確認できる。
  • ここが動けば8割は完成しているといってもいいと個人的には思う。
  • 他の開発環境などでも、初めて使う場合にも最初に試してください。

17 of 38

その1 何もしない

何もしない の 「処理」

出力 = 入力� *l_input = *l_input; // L CHのサンプルはL CHのサンプルそのまま�

何もしない

18 of 38

その2 ボリュームを変える

出力 = 入力 x ノブの値(0.0 ~ 1.0)

*l_input = *l_input * volume; // L CHのサンプルはL CHにボリュームを掛けたもの

ノブの値を掛け算

19 of 38

ボリュームの応用でエフェクトっぽく!

雑なクリッパー 掛け算を大きな値にして、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;

}

ノブの値を掛け算�大きすぎたら小さくする

20 of 38

その3 フィルター

1個のサンプルを大きくしたり小さくしたりすると、�エフェクトっぽいことができるのはわかった。

例えばフィルター、どうやるの?

21 of 38

その3 フィルター

フィルターって? �高い音だけ削ったり、低い音だけ削ったりするエフェクト。

サンプルが次々とやってくる。その大きさの変化のうち、素早いものを無視、ゆっくりした変化だけを取り出せば、高い音が消える。これがローパスフィルター。

22 of 38

その3 フィルター

どうやって? �直観的に簡単なのは、平均をとること。�全体がなめらかになる = 素早い変化が消える。�株とかFXのチャートとかで見たことあるかも。

23 of 38

その3 フィルター

平均をとるプログラムを書いて、NTS-1で動かしてみる�こんな感じ�const float l_filtered = movingAverage(*l_input, lch_buffer, num_samples_to_use);

今までに来たサンプルと並べて、平均をとる

メモリーに覚えておく

24 of 38

逆にハイパスは?

素早い変化だけを取り出せばOK�前のサンプルと、今のサンプルの差=変化

25 of 38

逆にハイパスは?

元の信号から、ローパスフィルタをかけた信号を引き算してもよい。

*l_input = *l_input - l_filtered; // LCH ローパスフィルタしたものを引く = 高い信号が残る

(本当は位相がズレてるので思ったようにはならないが、まあまあそれっぽくなる)

26 of 38

ここまでのまとめ

入ってきた信号をあれこれいじると、音が変わる。つまりエフェクト。

過去のサンプルを使うと、「変化」を利用したエフェクトが作れる。

27 of 38

ここまでのまとめ

ここまで見てきた感じのDSPの処理のやり方を、FIRフィルターといいます。�入ってきたサンプル、それを遅らせたサンプルを足したり掛けたりします。

28 of 38

ここまでのまとめ

他にFIRでできるもの

サンプリングリバーブ など。

29 of 38

別の方式

IIRというのもある。入ってきた信号、それを遅らせた信号だけでなく、�出力も使う。

30 of 38

IIRの簡単な例

aが大きい=>最新の信号の比率が高くなって、サンプルそのものに近づく�aが小さい=>過去の信号の比率が高くなって、変化がおさえられる

31 of 38

IIRの簡単な例

aが大きい=>最新の信号の比率が高くなって、サンプルそのものに近づく�aが小さい=>過去の信号の比率が高くなって、変化がおさえられる

つまり、aの大きさで特性が変わる、ローパスフィルタ!

32 of 38

IIRの簡単な例

logue-sdkでやるとこんな感じ

const float l_filtered = a * (*l_input) + (1-a) * lch_buffer;

33 of 38

logue-sdkのサンプル biquad

IIRの一種で、こんな形。(他もある)�aとbを色々な値にすることで、�ローパス、ハイパス、バンドパスなど�色々作れる。便利。

logue-sdkでは、�APIが最初から用意されてる。�中でやってることは、これまで説明�したような感じ。

34 of 38

サンプルコードが読めるかも?

DSP難しい? 

-> 結局はサンプルを掛けたり足したり、貯めたりしているだけ。�ここまで話したことだけでも、工夫次第でいろいろできる。

35 of 38

今日話さなかったこと

難し目のこと

  • サンプリングの理屈 ナイキスト周波数とか
  • フーリエ変換
  • フィルタの設計方法

など、ガチな数式が出てくるもの

36 of 38

今日話さなかったこと

知っていればできることは増えるが、まずできることはたくさんある。

とりあえず、音を出そう!

37 of 38

参考になるかもしれない情報

- music dsp(コピペできるものも多数) https://www.musicdsp.org/en/latest/

- やる夫で学ぶディジタル信号処理(かなりガチ寄り) http://www.ic.is.tohoku.ac.jp/~swk/lecture/yaruodsp/main.html

38 of 38

以上です。

ありがとうございました!

質問などあればどうぞ!!