このアプリは、音声入力から音声データを取得し、波形と周波数スペクトルの可視化、および円形のパターンを描画するプログラムです。 Processing Sound Libraryを使用しています。 ウィンドウには、3Dボックス、波形、円形のパターン、現在の時間が表示されています。円形のパターンは、音声入力から取得した音量に応じて変化します。円の位置、サイズ、回転速度、および周波数帯域幅などがランダムに生成されます。波形は、左右の音声入力から得られた波形を表示します。現在の時刻は、Helvetica Neueフォントで表示されます。

import processing.sound.*;

AudioIn audioInput;
Waveform leftWaveform, rightWaveform;
Circle[][] circles;
int numCircles = 120;
int minDist = 50;
int maxDist = 400;
int samples = 512;

void setup() {
  size(720, 300, P3D);
  frameRate(120);
  noStroke();
  ambientLight(0, 0, 0);
  initializeAudio();
  initializeTextFont();
  initializeCircles();
}

void initializeAudio() {
  audioInput = new AudioIn(this, 0);
  audioInput.start();
  leftWaveform = new Waveform(this, samples);
  leftWaveform.input(audioInput);

  audioInput = new AudioIn(this, 1);
  audioInput.start();
  rightWaveform = new Waveform(this, samples);
  rightWaveform.input(audioInput);
}

void initializeTextFont() {
  PFont font = createFont("HelveticaNeue-BoldItalic", 6);
  textFont(font);
  textAlign(CENTER, CENTER);
  textMode(SHAPE);
}

void initializeCircles() {
  circles = new Circle[numCircles / 10][10];
  for (int i = 0; i < numCircles; i++) {
    circles[i / 10][i % 10] = new Circle();
  }
}

// ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ //

void draw() {
  background(0, 107, 130);
  drawTimeText();
  draw3DBox();
  drawWaveforms();
  drawCircles();
}

// ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ //

void drawTimeText() {
  pushMatrix();
  translate(0, 0, 200);
  String text = getCurrentTimeString();
  int margin = 320;
  float totalTextWidth = textWidth(text) + (margin * 2);
  float letterSpacing = (width - totalTextWidth) / (text.length() - 1);
  float x = margin;
  float y = height / 2;
  fill(255);
  for (int i = 0; i < text.length(); i++) {
    char c = text.charAt(i);
    float charWidth = textWidth(c);
    text(c, x + (charWidth / 2), y);
    x += charWidth + letterSpacing;
  }
  popMatrix();
}

String getCurrentTimeString() {
  int hour = hour();
  int minute = minute();
  int second = second();
  return nf(hour, 2) + ":" + nf(minute, 2) + ":" + nf(second, 2);
}

// ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ //

void draw3DBox() {
  pushMatrix();
  translate(width / 2, height / 2, 50);
  rotateX(frameCount * 0.002);
  rotateY(frameCount * 0.005);
  noStroke();
  fill(0, 206, 206);
  box(100);
  popMatrix();
}

// ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ //

void drawWaveforms() {
  stroke(0, 206, 206);
  strokeWeight(4);
  noFill();

  leftWaveform.analyze();
  drawWaveform(leftWaveform, 0, width / 2);

  rightWaveform.analyze();
  drawWaveform(rightWaveform, width / 2, width);
}

void drawWaveform(Waveform waveform, float startX, float endX) {
  beginShape();
  for (int i = 0; i < samples; i++) {
    vertex(
      map(i, 0, samples, startX, endX),
      map(waveform.data[i], -1, 1, 0, height)
      );
  }
  endShape();
}

// ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ //

void drawCircles() {
  translate(width / 2, height / 2);
  for (Circle[] row : circles) {
    for (Circle circle : row) {
      circle.display();
    }
  }
}

class Circle {
  float x, y;
  float size;
  float smoothSize;
  float angle;
  float angleSpeed;

  Circle() {
    angle = random(TWO_PI);
    x = cos(angle) * random(minDist, maxDist);
    y = sin(angle) * random(minDist, maxDist);
    size = random(10, 60);
    smoothSize = size;
    angleSpeed = map(size, 10, 60, 0.0002, 0.0004);
  }

  void display() {
    float volume = getVolume();
    smoothSize = lerp(smoothSize, size * volume, 0.1);
    strokeWeight(1);
    smooth();
    ellipse(x, y, smoothSize, smoothSize);
    angle += angleSpeed;
    x = cos(angle) * dist(x, y, 0, 0);
    y = sin(angle) * dist(x, y, 0, 0);
  }
}

float getVolume() {
  float leftVolume = max(abs(min(leftWaveform.data)), abs(max(leftWaveform.data)));
  float rightVolume = max(abs(min(rightWaveform.data)), abs(max(rightWaveform.data)));
  float volume = (leftVolume + rightVolume) * 5;
  return volume;
}