P5.jsでオーディオビジュアライズ

[GRAND FRONTEND OSAKA 2016](http://kfug.jp/gfo2016/)のハッカソンで作りました、p5.jsを使用したオーディオビジュアライズです。

Macのマイクから音を拾って、ボリュームによって絵の大きさが変化します。
先に完成図とプログラム。ブラウザはChromeでのみ検証済みです。

![sound.png](https://qiita-image-store.s3.amazonaws.com/0/72056/51cfdb53-7822-c18c-410e-4093308b162a.png)

```index.html
<!DOCTYPE html>
<html>
<head>
  <title>p5j</title>
  <meta charset="UTF-8">
</head>
<body>
<style type="text/css">
  
body{
  background: #000;
}

</style>

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.3/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.3/addons/p5.sound.min.js"></script>
<script src="audio_visual.js" type="text/javascript"></script>

</body>
</html>
```

```audio_visual.js
var theta;
var colorH = 0;
var startColor = 0;
var rotate_arg;
var mic;

function setup() {
  createCanvas(windowWidth, windowHeight);

  background(0);
  colorMode(HSB,100);
  colorH = random(100);
  startColor = colorH;
  strokeWeight(1);
  rotate_arg = random(3);
 
  mic = new p5.AudioIn();
  mic.start();
}

function draw() {
  background(0,5);
  frameRate(30);
  stroke(colorH,80,255,10);

  //macから音声を取得
  var sound_volume = mic.getLevel();
  var change_sound_volume = map(sound_volume,0,1,0,1000);
  theta = radians(change_sound_volume);

  translate(width/2,height/2);

  branch(change_sound_volume);
  
  // 色相の調整
  colorH = colorH + 4;
  
  if(abs(colorH - startColor) > 25){
    colorH = startColor;
  }

}


function branch(h) {

  //ボリュームによってhの値を変化させる
  h *= 0.4;
  
  if (h > 2) {
    push();    
    rotate(theta);
    strokeWeight(h);
    line(0, 0, 0, -h);
    translate(0, -h);
    branch(h);
    pop();
    
    push();
    rotate(-theta);
    strokeWeight(h);
    line(0, 0, 0, -h);
    translate(0, -h);
    branch(h);
    pop();

    push();
    rotate(theta+radians(180));
    strokeWeight(h);
    line(0, 0, 0, -h);
    translate(0, -h);
    branch(h);
    pop();

    push();
    rotate(-theta-radians(180));
    strokeWeight(h);
    line(0, 0, 0, -h);
    translate(0, -h);
    branch(h);
    pop();

  }
}
```

経緯やプログラムの解説を記述していきます。

# 音声で変化させたい絵を作成する
今回のプログラムはProcessingのExampleにある[Treeのスケッチ](https://processing.org/examples/tree.html)から、木のフサフサしている部分だけ流用しています。

![tree.png](https://qiita-image-store.s3.amazonaws.com/0/72056/09673b29-039a-4568-e61f-405fa7e1faa4.png)

ProcessingのサイトではProcessing用のコードで記述されているので、p5.js用に書き換える必要があります。
今回はメンターのKeitaさんがコードを書き換え、[GitHubにup](https://github.com/p5aholic/GFO2016/tree/master/sketch05)してくださいました。

他にもProcessingとp5.jsでの書き方の違いを記述しているサイトがあるので、そのあたりも参考になるかと思います。

branch関数の解説についてはProcessingのプログラムに記載されているので、ここでは割愛します。

## jsの読み込み
作成したjsとp5.jsのファイルを、htmlに読み込むのを忘れないようにしましょう。
p5.jsはCDNで読み込むことにしました。

p5.jsの公式サイトにある[ダウンロードページ](https://p5js.org/download/)から、Single Files > CDN を選択して、`https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.3/p5.min.js`と
`https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.3/addons/p5.sound.min.js`をコピーし、htmlに貼り付けます。
単純にp5.jsを使いたいのであれば`p5.min.js`だけで事足りますが、音声認識も使うので`p5.sound.js`も読み込みます。

```index.html
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.3/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.3/addons/p5.sound.min.js"></script>
<script src="audio_visual.js" type="text/javascript"></script>
```

これでブラウザ上でも表示できるようになります。

# マイクからの入力
Processingのコードではマウスのx座標によって、木が閉じたり開いたりしていましたが、このマウスのx座標をMacのマイクからの入力に変更します。

```audio_visual.js
var mic;

function setup() {
  mic = new p5.AudioIn();
  mic.start();
}

function draw() {

  //macから音声を取得
  var sound_volume = mic.getLevel();
  var change_sound_volume = map(sound_volume,0,1,0,1000);

  branch(change_sound_volume);
}
```
`mic.getLevel()`は0~1の間の値で返ってくるので、`map`関数を用いてマイクからのボリュームを0~1000まで引き延ばし、変数`change_sound_volume`に代入します。
毎フレーム`branch`関数を呼び出し、引数に`change_sound_volume`を入れることでボリュームの大きさによってビジュアルが変化するようにしています。

# 微調整
あとは好みで線の太さ・回転・色などの調整です。

ボリュームによって線の太さや回転を変化させ、また、毎フレーム異なる色相でも整った見た目になるようにしました。
`startColor`と`colorH`との値を比較し、差が出過ぎないように調整しています。

```
if(abs(colorH - startColor) > 25){
    colorH = startColor;
  }
```

# 参考
[p5.js](https://p5js.org/)
[Processing](https://processing.org/)
[p5aholic/GFO2016](https://github.com/p5aholic/GFO2016/tree/master/sketch05)
[Processing transition](https://github.com/processing/p5.js/wiki/Processing-transition)