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

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

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

#include <MozziGuts.h>
#include <Oscil.h> // オシレーターのテンプレート
#include <tables/cos8192_int8.h> // オシレーター用のコサインテーブル
#include <mozzi_midi.h> //Pdの[mtof]オブジェクトの代わり

#define CONTROL_RATE 64 // コントロールレートの設定

// harmonics 加算するオシレーターの配列変数COS2048_DATA2048の8bitデータを格納
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos1(COS8192_DATA);
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos2(COS8192_DATA);
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos3(COS8192_DATA);
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos4(COS8192_DATA);
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos5(COS8192_DATA);
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos6(COS8192_DATA);
Oscil<COS8192_NUM_CELLS, AUDIO_RATE> aCos7(COS8192_DATA);

// ベースとなるピッチの変数を用意
Q16n16 f1,f2,f3,f4,f5,f6,f7;

float val = 0.f;
float pitch = 0.f; // 音の高さ (pitch) の変数
int sensorValue;
int pin = 0;

void setup(){
  startMozzi(CONTROL_RATE); // Mozziの初期化と処理開始
}

void loop(){
  audioHook(); // 再生のために必要
}

void updateControl(){ // Mozziの音出力設定はこの領域に書き込む

  sensorValue = mozziAnalogRead(pin); //Mozzi処理のバックグラウンドでセンサ値を読み込む
  val = map(sensorValue, 0, 1024, 0, 127); //センサの値を0~127にマッピング

  if(val < 128 && val > 0){ // 1~127の値であれば...
    pitch = val; //pitchに値を格納する

    // センサ値からピッチを決定 (MIDIノートナンバー)
    f1 = Q16n16_mtof(Q16n0_to_Q16n16(pitch));
    f2 = Q16n16_mtof(Q16n0_to_Q16n16(pitch+3));
    f3 = Q16n16_mtof(Q16n0_to_Q16n16(pitch+7));
    f4 = Q16n16_mtof(Q16n0_to_Q16n16(pitch+10));
    f5 = Q16n16_mtof(Q16n0_to_Q16n16(pitch+14));
    f6 = Q16n16_mtof(Q16n0_to_Q16n16(pitch+21));
    f7 = Q16n16_mtof(Q16n0_to_Q16n16(pitch+24));

    // setFreqに格納
    aCos1.setFreq_Q16n16(f1);
    aCos2.setFreq_Q16n16(f2);
    aCos3.setFreq_Q16n16(f3);
    aCos4.setFreq_Q16n16(f4);
    aCos5.setFreq_Q16n16(f5);
    aCos6.setFreq_Q16n16(f6);
    aCos7.setFreq_Q16n16(f7);
  }

  else{ // 1~127以外の値がきた場合は...
    pitch = 0.f; //pitchを0にしてオシレーターを止める
    f1 = Q16n16_mtof(Q16n0_to_Q16n16(0));
    f2 = Q16n16_mtof(Q16n0_to_Q16n16(0));
    f3 = Q16n16_mtof(Q16n0_to_Q16n16(0));
    f4 = Q16n16_mtof(Q16n0_to_Q16n16(0));
    f5 = Q16n16_mtof(Q16n0_to_Q16n16(0));
    f6 = Q16n16_mtof(Q16n0_to_Q16n16(0));
    f7 = Q16n16_mtof(Q16n0_to_Q16n16(0));

    aCos1.setFreq_Q16n16(0);
    aCos2.setFreq_Q16n16(0);
    aCos3.setFreq_Q16n16(0);
    aCos4.setFreq_Q16n16(0);
    aCos5.setFreq_Q16n16(0);
    aCos6.setFreq_Q16n16(0);
    aCos7.setFreq_Q16n16(0);
  }
}

int updateAudio(){
  // オーディオの繰り返し出力処理
  int asig =
    aCos1.next() + aCos2.next() +
    aCos3.next() + aCos4.next() +
    aCos5.next() + aCos6.next() +
    aCos7.next() ;

  return asig >> 3; ///それぞれの出力オーバーを防ぐために>>3
}

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