2015年7月23日木曜日

Processing Sound (day 1)



質より量を重視する選択をしましたどうもご無沙汰しております。

Processingの開発環境には音のライブラリとしてminimが標準で入っています。
このminimライブラリを使えばラインインから集めた音の周波数解析(FFT)やオーディオリアクティブなビジュアルソフト、自作の楽器を簡単に作成することができるようです。

ですが、標準のままですとラインインになんらかの処理を施し、ラインアウトへ。という処理ができません。すなわちラインインにつないだエレキギターにエフェクトをかけてスピーカーからかっこいい音を出したい。というのはそのままでは難しいということになります。一番の障害となっているのはAudioInputのインスタンスにはpatch() というメソッドが用意されていないことです。
patch() reference in -> http://code.compartmental.net/minim/ugen_method_patch.html

ソフトウエア的に生成した音声情報(ファイルからの読み込みを含む)はpatch()メソッドによって様々な既存のフィルター等を経由させて最終的に出力が可能です。

このpatch()メソッドをAudioInputのインスタンスに適用するためのひとつの方法は、新たにクラスを追加することです。processing forum (http://forum.processing.org/two/discussion/7172/echo-effect-with-minim)において紹介されている方法にて先ほど不可能であったラインインからラインアウトへ。が可能になったのでここに記述しておきます。

//Tab1 name:lineInTolineOut
Minim minim;
AudioInput in;
AudioOutput out;
MyAudioSocket socket;

void setup(){
  //initialize the minim and out objects
  int buffer_size = 512;
  minim = new Minim(this);
  minim.debugOn();
  in = minim.getLineIn(Minim.STEREO,buffer_size);
  out = minim.getLineOut(Minim.STEREO,buffer_size);
  socket = new MyAudioSocket(buffer_size);
  in.addListener(socket);
  socket.patch(out);
}

void draw(){
}

//Tab2 name:MyAudioSocket
class MyAudioSocket extends UGen implements AudioListener
{
 
  private float[] left;
  private float[] right;
  private int buffer_max;
  private int inpos, outpos;
  private int count;
 
  MyAudioSocket(int buffer_size)
  {
     int n_buffers = 4;
     buffer_max = n_buffers * buffer_size;
     left = new float[buffer_max];
     right = new float[buffer_max];
     inpos = 0;
     outpos = 0;
     count = 0;
  }
 
  // The AudioListener:samples method accepts new input samples
  synchronized void samples(float[] samp)
  {
    // handle mono by writing samples to both left and right
    samples(samp, samp);
  }
 
  synchronized void samples(float[] sampL, float[] sampR)
  {
    System.arraycopy(sampL, 0, left, inpos, sampL.length);
    System.arraycopy(sampR, 0, right, inpos, sampR.length);
    inpos += sampL.length;
    if (inpos == buffer_max) {
      inpos = 0;
    }
    count += sampL.length;
  }
 
 
  //if I understand this correctly, UGens operate on a per sample basis
  //Override
  protected void uGenerate(float[] channels) 
  {
    if (count > 0) {
      for(int n = 0; n < channels.length; n++){
       channels[n] = ((n&1) == 0)?left[outpos]:right[outpos]; 
      }
      outpos++;
      if (outpos == buffer_max) {
         outpos = 0;
       }
      count--;
    }
  }
}

0 件のコメント:

コメントを投稿