「Libraries」タブから「Sound」「Video」をそれぞれ検索、「The Processing Foundation」が作者になっているものを選択してインストールしてください。
Processing 3を使っていて、かつ最近のmacOSのバージョンを使っている場合、セキュリティ関連の問題によりエラーが出てしまう場合があります。これは一時的な問題で、Processingの次期バージョンが出れば解消する見込みですが、しばらくはこちらの記事などを参考に各々で回避策をとりましょう。
音は空気の振動(圧力の変化=音圧)により生じます。音量とは、音圧の大きさの実効値(均すとどのくらいの大きさになるか換算したもの)です。
音量を扱うには、先ほどインストールしたSoundライブラリを利用します。Processingが公式で提供しているもので、音の入力を扱う際はお世話になります。
さっそくライブラリを組み込んだスケッチを準備しましょう。新しい概念がいくつか含まれていますが、しばらくは「こういうふうに書けば使えるのね」程度の理解で大丈夫です。
// マイクの音を扱うためのライブラリをインポート
import processing.sound.*;
// マイク
AudioIn in;
// 音量を取得してくれるもの
Amplitude amp;
void setup() {
size(600, 600);
strokeWeight(2);
fill(255, 200, 100);
// マイクを初期化(おまじない。現時点で深い意味は考えなくてOK)
in = new AudioIn(this);
in.start();
// 音量の取得を開始
amp = new Amplitude(this);
amp.input(in);
}
void draw() {
background(255);
// マイクの音量を取得して、
// 結果を変数 a に入れる
float a = amp.analyze();
// 音量の数値をコンソールに出力してみる
println(a);
}
書き終わったらスケッチを実行して、PCのマイクのそばで音を出してみてください。コンソールに数値が流れていきますが、音に応じて変化しているのが確認できるでしょうか。
この数値がマイクで拾った音量です。結果が文字では味気ないので、試しに円を描いてそのサイズに反映してみましょう。
(→sound_amp
)
void draw() {
…
// 音量を円のサイズに反映して描く
float sz = a * 1000;
ellipse(
width / 2, height / 2,
sz, sz
);
}
音圧は周期的に変化します。周波数の小さな音は低く、周波数の大きな音は高く聞こえます。
耳に入ってくる音は、いろいろな周波数の波が重なったものです。まぜこぜになった音を周波数ごとに分解し、どの周波数の音がどれだけ含まれているかを解析する方法があり、FFT(Fast Fourier Transform: 高速フーリエ変換)と呼ばれています。このFFTも、先ほどと同じSoundライブラリで利用できます。
FFTを組み込んだサンプルコードを見てみましょう。
(→sound_fft
)
// マイクの音を扱うためのライブラリをインポート
import processing.sound.*;
// マイク
AudioIn in;
// 周波数を解析してくれるもの
FFT fft;
// 解析する周波数帯域の数
int COUNT = 64;
// 周波数成分の解析結果を入れる変数
float[] spectrum = new float[COUNT];
void setup() {
size(600, 600);
fill(0);
noStroke();
// マイクを初期化(おまじない。現時点で深い意味は考えなくてOK)
in = new AudioIn(this);
in.start();
// 周波数解析を開始
fft = new FFT(this, COUNT);
fft.input(in);
}
void draw() {
background(255);
// マイクの音の周波数を解析して、
// 結果を変数 spectrum に入れる
fft.analyze(spectrum);
// spectrum[0], [1], ... に数値が入る
// spectrrm[0] が低い(周波数が小さい)音の成分、
// 配列の数字が増えるほど高い(周波数が大きい)音の成分
for (int i = 0; i < COUNT; i++) {
rect(
i * 10,
height / 2,
10,
-spectrum[i] * 1000
);
}
}
fft.analyze()
を実行すると、計算した周波数成分を float
の配列に入れてくれるので、これを利用すればOKです。今回の例では、画面中央から上に向かって四角形を描いて表現してみました。
周波数成分は一瞬で変化してしまうので、一昔前のビジュアライザーのように「ふた」をつけてみるのもよいでしょう。余裕があればチャレンジしてみてください。
(→sound_fft_bars
)
カメラの映像の取得についても、冒頭でインストールした公式のライブラリを利用します。
まずはコードを書いてみましょう。
// カメラの映像を描く
// カメラの映像を扱うためのライブラリをインポート
import processing.video.*;
// カメラ
Capture cam;
void setup() {
size(600, 600);
// カメラを初期化(おまじない。現時点で深い意味は考えなくてOK)
cam = new Capture(this);
cam.start();
}
void draw() {
// カメラが有効なら、映像を取り込む
if (cam.available()) {
cam.read();
}
background(0);
// 映像を描く(カメラの映像は画像 PImage と同じように扱える)
image(cam, 0, 0);
}
(→video
)
無事に映像は出たでしょうか?
ポイントは、取得したカメラの映像は画像(PImage)と同様に扱える1ということ。キャンバスに描いたり色を取得したりと、「画像」の章で覚えたことが活用できます。
コードを少し書き換えて、クリックした位置に映像を小さく描くようにしてみましょう。
// カメラの映像を扱うためのライブラリをインポート
import processing.video.*;
// カメラ
Capture cam;
void setup() {
size(600, 600);
background(255);
// カメラを初期化
cam = new Capture(this);
cam.start();
}
void mousePressed() {
// 映像を小さく描く
image(cam, mouseX, mouseY, 80, 60);
}
void draw() {
// カメラが有効なら、映像を取り込む
if (cam.available()) {
cam.read();
}
}
mousePressed()
に書いた処理と同じものを mouseDragged()
ブロックにも書くと、動画をインクとしたペンのようなものが作れますね。カーソルの軌跡が時間の流れを描くようになりました。
(→video_stamp
)
「整列」で扱ったグリッドに、映像から取得した色を適用すると、おもしろい効果が得られます。
(→video_grid
)
void draw() {
// カメラが有効なら、映像を取り込む
if (cam.available()) {
cam.read();
}
background(0);
for (int y = 0; y <= height; y += 40) {
for (int x = 0; x <= width; x += 40) {
fill(cam.get(x, y));
ellipse(x, y, 20, 20);
}
}
}
brightness()
や、彩度saturation()
をうまく組み合わせられるだろうか?
(→video_grid_brightness
)video_grid_brightness
)発展的な内容だが、実装をみるとCaptureクラスはPImageを継承しているので、PImageとして扱えることが確認できる ↩︎