MozziWS 2_3

和音(加算合成)に挑戦してみる

次は和音出力(加算合成)に挑戦です。 少し込み入ってきましたが、記入してあるコメント文を読むと何となくわかってきます。 単純に今まで使ってきたオシレーターを複数用意して(この場合7つ)、今までと同じようにピッチを設定しています。

今回初めて使っているのは、updateAudio()内のゲイン調整です。 複数のオシレーターを重ねると出力が大きくなってしまいます。 そのため、シフト演算で>>3をかけてあげることで、1/2^3、すなわち8で割って出力オーバーを防ぎます。

(サンプルのSynthesis/”Detuned_Beats_Wash.ino”(Tim Barrass 2012.)を参考にしています。)

 1#include <MozziGuts.h>
 2#include <Oscil.h> // オシレーターのテンプレート
 3#include <tables/cos8192_int8.h> // オシレーター用のコサインテーブル
 4#include <mozzi_midi.h> //Pdの[mtof]オブジェクトの代わり
 5 
 6#define CONTROL_RATE 64 // コントロールレートの設定
 7 
 8// harmonics 加算するオシレーターの配列変数COS2048_DATA2048の8bitデータを格納
 9Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos1(COS8192_DATA);
10Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos2(COS8192_DATA);
11Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos3(COS8192_DATA);
12Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos4(COS8192_DATA);
13Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos5(COS8192_DATA);
14Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos6(COS8192_DATA);
15Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos7(COS8192_DATA);
16 
17// ベースとなるピッチの変数を用意
18Q16n16 f1,f2,f3,f4,f5,f6,f7;
19 
20float val = 0.f;
21float pitch = 0.f; // 音の高さ (pitch) の変数
22int sensorValue;
23int pin = 0;
24 
25void setup(){
26  startMozzi(CONTROL_RATE); // Mozziの初期化と処理開始
27}
28 
29void loop(){
30  audioHook(); // 再生のために必要
31}
32 
33void updateControl(){ // Mozziの音出力設定はこの領域に書き込む
34 
35  sensorValue = mozziAnalogRead(pin); //Mozzi処理のバックグラウンドでセンサ値を読み込む
36  val = map(sensorValue, 0, 1024, 0, 127); //センサの値を0~127にマッピング
37 
38  if(val < 128 && val > 0){ // 1~127の値であれば...
39    pitch = val; //pitchに値を格納する
40 
41    // センサ値からピッチを決定 (MIDIノートナンバー)
42    f1 = Q16n16_mtof(Q16n0_to_Q16n16(pitch));
43    f2 = Q16n16_mtof(Q16n0_to_Q16n16(pitch+3));
44    f3 = Q16n16_mtof(Q16n0_to_Q16n16(pitch+7));
45    f4 = Q16n16_mtof(Q16n0_to_Q16n16(pitch+10));
46    f5 = Q16n16_mtof(Q16n0_to_Q16n16(pitch+14));
47    f6 = Q16n16_mtof(Q16n0_to_Q16n16(pitch+21));
48    f7 = Q16n16_mtof(Q16n0_to_Q16n16(pitch+24));
49 
50    // setFreqに格納
51    aCos1.setFreq_Q16n16(f1);
52    aCos2.setFreq_Q16n16(f2);
53    aCos3.setFreq_Q16n16(f3);
54    aCos4.setFreq_Q16n16(f4);
55    aCos5.setFreq_Q16n16(f5);
56    aCos6.setFreq_Q16n16(f6);
57    aCos7.setFreq_Q16n16(f7);
58  }
59 
60  else{ // 1~127以外の値がきた場合は...
61    pitch = 0.f; //pitchを0にしてオシレーターを止める
62    f1 = Q16n16_mtof(Q16n0_to_Q16n16(0));
63    f2 = Q16n16_mtof(Q16n0_to_Q16n16(0));
64    f3 = Q16n16_mtof(Q16n0_to_Q16n16(0));
65    f4 = Q16n16_mtof(Q16n0_to_Q16n16(0));
66    f5 = Q16n16_mtof(Q16n0_to_Q16n16(0));
67    f6 = Q16n16_mtof(Q16n0_to_Q16n16(0));
68    f7 = Q16n16_mtof(Q16n0_to_Q16n16(0));
69 
70    aCos1.setFreq_Q16n16(0);
71    aCos2.setFreq_Q16n16(0);
72    aCos3.setFreq_Q16n16(0);
73    aCos4.setFreq_Q16n16(0);
74    aCos5.setFreq_Q16n16(0);
75    aCos6.setFreq_Q16n16(0);
76    aCos7.setFreq_Q16n16(0);
77  }
78}
79 
80int updateAudio(){
81  // オーディオの繰り返し出力処理
82  int asig =
83    aCos1.next() + aCos2.next() +
84    aCos3.next() + aCos4.next() +
85    aCos5.next() + aCos6.next() +
86    aCos7.next() ;
87 
88  return asig >> 3; ///それぞれの出力オーバーを防ぐために>>3
89}

回路は第4回の可変抵抗のものを流用してください。

NEXT 次へ

MAIN PAGE メインページへ