CGプログラミング演習
11 プログラミングによる音の視覚的表現[最終課題]

ついに、最終課題の説明です。
中間課題同様、テンプレートプログラムを用意していますので、そちらを利用してください。
テンプレートプログラムは、それなりに複雑ですが、少しずつでもよいので、自分なりにアレンジする作業をこころみ、積み重ねていってほしいと思います。
プログラムそのものを学ぶというよりは、プログラミングしながら、あるグラフィックを作り込んでいくという環境に浸ってもらえればと思います。

1 テンプレートプログラム

  • ダウンロードしたプログラムをアレンジして、最終課題を制作してもらいます。

1.1 プログラムのソースコード

  • 以下のソースコードのうち、黄色の背景になっている部分を変更することからはじめるとわかりやすいかと思います。
  • 可能ならば、その他の部分にも手を加えてみてください。
// OpenGL を使用する準備です
import processing.opengl.*;
import javax.media.opengl.GL; 

// Minim を使用する準備です
import ddf.minim.analysis.*;
import ddf.minim.*;

// Minim の最大音量を定めます
int BUFSIZE = 512;

// Minim の変数を用意します。
Minim minim;

// オーディオ入力の変数を用意します
AudioInput in;

// FFTの変数を用意します
FFT fft;

// OpenGL の変数を用意します
GL gl;

// 最終課題(kadai2)ライブラリを使用するための変数を用意します
K2 k2;

float angle = 0;      
float offset = 0;     

// プログラム開始時の事前準備です
void setup()
{
  // キャンバスサイズを定めるとともに、OpenGL の使用を宣言します
  size(1200, 800, OPENGL);

  // Framerate を定めます
  frameRate(24);

  // カラーモードを HSB に指定します
  colorMode(HSB, 360, 100, 100, 100);

  // OpenGL を有効にします
  gl = ((PGraphicsOpenGL)g).gl;
  gl.setSwapInterval(1);

  // Minim を生成します
  minim = new Minim(this);

  // minim からオーディオ入力源を取得します
  in = minim.getLineIn(Minim.STEREO, BUFSIZE);

  // FFT を生成します
  fft = new FFT(in.bufferSize(), in.sampleRate());

  // 背景を黒く塗りつぶします
  background(0);

  // 最終課題ライブラリを使用可能にします。
  // この時、あらかじめ定めておいたMinim の最大音量(BUFSIZE)を引数として与えます
  k2 = new K2(BUFSIZE);

  // 3D空間内での光の照射方法を定めます
  ambientLight(0, 0, 50);
  directionalLight(0, 0, 100, -1, 0, 0);
}

// 描画内容を定めます
void draw()
{
  // 背景を黒く塗りつぶします
  background(0);

  // OpenGL を利用して加算混色します
  gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE);

  // 描画内容を画面中央に描きます
  translate(width/2, height/2);

  // FFT を実行します
  fft.forward(in.mix);

  // 最終課題用の描画関数を実行します
  drawShape(fft);

  // 最終課題用の描画関数を実行します
  drawGraphic(fft);
}

// プログラム終了時の処理を定めます
void stop()
{
  minim.stop();
  super.stop();
}

// 最終課題でカスタマイズする関数その 1
void drawShape(FFT fft)
{
  float specSize = fft.specSize();
  float getBand;

  // 描画するシェイプを指定します。
  // 
  // 指定できるのは下記の通りです:
  //    POINTS
  //    LINES
  //    TRIANGLES
  //    TRIANGLE_FAN
  //    TRIANGLE_STRIP
  //    QUADS
  //    QUAD_STRIP
  // 
  // 詳しくはマニュアルを参照してみてください
  // http://www.technotype.net/processing/reference/beginShape_.html
  beginShape(QUAD_STRIP);

  for (int i = 0; i < specSize; i += 16)
  {
    // 音量を取得しておきます
    getBand = fft.getBand(i);

    // 描画位置を定めます
    Position pos = k2.spring(width, height, i, specSize, getBand);

    // 音量に応じて色相を定めます
    float h = map(i, 0, specSize, 0, 360);

    // 円の大きさを定めます
    float r = getBand * i / 4.0 + 30.0;

    // 塗りつぶし/線の色を定めます
    stroke(h, 50, 100, 50);
    fill(h, 100, 100, 10);

    // マウス位置に応じて視点を変更します
    pushMatrix();
    rotateY(radians(angle * mouseX/float(width) + offset*i));
    rotateX(radians(angle * mouseY/float(height) + offset*i));
    rotateZ(radians(angle / 10.0 + offset * i));

    // 描画する頂点を指定します
    vertex(pos.x + r, pos.y + r, random(r));

    // マウス位置に応じて変更した視点を元に戻しておきます
    popMatrix();
  }

  endShape();

  angle++;
}

// 最終課題でカスタマイズする関数その 2
void drawGraphic(FFT fft)
{
  float specSize = fft.specSize();
  float getBand;

  for (int i = 0; i < specSize; i += 1)
  {
    // 音量を取得しておきます
    getBand = fft.getBand(i);

    // 描画位置を定めます
    Position pos = k2.spring(width, height, i, specSize, getBand);

    // 音量に応じて色相を定めます
    float h = map(i, 0, specSize, 0, 360);

    // 円の大きさを定めます
    float r = getBand * i;

    // マウス位置に応じて視点を変更します
    pushMatrix();
    rotateY(radians(angle * mouseX/float(width) + offset*i));
    rotateX(radians(angle * mouseY/float(height) + offset*i));
    rotateZ(radians(angle / 10.0 + offset * i));

    // 円を描画してみます
    stroke(h, 50, 100, 50);
    fill(h, 100, 100, 50);
    ellipse(pos.x, pos.y, r, r);
    
    // 線を描画してみます
    stroke(h, 50, 100, 50);
    noFill();
    beginShape(LINES);
        vertex(0, 0, r);
        vertex(pos.x, pos.y, r);
    endShape();
    
    // マウス位置に応じて変更した視点を元に戻しておきます
    popMatrix();
  }

  angle++;
}

2 描画部分で使用している変数の意味

  • 描画部分で使用している変数の意味は、下記の通りです。
    • r: 音階別の音量(0〜)
    • h: 色相(0〜360)
    • pos.x: 基準点(x軸)
    • pos.y: 基準点(y軸)
  • このうち、pos.x, pos.y は、バネの動きを反映した位置を指定する場合に必要です。

3 最終課題の提出について

  • ダウンロードしたプログラムを、アレンジして、自分なりの音の視覚化プログラムを開発してください。
  • 提出の締め切りは、最終講義日(次週月曜日)の1コマ目終了時とします。
  • 提出方法は、これまでと同様、プロジェクトフォルダの名前を出席番号順にかえてもらい、こちらで用意したUSBにコピーしてもらう方法をとります。