[Processing] MinimとFFTで音量のリングを作る

#音に対する反応がほしい
誕生日を祝うのに音つけたいなって思うじゃん？
なのでやることは

- 曲の再生
- 音の取得
- 音程とか音量を取得

をイメージして最終目標は↓
円形に音量のブロックが同心円状に上下してほしい~~伝われ~~

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554244/594f0a0b-2c1e-fa07-bd59-8ba1b7bdab07.png)













#それではやっていきましょう
まずは横並びのブロック表現を作ります
参考にあったこれをブロック状にします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554244/3cd687f0-a35b-0e8a-1aa5-268944497c90.png)

















```Music_box.java
import ddf.minim.*;
import ddf.minim.analysis.*;

Minim minim;
AudioPlayer player;
FFT fft;
int fftSize;
PVector box = new PVector(40, 10);

void setup()
{
  size(1024, 480, P2D);
  colorMode(HSB, 360, 100, 100, 100);
  minim=new Minim(this);
  fftSize=512;
  player=minim.loadFile("POP STAR.mp3", fftSize);
  player.loop();
  player.setGain(-10);
  fft= new FFT(player.bufferSize(), player.sampleRate());
  frameRate(30);
}

void draw()
{
  //background(0);
  fill(0, 0, 0, 10);
  rect(0, 0, width, height);
  strokeWeight(2.0);
  fft.forward( player.mix );

  for (int  i =0; i < width/box.x; i++)
  {
    //↓ = fft.specSize()/(width/box.x) * i;
    float fftPos = fft.specSize()* i * box.x/width;
    float x = map(fftPos, 0, fft.specSize(), 0, width);
    float y = map(fft.getBand((int)fftPos), 0, 30.0, height, 0);
    float h = map(fftPos, 0, fft.specSize(), 0, 200); //音程次第で色を変える
    //float h = map(fft.getBand(i), 0, 20, 200, 0); //音量次第で色を変える
    fill(h, 100, 100);
    for (int j=height; j>y; j-=box.y) {
      rect(x, j, box.x, box.y);
    }
  }
}


```
mapメソッドで画面サイズに合わせてちょうどいいサイズにしてます

実行すると↓
#こんな
![Music Box.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554244/0f46b3a3-a90b-463d-f06c-d18b23beaeac.gif)


























#リングにしてみる
横向きにできたので、それを円形にします
rotateで回転させればいいだけですが、中心から距離を取る必要があるので、位置調整も必要です
mapの調整を画面サイズではなく、円周にして位置調整します

**ついでに「Q」「W」「E」「R」で見た目が変化します**

| キー | 変化|
|:-:|:-:|
| Q |  strokeのオンオフ |
| W |  内側をブロックにするか線にするか |
| E |  塗りつぶしオンオフ |
| R | 回転 |




#リングのプログラム

```Music_Ring.java
import ddf.minim.*;
import ddf.minim.analysis.*;

Minim minim;
AudioPlayer player;
FFT fft;
int fftSize;
float r = 0;
float size = 3.5f;

boolean strokeEnable = true, rotateR = false, inBox = true, fillEnable = true;


void setup()
{
  size(1200, 900, P2D);
  colorMode(HSB, 360, 100, 100, 100);
  frameRate(30);
  ellipseMode(CENTER);
  rectMode(CENTER);

  minim=new Minim(this);
  fftSize=512;
  player=minim.loadFile("POP STAR.mp3", fftSize);
  player.setGain(-10);
  fft= new FFT(player.bufferSize(), player.sampleRate());
}

void draw()
{
  background(0, 0, 100);
  translate(width/2, height/2);

  float radius = height/size;
  noFill();
  ellipse(0, 0, radius*2, radius*2);

  float roundCircle = 2 * PI * radius;
  PVector box = new PVector(roundCircle/90, 0);
  box.y = box.x/2;
  strokeWeight(box.x/10.0);
  fft.forward( player.mix );

  for (int  i =0; i < roundCircle/box.x; i++)
  {
    //↓ = fft.specSize()/(width/box.x) * i;
    float fftPos = fft.specSize()* i * box.x/roundCircle;
    float x = map(fftPos, 0, fft.specSize(), 0, 360-radians(box.x));
    float y = map(fft.getBand((int)(fftPos/PI)), 0, 80.0, 0, radius);
    float h = map(fftPos, 0, fft.specSize(), 0, 360);
    //float h = map(fft.getBand(i), 0, 20, 200, 0); //音量次第で色を変える

    if (strokeEnable) stroke(0, 0, 0);
    else stroke(h, 100, 100);

    if (fillEnable) noFill();
    else fill(h, 100, 100);

    //外側
    pushMatrix();
    rotate(radians(x + r));
    translate(0, -radius);
    if (inBox) {
      translate(0, -box.y/2);
      for (int j=0; j<y; j+=box.y) {
        rect(0, -j, box.x, box.y);
      }
    } else {
      stroke(h, 100, 100);
      line(0, 0, 0, -y);
    }
    popMatrix();

    //内側
    pushMatrix();
    rotate(radians(x + r));
    translate(0, -radius);
    if (inBox) {
      translate(0, box.y/2);
      for (int j=0; j<y; j+=box.y) {
        rect(0, j, box.x, box.y);
      }
    } else {
      stroke(h, 100, 100);
      line(0, 0, 0, y);
    }
    popMatrix();
  }


  if (rotateR)r = (r+1)%360;
}

void keyPressed() {
  switch(key) {
  case 'q':
    strokeEnable = !strokeEnable;
    break;
  case 'w':
    inBox = !inBox;
    break;
  case 'e':
    fillEnable = !fillEnable;
    break;
  case 'r':
    rotateR = !rotateR;
    break;

  case 'a':
    size -= 0.1f;
    break;
  case 'z':
    size += 0.1f;
    break;
  }
}

void mousePressed() {
  player.loop();
}

```



#こんな

![Music Ring.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554244/aeacc3e6-4c97-4e08-af1c-ea8e0e5325a3.gif)









#ありがとうございました
目的のものはできたので、誕生日祝う時に活用しようと思います

#参考
[Processingで音楽と同期するデジタルアートを作ってみた。できることも紹介 | テックキャンプ ブログ](https://tech-camp.in/note/technology/45369/)
[【Processing】FFTする]
(https://qiita.com/Beef1297/items/a20bec00c01a85daadd4)