Daily Creative Coding

元「30 min. Processing」。毎日、Creative Codingします。

インタラクティブに音を合成する

f:id:aa_debdeb:20151101111259j:plain

マウスをクリックすると,1つのサイン波を生成する. x方向は音の高さ,y方向は音の大きさに対応している. 生成したサイン波はドラッグで移動させることができる.

/**
* Interactive Sound Synthesis
*
* @author aa_debdeb
* @date 2015/11/05
*/

import ddf.minim.spi.*;
import ddf.minim.signals.*;
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.ugens.*;
import ddf.minim.effects.*;

Minim minim;
AudioOutput out;
ArrayList<Wave> waves;
Wave heldWave;

void setup(){
  size(500, 500);
  minim = new Minim(this); 
  out = minim.getLineOut(minim.STEREO);
  waves = new ArrayList<Wave>();
  heldWave = null;
}

void draw(){
  background(0);
  
  stroke(255);
  strokeWeight(1);
  beginShape();
  for(int x = 0; x < out.bufferSize(); x++){
    vertex(x, height/2 + out.mix.get(x) * 50);
  }
  endShape();
  
  for(Wave wave: waves){
    wave.display();
  }

}

void mousePressed(){
  for(Wave wave: waves){
    if(sqrt(sq(mouseX - wave.x) + sq(mouseY - wave.y)) < wave.radious){
      heldWave = wave;
      return;
    }
  }
  waves.add(new Wave(mouseX, mouseY));
}

void mouseDragged(){
  if(heldWave != null){
    heldWave.update(mouseX, mouseY);
  }
}  

void mouseReleased(){
  heldWave = null;
}

void stop(){
  out.close();
  minim.stop();
  super.stop();
}

class Wave{
  
  SineWave sine;
  float x, y;
  float radious = 20;
  
  Wave(float x, float y){
    this.x = x;
    this.y = y; 
    float freq = map(x, 0, width, 20,10000);
    float amp = map(y, 0, height, 0, 0.5);
    sine = new SineWave(freq, amp, out.sampleRate());
    sine.portamento(200);
    out.addSignal(sine);
  }
  
  void update(float x, float y){
    this.x = x;
    this.y = y;
    float freq = map(x, 0, width, 20, 5000);
    float amp = map(y, 0, height, 0, 1.0); 
    sine.setFreq(freq);
    sine.setAmp(amp);
  }
  
  void display(){
    noFill();
    stroke(255);
    strokeWeight(2);
    ellipse(x, y, radious * 2, radious * 2);
  }
  
}