Minim を使う!!
- かなり前に使ってみようとしたが、何故か上手くいかず挫折した。再挑戦
- 目標としては、マイク入力に対してリアルタイムで何か反応が返ってくるものを作りたい
Minim を知る
minim-Github
API reference
Minim ライブラリを使うことで、比較的簡単に、音声ファイルを流したり、マイク入力をリアルタイムで出力するとかができるようになるらしい。フーリエ変換もできるみたい。
// get the default STEREO input
AudioInput getLineIn()
// specifiy either Minim.MONO or Minim.STEREO for type
AudioInput getLineIn(int type)
// bufferSize is the size of the left, right,
// and mix buffers of the input you get back
AudioInput getLineIn(int type, int bufferSize)
// sampleRate is a request for an input of a certain sample rate
AudioInput getLineIn(int type, int bufferSize, float sampleRate)
// bitDepth is a request for an input with a certain bit depth
AudioInput getLineIn(int type, int bufferSize, float sampleRate, int bitDepth)
getLineIn
を使えば簡単に入力を取れるみたい. bitDepth
ってなんだ?
ビット深度(びっとしんど)は、ある単位あたりのビット数である。ビットの深さ、ビットデプス (bit depth) とも。
PCM音声やモノクロ画像などでは量子化ビット数そのもののことだが、カラー画像などの場合はRGBA各チャネルの量子化ビット数の合計であり、インデックスカラー方式(パレット方式)では量子化ビット数とは関係なくなる。(Wikiより)
いわゆる解像度みたいな感じ? かな今はそういうことにしとこう
とりあえずサンプルを見つつ使ってみる.( inputStream みたいなのを使って色々指定してるやつもあったけどあれは何なんだ?? )
使うのは、下の感じ
Minim のインスタンスを生成して、minim オブジェクトから getLineIn() で AudioInput を持ってくる(参照できるようにするって感じ)?
minim = new Minim(this);
// use the getLineIn method of the Minim object to get an AudioInput
in = minim.getLineIn();
i = 0, 1, 2, ... ,bufferSize;
in.left.get(i);
in.right.get(i);
get で何が取れるの?? 音の大きさ? 振動数? いろいろ気になるところがある。はてなが止まらない。
あ、バッファに入っている値か、普通にステレオのサンプリングした値持ってくる感じだ。left, rightだけじゃなくてmixもあるんだ。
(簡単にフーリエ変換できるじゃん...)
よし使ってみよう。
import ddf.minim.*;
Minim minim;
AudioInput in;
void setup() {
size(400, 400, P3D);
background(255);
minim = new Minim(this);
textFont(createFont("Calibri-Bold-24", 12));
in = minim.getLineIn(Minim.STEREO);
noStroke();
fill(0);
frameRate(10);
}
void draw() {
background(255);
text("bufferSize:"+in.bufferSize(), 10, 20);
for (int i=0; i < in.bufferSize(); i++) {
text(in.mix.get(i), width/2, 10*i);
println(in.mix.get(i));
}
}
情報が見てみたかったので、数値をただ表示させるだけにした.
なるほど、デフォルトだと bufferSizeは 1024
になってるし、バッファに入ってる数値はめちゃめちゃ小さい(むしろマイナスに行ってる)
import ddf.minim.*;
Minim minim;
AudioInput in;
void setup() {
size(400, 400, P3D);
background(255);
minim = new Minim(this);
textFont(createFont("Calibri-Bold-24", 12));
in = minim.getLineIn(Minim.STEREO);
noStroke();
frameRate(30);
}
void draw() {
float _old_buf_num = 0;
float _buf_num = 0;
float[] between = {};
background(255);
fill(#00FFFF);
lights();
pushMatrix();
translate(width/2, height/2, -100);
rotateY(PI/6);
rotateX(PI/6);
for (int i=0; i < in.bufferSize(); i++) {
_buf_num = abs(in.mix.get(i))*300;
if (abs(_buf_num - _old_buf_num) <= 2.0) {
continue;
}
if (_old_buf_num > _buf_num) between = _get_succesive_data(_buf_num, _old_buf_num);
else between = _get_succesive_data(_old_buf_num, _buf_num);
for(float j:between){
box(j);
}
}
popMatrix();
}
float[] _get_succesive_data(float from, float to) {
float[] between = {};
for (float j=from; j <= to; j+=.1) {
between = append(between, j);
}
return between;
}
途中経過だけれど、bufferの値に応じて、boxの大きさを変更するプログラムにした。
bufferの値は離散値だから、やっぱり変化が一瞬とかになってちょっと気持ち悪い、frameRateを上げるとすごい早送りみたいに変化するからその対応は避けたい。
なので、細かい振動をなくすために、変化量が少ないときは、 continue にするとか、データを二つ渡してその間を.1ずつ埋めて配列で返すという関数 _get_succesive_data
を作ったりしたけど上手くいかず...
まず、変化量でcontinueにしても、結局振動はしてしまう。振動の幅が変わるだけ、できるだけ連続値にしよう作戦も、動作に変化が見られず...
デフォルト値を用意しておいて、閾値をセットしそれを超えたら,スムーズに変化するようにするというのができそうな気がするのでやってみる。
うーん上手くいかない。調査を進めよう。
getInputStream を見てみる
調べてて、getInputStream
を使っているのを見かけたので、getLineIn
と何が違うのか調べる.
Get the input as an AudioStream that you can read from yourself, rather than wrapped in an AudioInput that does that work for you.
AudioInput がやってくれることを 自分で読みに行くみたいな感じ
つまり、より深くまでやるなら AudioStream を使う必要がでてくるのかもしれないけど、今のところ違いも分かっていないから AudioInput を使う形でいい気がする...
out = minim.getLineOut();
AudioStream inputStream = minim.getInputStream(
out.getFormat().getChannels(),
out.bufferSize(),
out.sampleRate(),
out.getFormat().getSampleSizeInBits());
in = new LiveInput(inputStream);
in.patch(out);
こんな感じで使われていた。なんか、out に合わせてるって感じなのか?? いや、それは getLineIn でもできる。
LiveInput の方か見てみよう。ついでに getLineOutも
Signature
AudioOutput getLineOut()
AudioOutput getLineOut(int type)
AudioOutput getLineOut(int type, int bufferSize)
AudioOutput getLineOut(int type, int bufferSize, float sampleRate)
Returns
an AudioOutput that can be used to generate audio
音を出力するAudioOutput を持ってくるもの( 文字どおりやんけ )どちらかというと、 generate
がぴったり合ってるかもしれない。あと、音声を生成するときは patch をしないといけないらしい。
LiveInput リファレンスに見当たらなかった。githubの方を見てみると、ugenの下にあった。ugenってそもそもなんだ?
あ、リファレンス、メニューのugens のページにあった。
UGen は Unit Generator の略で、波を生成したり、加工したりするのにかかわってる感じか、いやよくわからん。output に音声をpatchすることもできてそうすると、音声が再生されるって感じか。いろいろフィルタ掛けたり、0から音を作るときは UGenを使う必要がありそうだなという感じ
ただ、入力を受けてそのまま流すなら、別に使わなくていいんじゃない??
流すためには patch
をしないといけない、patch はUGen のメソッドだからこういうことをしているのかもしれないけど、
いや、使わないといけないのか、AudioOutput を使えるのはugen に対してだ、AudioInputは使えねぇや。
なるほど、出力するためには AudioStream を持ってくる必要があるんだ。しかしながら、今回はマイク入力を受け取るだけでよいので、getLineIn を使う。
入力や出力に関してはだいたい分かった!!!
UI
どういうUIを作るか
-
音にスムーズに合わせるというのはちょっと触ってみて難しそうかなぁ、Amplitude を取ってきて、連続的な変化をするようにできれば綺麗にできたりするのかな... 結構デフォルメが大事だと気付いた。バッファの値を二乗すると変化が綺麗に見える。
-
入力に対して、いくつかの要素に対して閾値を設けてそれに応じたなんらかの変化をする。
- 例えば、Amp, Freq, 変化の幅とかにそれぞれ閾値をつけて、この要素が閾値を超えたら、こういう変化、こっちはこういう変化みたいにすれば、面白いかも
-
それか、UIとしての面白さ、綺麗さを提供する。
- 入力された音声によって、ビルが建っていき、街が形成されていくとか..
- 入力があると、ランダム(ここは未定)な場所に建物が建て始めて、入力されてる間は伸び続けて、入力が途切れたら、高さが決まるみたいにすると面白いかも...
- 波紋が広がってフェードアウトしていくのを重ねたり...(ありがちだなぁ)
- 入力された音声によって、ビルが建っていき、街が形成されていくとか..
-
UI は後々考えるとして,とりあえず,Minimの使い方は分かった!!!!!
参考
http://aa-deb.hatenablog.com/entry/2016/11/03/160003
http://code.compartmental.net/minim/index_ugens.html
https://github.com/ddf/Minim/tree/master/src/main/java/ddf/minim/ugens
http://aa-deb.hatenablog.com/entry/2016/11/03/160003