メインページに戻る

1. 楽曲のビート情報を推定してみよう!

  1. Colaboratoryを使います
  2. リンクをクリックしてをドライブにコピーをクリック
  3. music/sample.wavをアップロード
  4. コードを実行
  5. beat_times.csvをダウンロード
    (beat_times.csvにビートのタイミングの秒数が記録されている)
import librosa
import numpy as np
import pandas as pd

# ローカルから音楽ファイルをアップロード
from google.colab import files
uploaded = files.upload()
filename = list(uploaded.keys())[0]

# ビート検出
y, sr = librosa.load(filename)
tempo, beat_frames = librosa.beat.beat_track(y=y, sr=sr)
beat_times = librosa.frames_to_time(beat_frames, sr=sr)

# データをDataFrameに変換
df = pd.DataFrame(beat_times, columns=["Beat_Times"])

# CSVとして保存
csv_filename = "beat_times.csv"
df.to_csv(csv_filename, index=False)

# ダウンロードリンクを表示
files.download(csv_filename)


2. ビート情報を可視化してみよう!

2.1 Minimライブラリをインストールしよう

ProcessingのIDEを開き、Sketchメニューの中のライブラリをインポート… > Manage Libraries…を選択します。

検索ボックスに”Minim”と入力し、表示されたMinimライブラリをインストールします。

2.2 ビート情報を可視化してみよう

  1. Processingでファイル=>新規 から新しいコードを作成して保存しよう。
  2. 新しく作成したファイル名/data にsample.wavと先ほどダウンロードしたbeat_times.csvを入れる。
  3. 以下のコードを実行!
import ddf.minim.*;

ArrayList<Float> beatTimes;
float circleSize;
float baseSize = 50;
float expandSize = 150;
float shrinkSpeed = 5;
int index = 0;
boolean loopStarted = false;
Minim minim;
AudioPlayer player;

void setup() {
  size(800, 600);
  background(255);

  // CSVからビートのタイムスタンプを読み込む
  beatTimes = new ArrayList<Float>();
  String[] lines = loadStrings("beat_times.csv");
  for (int i = 1; i < lines.length; i++) { // ヘッダー行をスキップ
    beatTimes.add(float(lines[i]));
  }

  circleSize = baseSize;

  // Minimを初期化し、音楽ファイルを読み込む
  minim = new Minim(this);
  player = minim.loadFile("sample.wav");
  player.play();
  player.loop();
}

void draw() {
  background(255);
  update();
  display();
}

void update()
{
  float songCurrentTime = player.position() / 1000.0; // 経過時間を秒単位で計算

  // ループ再生の時、再生位置が楽曲の最後に達したら index を0にリセット
  if (songCurrentTime >= player.length() / 1000.0 - 0.03) {
    println("Loop started!");
    index = 0;
  } else if (songCurrentTime <= 0.025)
  {
    index = 0;
  }


  println(index, songCurrentTime, player.length() / 1000.0);


  // 現在の再生時間を表示
  fill(0);
  text("Current time: " + nf(songCurrentTime, 0, 2) + " seconds", 20, 20);

  // 次のビートが来たら円のサイズを大きくする
  if (index < beatTimes.size() && songCurrentTime >= beatTimes.get(index)) {
    if (index%2==0)
      circleSize = expandSize;
    index++;
  }

  // 円のサイズを縮小させる
  circleSize = lerp(circleSize, baseSize, shrinkSpeed * 0.01);
}

void display()
{
  // 円を描画
  fill(127);
  ellipse(width/2, height/2, circleSize, circleSize);
}

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


音楽のビートに合わせて円が大きくなったかな?

参考:part09_beat_tracking

3. ビート情報に合わせてエフェクトをコントロールしよう!

part09_random_circle_on_beatを実行!
ビートに合わせてエフェクトがどのように変化したかな?コードを追ってみよう!

メインページに戻る