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

学習日

2025年12月23日、2026年1月13日

名前

樋口桜大

準備をしよう!

1.ファイル名をsoudEQとして一回保存する。                                                 2.index.htmlのheadに下記のコードを追加する。         

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

↓↓↓のコードが入っているから、この下に入れる!!

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

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

4.下記のスクリプトをスケッチに貼り付ける。
let sound;   // 再生する音
let fft;     // 音のデータを取り出す道具

function preload() {
  sound = loadSound('sample.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(); // ループ再生(繰り返し)
  }
}

これで、流れの確認と準備完了!!

自分で作った図形(コードと画像)

🖊️1−1(さっきの例を自分なりにアレンジしてみた!)

↓すべてダウンロードしたら、下記のコードを貼り付ける

コード

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

function preload() {
  sound = loadSound('tadakoehitotsu.mp3');
  sura = loadImage('purupuru.png');
  king = loadImage('buruburu.jpg');
  meta = loadImage('metaburu.png');
  naito = loadImage('naito.jpg');
}

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

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

  textSize(16);
}

function draw() {
  background(255);

  // まだ再生していない時は案内だけ出す
  if (!sound.isPlaying()) {
    fill(random(255), random(255), random(255));
    textAlign(CENTER, CENTER);
    text('クリックで再生 / 停止', 200, 100);
    imageMode(CENTER);
    image(king, 50, 50, 100, 100);
    image(naito, 350, 100, 100, 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;
  
  //画像の中心を設定
  imageMode(CENTER);

  noStroke();
  image(sura, 100, 100, leftRadius * 2, leftRadius * 2);

  image(meta, 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(); // ループ再生(繰り返し)
  }
}

📷 実行結果

アレンジ内容

・曲を始めるときの画面にキングスライム(キングス)とスライムナイト(ピエール)を貼り付けた。 

・曲を始めるときの画面の「クリックで再生/停止」の文字をカラフルになるようにした。         

・曲を流した時に音量の大きさを表していた円を、左側をスライム(スラリン)/右側をメタルキング(メタキン)に変えた。

🖊️1−2(1−1で表した音量の波形を点で表してみよう!!)

まずは、「1番目の音量を◯◯にする」というのを1024個横に伸びていくように作っていくよ!

コード

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

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

function setup() {
  createCanvas(1024, 300);

  // ★波形データを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 spectrum = fft.analyze();
  for(let i = 0; i < 1024; i++){
     point(i, 300-spectrum[i]);
  }
}

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

📷 実行結果

x=700までの部分を動画にしているよ!

作るときのポイント

1.いらない部分は省くこと。                                          2.fft.をwavefrom()からanalyze()に変えること。                                3.1024回繰り返すfor文を作って点を描けるようにすること。                               4.点を一つずつ描いていくとき、点が下から上に向かうように描けるようにすること。

🖊️1−3(1−2で作った点の波形を線で繋いで曲線になるようにしよう)

作るときのポイント

 反比例のグラフを描いた時に使ったcurveVertex()をうまく活用してみると簡単にできるかも…。

コード  for分の部分を下のコードのように付け加えるだけ!!!

  let spectrum = fft.analyze();
  beginShape();
  for(let i = 0; i < 1024; i++){
     point(i, 300-spectrum[i]);
     // noFill();
     // curveVertex(i, 300-spectrum[i]);
  }
  endShape();
}

📷 実行結果

🖊️1−4(自作アレンジ!!)

コード

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

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

function setup() {
  createCanvas(1024, 300);

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

  textSize(16);
}

function draw() {
  background(0);

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

  // 波形(音の振れ方)を配列でもらう(長さは1024)
  // 値はだいたい -1.0 ~ +1.0 の範囲
  let spectrum = fft.analyze();
  beginShape();
  for(let i = 0; i < 1024; i++){
     stroke(random(255), random(255), random(255));
     point(i, 300-spectrum[i]);
     noFill();
     curveVertex(i, 300-spectrum[i]);
  }
  endShape();
}

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

📷️実行結果

こだわりについて

・曲線の色が変化していくようにした。                                   

・曲線の色を目立たせるように背景を黒くした。

まとめ・感想

・サウンドイコライザーを作る中で、今まで学習してきた「for文」だったり、「beginShape/endShape」を使ったりする場面があって、復讐しながら作ることができた。

・初めて習った「spectrum/fft.analyze」は、意味を理解してこれからさまざまなアレンジをしていくうえで活かしていけると思ったから、しっかりと覚えていきたい。

・自分なりにアレンジする時に「どういうアレンジだと面白いか」を考えて、自分で画像を持ってきたり、色をただ変えるだけでなくカラフルにしたりして楽しんで取り組めた。

コメントする