ProcessingでMacのマイク入力を扱う
こんなこと、やります。 - ProcessingからMacのマイク入力アクセスへのセキュリティ許可設定 - Processingでマイク入力に合わせた、さまざまなアニメーション - 音声データの波形表示 - FFTで周波数特性のリアルタイム表示

つかうもの
この記事でつかうものを説明します。
Processing
Processingをまだお持ちでない方は、 Processing.org からインストールしてください。 こちらでは、macOS上でProcessingバージョン3.4.5を動かしてます。 Processingでの図形描画などのやり方は説明いたしませんので、基礎的な技術は習得してください。
ProcessingのSoundライブラリのインストール
Processingでマイク入力を扱うために、Soundライブラリのインストールを行います。
Processingのメニューから「Sketch」→「Import Library」→「Add Library」へとすすみます。
そこで「sound」で検索し、「The Processing
Foundation」のSound
ライブラリをインストールします。
マイク入力アクセスへのセキュリティ許可設定
ProcessingからMacのマイク入力へアクセスできるように、セキュリティ許可設定をおこないます。
Processingでマイク入力を使ってみよう
macOSではデフォルトで、Processingから内蔵マイクへアクセスできません。Processingでマイク入力をつかえるように設定しましょう。
やること
Preferenceアプリで「Security &
Privacy」→「Privacy」→「Microphone」を表示します。すると次のように、Processingの項目がありませんでした。
Processingをここへ追加するため、次の作業をおこないます。
作業
ターミナルからProcessingを実行します。
$ /Applications/Processing.app/Contents/MacOS/Processing
AudioIn
を使ったプログラムを実行します。
すると、マイクへのアクセスを許可するアラートが表示されます。「OK」を押して許可します。
プライバシーにProcessingが追加され、Processingでマイク入力を扱えるようになりました。
以降、ターミナル経由でProcessingを立ち上げなくても大丈夫です。
さきほどの「マイク入力から音量を取得してみる」プログラムを再度実行して、マイク入力から音量を取得できるか試してみてください。
Processingでマイク入力を使ってみよう
それでは、macOSのマイク入力をProcessingで扱ってみましょう。
マイク入力から音量を取得してみる
まずは、マイク入力から音量を取得して、値を標準出力してみます。
ソースコード
import processing.sound.*;
;
AudioIn in;
Amplitude amp
void setup() {
= new AudioIn(this);
in .start();
in
= new Amplitude(this);
amp .input(in);
amp}
void draw() {
(255);
background
float a = amp.analyze();
if(a > 0) {
(a);
println}
}
Macで音量が表示されない場合は、最初に説明したマイク入力アクセスへのセキュリティ許可設定が正しくできているかご確認ください。
音量に合わせて円を描くアニメーション
さきほど取得した音量にあわせて、円が大きくなるアニメーションを作ってみます。

ソースコード
import processing.sound.*;
;
AudioIn in;
Amplitude amp
void setup() {
(400, 300);
size(0);
strokeWeight(255);
background(90);
frameRate
= new AudioIn(this);
in .start();
in
= new Amplitude(this);
amp .input(in);
amp}
void draw() {
(255);
background
float a = amp.analyze();
(#ff6347);
fill(width/2, height/2, 1000*a);
circle
}
音量に合わせて縦棒が伸びるアニメーション
サウンドメーターとして一般的な、音量に合わせて縦棒が伸びるアニメーションを作ってみました。

ソースコード
import processing.sound.*;
;
AudioIn in;
Amplitude ampfloat peakDetector;
void setup() {
(400, 300);
size(0);
strokeWeight(255);
background(90);
frameRate
= new AudioIn(this);
in .start();
in
= new Amplitude(this);
amp .input(in);
amp}
void draw() {
(255);
background
float a = amp.analyze();
(a);
displayBar}
void displayBar(float a) {
(255);
background(#00ced1);
fillfloat h = 5000 * a;
float w = 50;
float marginBottom = 10;
(width/2 - w/2, height - marginBottom - h, w, h);
rect}
ピークホールド付きアニメーション
さきほどのサウンドメータに、さらにピークホールドをつけてみました。
ピークホールドとは、最大音量を一定時間保持するものです。
ソースコード
import processing.sound.*;
;
AudioIn in;
Amplitude ampfloat peakDetector = 0;
int limitTime = 90;
int countTime = 0;
void setup() {
(400, 300);
size(0);
strokeWeight(255);
background(90);
frameRate
= new AudioIn(this);
in .start();
in
= new Amplitude(this);
amp .input(in);
amp}
void draw() {
(255);
background
float a = amp.analyze();
if(a > peakDetector && countTime <= limitTime) {
= a;
peakDetector = 0;
countTime } else if (countTime > limitTime) {
= 0;
peakDetector = 0;
countTime }
+= 1;
countTime int alpha = (int) (255 * (1.0 - float(countTime) / float(limitTime)));
//println(alpha);
(a, peakDetector, alpha);
displayBar}
void displayBar(float a, float peak, float alpha) {
(255);
background();
noStroke(208, 208, 208);
fillfloat h = 800 * a;
float w = 50;
float marginBottom = 10;
(width/2 - w/2, height - marginBottom - h, w, h);
rect
float peak_h = height - marginBottom - 800 * peak;
(255, 102, 102, alpha);
fill(width/2 - w/2, peak_h, w, 3);
rect
}
マイク入力の波形を表示
オシロスコープのように、マイク入力の音声データの波形を描くアニメーションです。

ソースコード
import processing.sound.*;
;
AudioIn in;
Amplitude amp;
Waveform waveform
int samples = 1024;
void setup() {
(400, 300);
size(0);
strokeWeight(255);
background(90);
frameRate
= new AudioIn(this);
in .start();
in
= new Waveform(this, samples);
waveform .input(in);
waveform}
void draw() {
(255);
background(0);
stroke(2);
strokeWeight();
noFill
.analyze();
waveform
();
beginShapefor(int i = 0; i < samples; i++)
{
(
vertex(i, 0, samples, 0, width),
map(waveform.data[i], -1, 1, 0, height)
map);
}
();
endShape}
サンプル数
samples
変数では、一度に描くサンプル数を設定できます。
#### map関数
map関数は、数値を現在のスケールから別のスケールへ変換します。
(変換したい数値, 現在の範囲の下限, 現在の範囲の上限, 変換後の範囲の下限, 変換後の範囲の上限) map
FFTで周波数特性をリアルタイムで表示
FFTで周波数特性をリアルタイムで表示します。
ただし、周波数はリニアスケールですので、音声データですと見づらいです。対数スケールに変換できればいいのですが、簡単にはいかなそうです。
ソースコード
import processing.sound.*;
;
FFT fft;
AudioIn inint bands = 128;
float[] spectrum = new float[bands];
void setup() {
(400, 300);
size(255);
background
= new FFT(this, bands);
fft = new AudioIn(this, 0);
in
.start();
in
.input(in);
fft}
void draw() {
(255);
background();
noStroke(208, 208, 208);
fill
.analyze(spectrum);
fftfloat bar_w = width / bands;
float margin = 10;
float start_h = height - margin;
for(int i = 0; i < bands; i++){
float bar_h = height * spectrum[i] * 10;
(bar_w*i + margin, start_h, bar_w, -bar_h);
rect}
}