ステレオオーディオからリサジュー図形を描画する

  • ステレオオーディオから音声信号を取得します。
  • 取得した信号を左右のチャンネルに分離します。
  • 左右のチャンネルの信号に対して、異なる周波数の正弦波を加えます。このとき、周波数の比率は、描画するリサジュー図形の形状を決定します。
  • 加えた正弦波の波形を、x軸に左チャンネルの波形、y軸に右チャンネルの波形をとり、2次元平面上にプロットします。
  • プロットした点を順番につなぎ、リサジュー図形を描画します。

以上が、ステレオオーディオからリサジュー図形を描画する方法の簡単な手順です。これらの手順を実行することで、ステレオオーディオから美しいリサジュー図形を描画することができます。

リサジュー図形 - Wikipedia

import processing.sound.*;

Waveform monitorWave;
final int SAMPLES = 2048;
final float MIN_STD = 16.0;
final int X_FACTOR = 20;
final int Y_FACTOR = 20;

int lineWeight = 1;
color lineColor = color(0, 224, 255);
color backgroundColor = color(0,63,73);

void setup() {
  size(720, 300);
  //fullScreen();
  frameRate(120);
  background(backgroundColor);
  strokeWeight(lineWeight);
  stroke(lineColor);
  initializeAudio();
}

void initializeAudio() {
  AudioIn audioInput = new AudioIn(this, 0);
  audioInput.start();
  monitorWave = new Waveform(this, SAMPLES);
  monitorWave.input(audioInput);
}

void draw() {
  background(backgroundColor);
  float[] monitorWaveData = getMonitorWaveData();
  float[] pointList = getPointList(monitorWaveData);
  drawWaveform(pointList);
}

float[] getMonitorWaveData() {
  monitorWave.analyze();
  return monitorWave.data;
}

float[] getPointList(float[] monitorWaveData) {
  float[] pointList = new float[SAMPLES * 2];
  for (int i = 0; i < SAMPLES; i++) {
    float x = (monitorWaveData[i] - monitorWaveData[(i + SAMPLES / 2) % SAMPLES]) * X_FACTOR;
    float y = (monitorWaveData[i] + monitorWaveData[(i + SAMPLES / 4) % SAMPLES]) * Y_FACTOR;
    x /= MIN_STD;
    y /= MIN_STD;
    x *= width / 2;
    y *= height / 2;
    x += width / 2;
    y += height / 2;
    pointList[i * 2] = x;
    pointList[i * 2 + 1] = y;
  }

  return pointList;
}

void drawWaveform(float[] pointList) {
  stroke(lineColor);
  strokeWeight(lineWeight);
  noFill();
  beginShape();
  for (int i = 0; i < SAMPLES; i++) {
    vertex(pointList[i * 2], pointList[i * 2 + 1]);
  }
  endShape(CLOSE);
}

float stddev(float[] values) {
  float mean = mean(values);
  float sumSquaredDiff = 0;
  for (int i = 0; i < values.length; i++) {
    sumSquaredDiff += sq(values[i] - mean);
  }
  return sqrt(sumSquaredDiff / values.length);
}

float mean(float[] values) {
  float sum = 0;
  for (int i = 0; i < values.length; i++) {
    sum += values[i];
  }
  return sum / values.length;
}