p5.jsでサウンドイコライザー 1/29

p5.jsでサウンドイコライザーを作る。

手順は以下の通り!

1.ファイル名をsoudEQとして一回保存する。

2.index.htmlのheadに下記のコードを追加する。

<script src="https://cdn.jsdelivr.net/npm/p5@1.11.11/lib/addons/p5.sound.min.js"></script>

3.好きなサウンドファイル(sample.mp3)をアップロードする。

今回はコレ!

でもこれだとサイズが大きすぎるので好きなところで縮めてみる。
それとチェック用にマリオの音源や周波数を下から上げていく音声も追加してみた。

さて、いよいよプログラム編

4.下記のスクリプトをスケッチに貼り付ける。

let sound;   // 再生する音
let fft;     // 音のデータを取り出す道具

function preload() {
  sound = loadSound('FIRST_NOTE.mp3');
}

function setup() {
  createCanvas(400, 200);

  // ★波形データを1024個に固定して取り出す
  //   1024個のうち、前半512を「左」、後半512を「右」として扱う
  fft = new p5.FFT(0.8, 1024);

  textSize(16);
}

function draw() {
  background(240);

  // まだ再生していない時は案内だけ出す
  if (!sound.isPlaying()) {
    fill(80);
    textAlign(CENTER, CENTER);
    text('クリックで再生 / 停止', 200, 100);
    return;
  }

  // 波形(音の振れ方)を配列でもらう(長さは1024)
  // 値はだいたい -1.0 ~ +1.0 の範囲
  let wave = fft.waveform();

  // 左右の「音量っぽい値」を作るための合計
  let leftSum = 0;
  let rightSum = 0;
  for (let i = 0; i < 512; i++) {
    leftSum += abs(wave[i]);
  }
  for (let i = 512; i < 1024; i++) {
    rightSum += abs(wave[i]);
  }
  let leftLevel = leftSum / 512;
  let rightLevel = rightSum / 512;

  // ★円の大きさ(半径)を作る
  let leftRadius = 10 + leftLevel * 250;
  let rightRadius = 10 + rightLevel * 250;

  // ★大きくなりすぎないように上限を決める
  if (leftRadius > 80) leftRadius = 80;
  if (rightRadius > 80) rightRadius = 80;

  // ★小さくなりすぎないように下限を決める
  if (leftRadius < 10) leftRadius = 10;
  if (rightRadius < 10) rightRadius = 10;


  noStroke();
  fill(100, 150, 255);
  ellipse(100, 100, leftRadius * 2, leftRadius * 2);

  // 右の円(中心は決め打ちで300,100)
  fill(255, 120, 120);
  ellipse(300, 100, rightRadius * 2, rightRadius * 2);

  // 数値を表示
  fill(50);
  textAlign(CENTER, CENTER);
  text('L', 100, 170);
  text('R', 300, 170);

  let leftValue = int(leftLevel * 100);
  let rightValue = int(rightLevel * 100);

  text(leftValue, 100, 190);
  text(rightValue, 300, 190);
}

function mousePressed() {
  
  // クリックで再生/停止できるようにする
  if (sound.isPlaying()) {
    sound.pause();
  } else {
    sound.loop(); // ループ再生(繰り返し)
  }
}

ここからアレンジを加える。

色々と試したところ、泡っぽく見せるのがかっこいいなと感じたので小さい方から大きい周波数になるほどcircleの大きさも大きく、今のままでは周波数が多すぎるので、3回に一回に調整して泡の数を少なくした。

let sound;   // 再生する音
let fft;     // 音のデータを取り出す道具

function preload() {
  sound = loadSound('FIRST_NOTE (mp3cut.net).mp3');
}

function setup() {
  createCanvas(512, 300);
  // ★波形データを1024個に固定して取り出す
  //   1024個のうち、前半512を「左」、後半512を「右」として扱う
  fft = new p5.FFT(0.8, 1024);
  textSize(16);
  twosecond = 0;
}

function draw() {
  background(24, 119, 149);

  // まだ再生していない時は案内だけ出す
  if (!sound.isPlaying()) {
    fill(255);
    textSize(16);
    textAlign(CENTER, CENTER);
    text('クリックで再生 / 停止', 256, 150);
    return;
  }

  // 波形(音の振れ方)を配列でもらう(長さは1024)
  // 値はだいたい -1.0 ~ +1.0 の範囲
  let wave = fft.analyze(1024);

  // 左右の「音量っぽい値」を作るための合計
  let Sum = [];

  for (let i = 0; i < 8; i++) 
  {
    Sum[i] = 0;
  }
  if (frameCount % 120 === 0) {
    twosecond += 1;
  }
  for (let i = 0; i < 1024; i++) 
  {
    // rect(i,200,1,-1*abs(wave[i]));
    if (abs(wave[i]) != 0 && abs(wave[i]) % 3 == 0)
    {
      fill(113, 191, 234);
      // if (abs(wave[i] % 50 == 0))
      //   {
      //     // fill(96/twosecond * 12, 191/twosecond * 12, 59/twosecond * 12);
      //     fill(255)
        // }
      // else if (abs(wave[i] % 50+random(50) == 0))
      //   {
      //     fill(160, 68, 40);
      //   }
      // ellipse(i + 5 * random(),200 -1* abs(wave[i]),10,10);
      ellipse(i,300 -1* abs(wave[i]),abs(wave[i])*abs(wave[i]/1000) ,abs(wave[i])*abs(wave[i])/1000);
      fill(255)
      ellipse(i,300 -1* abs(wave[i]),abs(wave[i])*abs(wave[i]/1200) ,abs(wave[i])*abs(wave[i])/1200);
      
    }
    if (i > 0 && i < 1024/8)
      {
        Sum[0] += abs(wave[i]);
      }
    else if(i < 1024/8 * 2)
      {
        Sum[1] += abs(wave[i]);
      }
    else if(i < 1024/8 * 3)
      {
        Sum[2] += abs(wave[i]);
      }
    else if(i < 1024/8 * 4)
      {
        Sum[3] += abs(wave[i]);
      }
    else if(i < 1024/8 * 5)
      {
        Sum[4] += abs(wave[i]);
      }
    else if(i < 1024/8 * 6)
      {
        Sum[5] += abs(wave[i]);
      }
    else if(i < 1024/8 *7)
      {
        Sum[6] += abs(wave[i]);
      }
    else
      {
        Sum[7] += abs(wave[i]);
      }
  }
  

  // let leftLevel = leftSum / 512;
  // let rightLevel = rightSum / 512;

  // // ★円の大きさ(半径)を作る
  // let leftRadius = 10 + leftLevel * 250;
  // let rightRadius = 10 + rightLevel * 250;

//   // ★大きくなりすぎないように上限を決める
//   if (leftRadius > 80) leftRadius = 80;
//   if (rightRadius > 80) rightRadius = 80;

//   // ★小さくなりすぎないように下限を決める
//   if (leftRadius < 10) leftRadius = 10;
//   if (rightRadius < 10) rightRadius = 10;


  noStroke();
  textSize(16);
  fill(231, 136, 106);

  // for (let i = 0; i < 8; i++) 
  //   {
  //     rect(400/8 * i,200-int(Sum[i]),400/8,int(Sum[i]));
  //   }
  // let leftValue = int(leftLevel * 100);
  // let rightValue = int(rightLevel * 100);
  
  textSize(40);
  fill(255, 155, 61);
  text("BLUE GIANT",120,280)
}

function mousePressed() {
  
  // クリックで再生/停止できるようにする
  if (sound.isPlaying()) {
    sound.pause();
  } else {
    sound.loop(); // ループ再生(繰り返し)
  }
}

炭酸水みたいになった。実行結果は下記のとおり

完成!

どやぁ~

コメントする