minimはProcessing1.0以降のバージョンで標準のサウンドライブラリです。
それまでのライブラリが、ステレオ再生できなかったのに対して、minimはステレオになっています。
短いコードでオーディオのコントロールができます。
Processingをダウンロードした時点で、いくつかのサンプルは入っているのですが、以下のサイトの「Minim 2.0.2 full distro」をダウンロードすると、かなりの数のサンプルが入手できます。ちなみに、現在の最新バージョンは2.1.0 betaです。
http://code.compartmental.net/tools/minim/
また、上記のサイトはminimの全ての情報が載っています。英語なので大変かもしれませんが、もしminimを使っていて分からないことがあったら、まずはこのサイトを覗いてみましょう。
さて、まずは基本中の基本である音声ファイルの再生です。再生自体は短いコードで済みますが、最後にサウンドデータをプログラムの中で終了させることを忘れないで下さい。
また、このサンプルは、pdeファイルと同じ階層にdataフォルダを作り、そこにgroove.mp3がないと動きません。気をつけてください。
groove.mp3のダウンロード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | import ddf.minim.*; //minimライブラリのインポート Minim minim; //Minim型変数であるminimの宣言 AudioPlayer player; //サウンドデータ格納用の変数 void setup() { size(100, 100); minim = new Minim(this); //初期化 player = minim.loadFile("groove.mp3"); //groove.mp3をロードする player.play(); //再生 } void draw() { background(0); } void stop() { player.close(); //サウンドデータを終了 minim.stop(); super.stop(); } |
ひとまず音楽をプログラムから再生させることは成功しましたね。ここで、音の原理について考えてみましょう。
おそらく、皆さんは音が何かをそんなに意識的に考えたことはないでしょう。しかし、音がどのようにして発生して私達がどのように知覚しているかを考えることは、自分自身が音を作っていく過程において非常に重要です。全ては基本を理解する必要があるのです。
では、音とは一体なんでしょう。それは、「振動」です。例えば、物を叩けばそのものは振動しますが、その振動が実は空気を振動させ、あなたの鼓膜を振動させて・・・というように振動が伝搬していく訳です。通常人間はそんなことを意識して音は聞いていませんが、音を知覚するといことは、振動を知覚するということなのです。
参考サイト
http://poem.kagebo-shi.com/audio1/a01.html
音の正体が振動であることを話しましたが、その振動は「波」として表されます。つまり、音は全て「波形」を持っています。実際に波形を見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | import ddf.minim.*; //minimライブラリのインポート Minim minim; //Minim型変数であるminimの宣言 AudioPlayer player; //サウンドデータ格納用の変数 int waveH = 100; //波形の高さ void setup() { size(512, 200); minim = new Minim(this); //初期化 //バッファ(メモリ上のスペース。この場合は512要素のfloat型の配列)を確保し、サウンドファイルを読み込む。バッファは指定しなければ1024。 player = minim.loadFile("groove.mp3", 512); player.play(); //ファイルを再生 } void draw() { background(0); stroke(255); //波形を描く //left.get()とright.get()が返す値は-1から+1なので、見やすくするために、 //waveH(初期値は100)を掛けている。 //サウンドファイルがモノラルの場合は、left.get()とright.get()が返す値は同じ。 for(int i = 0; i < player.left.size()-1; i++) { point(i, 50 + player.left.get(i)*waveH); //左の音声の波形を画面上に描く point(i, 150 + player.right.get(i)*waveH); //右 〃 } } void stop() { player.close(); minim.stop(); super.stop(); } |
色んな音声ファイルを試してみてください。mp3以外にもwave, aiff, auなど様々なフォーマットのファイルが再生できます。
さて、波形を見ましたが、この波形は音をどのように表しているのでしょうか。
次の図を見てください。

縦軸が振幅(音の大きさ)、横軸が波長(音の高さ)です。この縦軸の高さが高ければ高い程、大きな音になります。また、横軸の波の密度が高ければ高いほど、高い音になります(次の図を参照)。

波形を見たときはこのような情報が視覚化されていると考えてください。
しかし、音には「大きさ」と「高さ」に加えてもう一つの要素があります。それは「音色」です。この音色を理解しないことには、私達が普段どのような音を聞いているのかが分かりません。
上記の波形は、実は純音と呼ばれるもので、その名の通り純粋な音です。よって波形もきれいなカーブを描いています。
以下のファイルを前述のプログラムで再生してみましょう。
sin00900.AIF
きれいな波形が出るはずです。これは、900Hz(周波数については後で説明します)の周波数の純音を再生しています。
しかし、実際に世の中にあふれている音は、こんなに純粋なものではありません。様々な周波数が重なってできたものです。このような音を複合音と呼びます。
ここで、実際に純音を合成して音を作ってみましょう。
授業名の中でMax/MSPを使って実験
scope_simple
もう少し色んな音の波形を見ていきましょう。次はマイク入力です。通常ノートパソコンなどはマイクが入っているので、そのまま再生しても機能しますが、デスクトップパソコンはマイクがついていない場合が多いので、気をつけてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | import ddf.minim.*; //minimライブラリのインポート Minim minim; //Minim型変数であるminimの宣言 AudioInput in; //マイク入力用の変数 int waveH = 50; //波形の高さ void setup() { size(512, 200); minim = new Minim(this); //初期化 //バッファ(メモリ上のスペース。この場合は512要素のfloat型の配列)を確保し、マイク入力用の変数inを設定する。 in = minim.getLineIn(Minim.STEREO, 512); } void draw() { background(0); stroke(255); //波形を描く //left.get()とright.get()が返す値は-1から+1なので、見やすくするために、 //waveH(初期値は100)を掛けている。 for(int i = 0; i < in.bufferSize()-1; i++) { point(i, 50 + in.left.get(i)*waveH); //左の音声の波形を画面上に描く point(i, 150 + in.right.get(i)*waveH); //右 〃 } } void stop() { in.close(); minim.stop(); super.stop(); } |
色んな音をマイクから入力してみてください。例えば、口笛は純音に近い波形が出るのに、自分の声は、先ほどMax/MSPで合成した波形のように、不規則な波形になっていませんか?
これは、人間の声が様々な周波数の波形が合成された音だということを証明しています。
身の回りの音がどのような性質を持っているのか確かめてみましょう。
では、波形の合成はプログラム上ではどのような式で求められるのでしょうか。
これは以外に簡単です。ここでは、サウンドの波形ではなくsine, cosineで描かれた波形を使います。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | float x, y1, y2; //x, y座標 float A1; //振幅 float A2; float w1; //角周波数 float w2; float p; //初期位相 float t; //時間 float speed; //アニメーションのスピード float reSize = 35.0; //画面の拡大率(数値を上げるとグラフック全体が大きくなる) void setup() { size(480, 300); background(255); noStroke(); smooth(); fill(0); A1 = 1.0; //振幅を設定 A2 = 1.5; //振幅を設定 w1 = 2.8; //角周波数を設定 w2 = 1.67; //角周波数を設定 p = 0.0; //初期位相を設定 t = 0.0; //時間を初期化 speed = 0.03; //描画速度を設定 } void draw() { //点のアニメーション x = t; y1 = -A1*sin(w1*t - p); //processingのy座標は数学の座標と反対のため、-にする y2 = -A2*sin(w2*t - p); //1つ目のサイン波を描画 fill(255, 0, 0, 50); ellipse(x*reSize, y1*reSize+height/2, 3, 3); //円を描く //2つ目のサイン波を描画 fill(0, 0, 255, 50); ellipse(x*reSize, y2*reSize+height/2, 3, 3); //円を描く //合成したサイン波を描画 fill(0); ellipse(x*reSize, (y1+y2)*reSize+height/2, 3, 3); //円を描く t += speed; //時間を進める } |
上のような結果になるはずです。ここでは、赤の波形と青の波形が合成されて黒の波形になっています。
コードを見ると、実はy1とy2が足されているだけですね?
このような波形の合成が繰り返されることによって、より複雑な波形が生まれてくるのです。
それでは、Processingでサイン波を作って実際に出力してみましょう。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | import ddf.minim.*; //minimライブラリのインポート import ddf.minim.signals.*; //サイン波を発生させるためのライブラリ Minim minim; AudioOutput out; //サウンド生成用の変数 SineWave sine; //サイン波生成用の変数 float waveH = 50; //振幅 void setup() { size(512, 200); minim = new Minim(this); //サウンド出力用変数。 out = minim.getLineOut(Minim.STEREO); //サイン波用の変数。バッファの初期値は1024、サンプルレートは44100、ビット深度は16ビット。 //これは、0~65535の段階に分割されるということです。 sine = new SineWave(440, 0.5, out.sampleRate()); //ポルタメントスピード(音程の変化の滑らかさ)を200ミリセカンドに設定。小さい値になればなるほど、精度が上がる。 sine.portamento(200); out.addSignal(sine); } void draw() { background(0); stroke(255); // 波形を描く for(int i = 0; i < out.bufferSize()-1; i++) { point(i, 50 + out.left.get(i)*waveH); //左の音声の波形を画面上に描く point(i, 150 + out.right.get(i)*waveH); //右 〃 } } void stop() { out.close(); minim.stop(); super.stop(); } |
それでは、次に上記のサイン波のコードを元にして2つの波を合成してみます。これは非常に簡単です。複数のサイン波をそれぞれ宣言(sine1, sine2)して、同じように実行すればいいのです。これは、outという変数に一緒に格納されるので、自動的に合成されて出力されます。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | import ddf.minim.*; //minimライブラリのインポート import ddf.minim.signals.*; //サイン波を発生させるためのライブラリ Minim minim; AudioOutput out; //サウンド生成用の変数 SineWave sine1, sine2; //サイン波生成用の変数 float waveH = 50; //振幅 void setup() { size(512, 200); smooth(); minim = new Minim(this); //サウンド出力用変数。 out = minim.getLineOut(Minim.STEREO); //サイン波用の変数。バッファの初期値は1024、サンプルレートは44100、ビット深度は16ビット。 //これは、0~65535の段階に分割されるということです。 sine1 = new SineWave(440, 0.5, out.sampleRate()); sine2 = new SineWave(1000, 0.2, out.sampleRate()); //ポルタメントスピード(音程の変化の滑らかさ)を200ミリセカンドに設定。小さい値になればなるほど、精度が上がる。 sine1.portamento(200); sine2.portamento(200); out.addSignal(sine1); out.addSignal(sine2); } void draw() { background(255); stroke(0); // 波形を描く for(int i = 0; i < out.bufferSize()-1; i++) { point(i, 50 + out.left.get(i)*waveH); //左の音声の波形を画面上に描く point(i, 150 + out.right.get(i)*waveH); //右 〃 } } void stop() { out.close(); minim.stop(); super.stop(); } |
Sorry, comments are closed.