お久しぶりです。春休みに入って暇になり、留学がなくなり暇になり、春休みが伸びて暇をしています。電動バイクは減速機が作れずにn回目の計画破棄をしたので進捗はないです。

 そんなこんなでなんとなくModulinもどきを作ってみました。
 Modulinはこんなやつです。


 これは確かどこかのシンセサイザー会社が限定で作ったモジュラーシンセサイザーで、センサーだけでものすごく高かったので、自分は楽器が弾けませんが作ってみました。

 作るにあたって、このセンサーと同じようなものや同じような働きのセンサーがありました。それで長いこと探していた時に、この前の記事の時に使っていたものを見つけました。このsoft potというセンサーはは秋月では売ってなく、千石では短いものしかなく、マルツにも在庫がなく、スイッチサイエンスは取扱しておらず、国内で買うことがたぶんできない状態でした。それなので今回はMouserから買いました。なんか関税とかかかって多少割高になりますがこれで買うことができました。

 システムは下のようになります。今回、処理はほぼすべてProcessingで行ったのでArduinoはセンサーの値をまとめてシリアルで送っているだけです。
Untitled Diagram

 センサーには今回、つまみ用の可変抵抗10個、スライド抵抗1個、モーメンタリトグルスイッチ1個、SoftPot 500mm 1個、圧力センサー1個、を使いました。これらの値をArduino MEGAで読み取りProcessingに送っています。

 Processingに送られたデータはMinimライブラリのパラメータにします。MinimはProcessingのライブラリで、これを使うことで様々な波形を出したりそれにエフェクトをかけたりすることができます。今回はこちらのブログを参考にVCO,VCF,VCA,EG,LFOを実装しました。

 これらをいい感じに実装すると下のようになりました。
ah5uf-ml17t
a2mbv-4c1fh

 実際にならしてみるとこんな感じです。
 音楽ができないので引くことはできないのですが自分的には結構いい感じにできたので満足しています。

 今回はここまでです。自分の中ではいい感じにできたので良かったです。それではまた今度。

プログラム(Arduino)
int recv_data_a;
int recv_data_b;
int data=10;
void setup() {
  Serial.begin(250000);
}

void loop() {
  delay(1);
  int value0 = analogRead(0);
  int value1 = analogRead(1);
  int value2 = analogRead(2);
  int value3 = analogRead(3);
  int value4 = analogRead(4);
  int value5 = analogRead(5);
  int value6 = analogRead(6);
  int value7 = analogRead(7);
  int value8 = analogRead(8);
  int value9 = analogRead(9);
  int value10 = analogRead(10);
  int value11 = analogRead(11);
  int value12 = analogRead(12);
  int value13 = analogRead(13);
  recv_data_a = analogRead(14);
  int value15 = analogRead(15);
  if(450 < recv_data_b && recv_data_b < 600){
    if(recv_data_a > 600){
      data++;
    }
    if(recv_data_a < 450){
      data--;
    }
  }
  recv_data_b = recv_data_a;
  Serial.write('H');
  Serial.write(highByte(value0));
  Serial.write(lowByte(value0));
  Serial.write(highByte(value1));
  Serial.write(lowByte(value1));
  Serial.write(highByte(value2));
  Serial.write(lowByte(value2));
  Serial.write(highByte(value3));
  Serial.write(lowByte(value3));
  Serial.write(highByte(value4));
  Serial.write(lowByte(value4));
  Serial.write(highByte(value5));
  Serial.write(lowByte(value5));
  Serial.write(highByte(value6));
  Serial.write(lowByte(value6));
  Serial.write(highByte(value7));
  Serial.write(lowByte(value7));
  Serial.write(highByte(value8));
  Serial.write(lowByte(value8));
  Serial.write(highByte(value9));
  Serial.write(lowByte(value9));
  Serial.write(highByte(value10));
  Serial.write(lowByte(value10));
  Serial.write(highByte(value11));
  Serial.write(lowByte(value11));
  Serial.write(highByte(value12));
  Serial.write(lowByte(value12));
  Serial.write(highByte(value13));
  Serial.write(lowByte(value13));
  Serial.write(highByte(data));
  Serial.write(lowByte(data));
  Serial.write(highByte(value15));
  Serial.write(lowByte(value15));
  Serial.println(value15);
}


プログラム(Processing)
import ddf.minim.spi.*;
import ddf.minim.signals.*;
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.ugens.*;
import ddf.minim.effects.*;
import  processing.serial.*;

Serial  serial;
Minim minim;
AudioOutput out;
// variance for VCO
Oscil oscil;
int octave;
// variance for VCF
MoogFilter filter;
// variance for VCA
ADSR adsr;
Multiplier multiplier;
// variance for LFO
Oscil vcoLfo, vcfLfo, vcaLfo;
float vcoLfoIntensity;
// variance for keyboard
boolean isbarLocked;
char lockedKey;
int recv_data_0;
int recv_data_1;
int recv_data_2;
int recv_data_3;
int recv_data_4;
int recv_data_5;
int recv_data_6;
int recv_data_7;
int recv_data_8;
int recv_data_9;
int recv_data_10;
int recv_data_11;
int recv_data_12;
int recv_data_13;
int recv_data_14;
int recv_data_15;
float freq[] = new float [1024];


void setup() {
  freq();
  size(1024, 100);
  textAlign(CENTER);
  fill(255);
  background( 0 );
  textSize(36);
  serial = new Serial( this, Serial.list()[1], 250000 );

  minim = new Minim(this);
  out = minim.getLineOut();
  oscil = new Oscil(440, 1.0, Waves.SQUARE);
  filter = new MoogFilter(10000, 0.0, MoogFilter.Type.LP);
  multiplier = new Multiplier(1.0);
  adsr = new ADSR(1.0, 1.0, 1.0, 0.5, 1.0);
  oscil.patch(filter).patch(multiplier).patch(adsr);
  vcoLfo = new Oscil(10, 0.0, Waves.SINE);
  vcoLfo.patch(oscil.frequency);
  vcfLfo = new Oscil(10, 0.0, Waves.SINE);
  vcfLfo.amplitude.setLastValue(0.0);
  vcfLfo.offset.setLastValue(10000);
  vcfLfo.patch(filter.frequency);
  vcaLfo = new Oscil(10, 0.0, Waves.SINE);
  vcaLfo.amplitude.setLastValue(0.0);
  vcaLfo.offset.setLastValue(1.0);
  vcaLfo.patch(multiplier.amplitude);
}

void setVcoWave() {//2
  switch(int(map(recv_data_2, 0, 1023, 0, 6))) {
    case(0):
    oscil.setWaveform(Waves.SINE);
    break;
    case(1):
    oscil.setWaveform(Waves.TRIANGLE);
    break;
    case(2):
    oscil.setWaveform(Waves.SAW);
    break;
    case(3):
    oscil.setWaveform(Waves.SQUARE);
    break;
  }
}

void setLfoWave() {//3
  switch(int(map(recv_data_3, 0, 1023, 0, 6))) {
    case(0):
    vcoLfo.setWaveform(Waves.SINE);
    vcfLfo.setWaveform(Waves.SINE);
    vcaLfo.setWaveform(Waves.SINE);
    break;
    case(1):
    vcoLfo.setWaveform(Waves.TRIANGLE);
    vcfLfo.setWaveform(Waves.TRIANGLE);
    vcaLfo.setWaveform(Waves.TRIANGLE);
    break;
    case(2):
    vcoLfo.setWaveform(Waves.SAW);
    vcfLfo.setWaveform(Waves.SAW);
    vcaLfo.setWaveform(Waves.SAW);
    break;
    case(3):
    vcoLfo.setWaveform(Waves.SQUARE);
    vcfLfo.setWaveform(Waves.SQUARE);
    vcaLfo.setWaveform(Waves.SQUARE);
    break;
  }
}

void setCutoffFrequency() {//4
  vcfLfo.amplitude.setLastValue(map(recv_data_4, 0, 1023, 0, 10000) / 2.0 * map(recv_data_8, 0, 1023, 0, 1));
  vcfLfo.offset.setLastValue(map(recv_data_4, 0, 1023, 0, 10000));
}

void setResonance() {//5
  filter.resonance.setLastValue(map(recv_data_5, 0, 1023, 0, 1));
}

void setLfoRate() {//6
  float value = map(recv_data_6, 0, 1023, 0, 100);
  vcoLfo.setFrequency(value);
  vcfLfo.setFrequency(value);
  vcaLfo.setFrequency(value);
}

//7

void setVcfIntensity() {//8
  float value = map(recv_data_8, 0, 1023, 0, 1);
  vcfLfo.amplitude.setLastValue(map(recv_data_4, 0, 1023, 0, 10000) / 2.0 * value);
}

void setVcaIntensity() {//9
  float value = map(recv_data_9, 0, 1023, 0, 1);
  vcaLfo.amplitude.setLastValue(map(recv_data_15, 0, 1023, 0, 1) / 2.0 * value);
}

void setParameters() {//10,11,12,13
  adsr.setParameters(1.0, map(recv_data_10, 0, 1023, 0, 1), map(recv_data_11, 0, 1023, 0, 1), map(recv_data_12, 0, 1023, 0, 1), map(recv_data_13, 0, 1023, 0, 1), 0.0, 0.0);
}

void setAmplitude() {//15
  float value = map(recv_data_15, 0, 1023, 0, 1);
  vcaLfo.amplitude.setLastValue(value / 2.0 * map(recv_data_9, 0, 1023, 0, 1));
  vcaLfo.offset.setLastValue(value);
}

void serialEvent(Serial port) {  
  if ( port.available() >= 33 ) {
    if ( port.read() == 'H' ) {
      //0
      int high = port.read();
      int low = port.read();
      recv_data_0 = high * 256 + low;
      //1
      high = port.read();
      low = port.read();
      recv_data_1 = high * 256 + low;
      //2
      high = port.read();
      low = port.read();
      recv_data_2 = high * 256 + low;
      //3
      high = port.read();
      low = port.read();
      recv_data_3 = high * 256 + low;
      //4
      high = port.read();
      low = port.read();
      recv_data_4 = high * 256 + low;
      //5
      high = port.read();
      low = port.read();
      recv_data_5 = high * 256 + low;
      //6
      high = port.read();
      low = port.read();
      recv_data_6 = high * 256 + low;
      //7
      high = port.read();
      low = port.read();
      recv_data_7 = high * 256 + low;
      //8
      high = port.read();
      low = port.read();
      recv_data_8 = high * 256 + low;
      //9
      high = port.read();
      low = port.read();
      recv_data_9 = high * 256 + low;
      //10
      high = port.read();
      low = port.read();
      recv_data_10 = high * 256 + low;
      //11
      high = port.read();
      low = port.read();
      recv_data_11 = high * 256 + low;
      //12
      high = port.read();
      low = port.read();
      recv_data_12 = high * 256 + low;
      //13
      high = port.read();
      low = port.read();
      recv_data_13 = high * 256 + low;
      //14
      high = port.read();
      low = port.read();
      recv_data_14 = high * 256 + low;
      //15
      high = port.read();
      low = port.read();
      recv_data_15 = high * 256 + low;

      setVcoWave();//2
      setLfoWave();//3
      setCutoffFrequency();//4
      setResonance();//5
      setLfoRate();//6
      setVcfIntensity();//8
      setVcaIntensity();//9
      setParameters();//10,11,12,13
      setAmplitude();//15
      
       print(recv_data_0);
       print(",");
       println(440*pow(2,freq[recv_data_0]/12.0));
       
    }
  }
}

void draw() {
  float waveH = 50;
  background(0);
  for(int i = 0; i < out.bufferSize()-1; i++)
  {
    point(i, 50 + out.left.get(i)*waveH);
  }
  stroke(255);
  if (recv_data_0>=18&&recv_data_1<=1000) {
    vcoLfo.amplitude.setLastValue(440*pow(2, (freq[recv_data_0]/12.0)+recv_data_14-10) / 2.0 * map(recv_data_7, 0, 1023, 0, 1));
    vcoLfo.offset.setLastValue(440*pow(2, (freq[recv_data_0]/12.0)+recv_data_14-10));
    adsr.unpatch(out);
    adsr.noteOn();
    adsr.patch(out);
    isbarLocked = true;
  } else {
    if (isbarLocked) {
      adsr.unpatchAfterRelease(out);
      adsr.noteOff();
      isbarLocked = false;
    }
  }
}