もなかアイスの試食品

「とりあえずやってみたい」そんな気持ちが先走りすぎて挫折が多い私のメモ書きみたいなものです.

音(低音)に合わせてLEDを光らせてみた

昔,こんな動画を作りました.

内容は,再生中の音楽を高速FFTして,ある周波数帯が設定した閾値を超えたら,シリアル通信で信号を送信.

受け取った方は,LEDを点灯させるという感じです.

ソースを知りたいというお声を頂いたので書いておきます.

結構前に作ったので,結構忘れているもんですね・・・

参考にしたサイトのプログラムの丸パクリです・・・

参考サイトはこちら

エフェクト、周波数解析 | Yasushi Noguchi Classエフェクト、周波数解析 | Yasushi Noguchi Class

import ddf.minim.analysis.*;
import ddf.minim.*;
import processing.serial.*;
Serial myPort;
int S_a1;

Minim minim; //Minim型変数であるminimの宣言
AudioPlayer player;  //サウンドデータ格納用の変数
FFT fft;    //フーリエ変換用変数
 
void setup()
{
  size(512, 512);
  stroke(0);
  // シリアル通信の初期化
  myPort=new Serial(this,"COM3",9600);
 
  minim = new Minim(this);
  // LEDを光らす閾値
  S_a1 = 65;
  
  // 解析する音楽
  player = minim.loadFile("unfragment (Original Mix).mp3", 512);
  
  player.loop();
 
  //FFTオブジェクトを作成。bufferSize()は1024、sampleRateは初期設定では44100Hz。
  fft = new FFT(player.bufferSize(), player.sampleRate());
  println("sampling reate is " +player.sampleRate());
  println("spec size is " +fft.specSize());
  println("bandwidth is: " +fft.getBandWidth());    //最小単位の帯域
}
 
void draw()
{
 
  background(0);
 
  //fftを左と右の音声を混ぜて解析
  //左右の音をそれぞれ取りたければ、player.left、player.rightという形で使う
  fft.forward(player.mix);

 // 周波数帯(86.133〜172.266)が閾値以上の時,シリアルでを送信
  if (fft.getBand(1) > S_a1){
   //background(255); 
   myPort.write('1');
  }
  else{
    myPort.write('0');
  }
 
  //サンプリングレートが44100Hzの場合、実際の周波数はその半分の0~22050Hzしか入っていない。
  //なので、バッファサイズが1024だとすると、specSize()はバッファ/2 +1 になる。つまり513。
  //また、バッファが1024ということは、44100Hzを1024分割していることになり、結果BandWidthは43.066406になる。
  stroke(255);
  line(0,height-S_a1*4,width,height-S_a1*4); // 閾値ライン
  
 
  for(int i = 0; i < fft.specSize(); i++)
  {
    //画面のy座標の中心から上下に延びる線を描く
    if(i==1){
      stroke(255,0,0); // 閾値判断用のスペクトルだけ色を変更する(赤)
    }
    else{
       stroke(0,255,0); // 後は同じ色(緑)
    }
    float x1 = map(i,0,fft.specSize(),0,width);
    line(x1, height, x1, (height - fft.getBand(i)*4));
    
  }
}
 
void stop()
{
  // アプリケーションの終了前にAudioPlayerを終了する
  player.close();

  // minimを終了
  minim.stop();
 
  //ソフト全体を終了
  super.stop();
}


次にArduinoのプログラムです.こちらは,デフォルトで入っていたプログラムを元に作りました.

String txtMsg = "";   // 受信データ記録用

void setup() {
  // シリアル通信の初期化
  Serial.begin(9600);
  pinMode(8, OUTPUT);
}

void loop() {
  // シリアル受信処理
  while (Serial.available() > 0) {
    char inChar = Serial.read();
    txtMsg += inChar;
  }
    if (txtMsg == '1') {
      digitalWrite(8, HIGH);   // LED on
    }  
    if (txtMsg == '0') {
      digitalWrite(8, LOW);   // LED off
    }
    // 受信データ削除
    txtMsg = "";

}