サウンド(Essライブラリ)

さて今回はサウンドの実習です。
ここでは、Essというライブラリを使ってみます。ここではインストールの仕方は説明しませんので、自力でやってください。

1. サイン波

まずは、サイン波を出してみましょう。サイン波は、音の中で一番単純なものです。
まずは、220ヘルツのサイン波を出すコードを書いてみましょう。

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
import krister.Ess.*;
 
AudioChannel myChannel;
SineWave myWave;
 
void setup() {
  size(300,300);
 
  //Essをスタートさせる
  Ess.start(this);
 
  //myChannelオブジェクトを作成
  myChannel=new AudioChannel();
  //myChannelを初期化。この場合2000ミリ秒 = 2秒
  myChannel.initChannel(myChannel.frames(2000));
 
  myWave=new SineWave(220,.5);      //SineWave(周波数, ボリューム[0-1の間])
  myWave.generate(myChannel);    //波形を生成し、myChannelに割り当てる
  myChannel.volume(300);    //ボリュームは300
 
  //スムーズにパンする
  myChannel.play(Ess.FOREVER);    //ループ再生
 
  //ボリュームを調整する。ボリューム[0-1の間], 調整する時間間隔[単位:ミリ秒]
  myChannel.fadeTo(.5,500);
}
 
void draw() {
 
}
 
//終了する前にクリーンアップする
public void stop() {
  Ess.stop();
  super.stop();
}

簡単ですか?次は少し複雑です。
マウスのX軸の動きによって、左から聞こえたり右から聞こえたりします。更にY軸の動きによって、音量が変化します。

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//This code has been arranged by Yasushi Noguchi. Last updated on July 1, 2008.
 
// Pan and Volume
// by Krister Olsson <http ://www.tree-axis.com>
 
// Generates a looping sine wave and pink noise. 
// Pan and volume are controlled by mouse position
 
// Created 1 May 2005
// Updated 3 May 2006
 
import krister.Ess.*;
 
AudioChannel myChannel;
SineWave myWave;
 
void setup() {
  size(300,300);
 
  //Essをスタートさせる
  Ess.start(this);
 
  //myChannelオブジェクトを作成
  myChannel=new AudioChannel();
  //myChannelを初期化。この場合2000ミリ秒 = 2秒
  myChannel.initChannel(myChannel.frames(2000));
 
  myWave=new SineWave(220,.5);      //SineWave(周波数, ボリューム[0-1の間])
  myWave.generate(myChannel);    //波形を生成し、myChannelに割り当てる
  myChannel.volume(0);    //ボリュームは0
 
  //スムーズにパンする
  myChannel.smoothPan=true;
  myChannel.play(Ess.FOREVER);    //ループ再生
 
  //ボリュームを調整する。ボリューム[0-1の間], 調整する時間間隔[単位:ミリ秒]
  myChannel.fadeTo(.5,500);
  frameRate(30);
}
 
void draw() {
  background(0);
  stroke(255);
 
  int x = mouseX;
  int y = mouseY;
 
  //パンとボリュームがマウスの動きで変化する。パンは-1から1の値を取る。
  float newPan = (x/(float)width*2)-1;
  float newVolume = y/(float)height;
 
  //もし、パンしていなければ、newPanの値ごとにパンする(単位 ミリ秒)
  if (!myChannel.panning) myChannel.panTo(newPan,500);
  //newVolumeの値ごとにボリュームが変化する(単位 ミリ秒)
  if (!myChannel.fading) myChannel.fadeTo(newVolume,500);
 
  line(x, 0, x, height);    //縦の線
  line(0,y,width,y);    //横の線
}
 
//終了する前にクリーンアップする
public void stop() {
  Ess.stop();
  super.stop();
}

ここで、いくつか重要な概念が登場します。
一般的に言われる音の三要素は、大きさ(Loudness)、高さ(Pitch)、音色(Tone)です。
ここでは、ボリューム=音の大きさ、周波数=高さが出てきます。
ですから、ボリュームは言うに及ばず、サンプルでは220に設定されている周波数を操作すると、音の高低が変化します。

クイズ マウスのy軸の値を変化させて周波数110から440の値をマウスの位置によって変化させなさい。

解答

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
49
50
51
52
53
54
55
56
57
58
59
60
import krister.Ess.*;
 
AudioChannel myChannel;
SineWave myWave;
float frequency = 0.0;
 
void setup() {
  size(300,300);
 
  //Essをスタートさせる
  Ess.start(this);
 
  //myChannelオブジェクトを作成
  myChannel=new AudioChannel();
  //myChannelを初期化。この場合2000ミリ秒 = 2秒
  myChannel.initChannel(myChannel.frames(10000));
 
  myWave=new SineWave(220,.5);      //SineWave(周波数, ボリューム[0-1の間])
  myWave.generate(myChannel);    //波形を生成し、myChannelに割り当てる
  myChannel.volume(0);    //ボリュームは0
 
  //スムーズにパンする
  myChannel.smoothPan=true;
  myChannel.play(Ess.FOREVER);    //ループ再生
 
  //ボリュームを調整する。ボリューム[0-1の間], 調整する時間間隔[単位:ミリ秒]
  myChannel.fadeTo(1.0,500);
  frameRate(30);
}
 
void draw() {
  background(0);
  stroke(255);
 
  int x = mouseX;
  int y = mouseY;
 
  //パンとボリュームがマウスの動きで変化するパンは-1から1の値を取る。
  float newPan = (x/float(width)*2)-1;
 
  //もし、パンしていなければ、newPanの値ごとにパンする(単位 ミリ秒)
  if (!myChannel.panning) myChannel.panTo(newPan,500);
 
  myWave.frequency=frequency;
  myWave.generate(myChannel);
 
  line(x, 0, x, height);    //縦の線
  line(0,y,width,y);    //横の線
}
 
//終了する前にクリーンアップする
public void stop() {
  Ess.stop();
  super.stop();
}
 
void mousePressed(){
  //周波数は110から440の間を行き来する
  frequency = mouseY/(float)height*(440-110) + 110;
}

2. サウンドファイルの再生

次は、サウンドファイルが外部から読み込んで再生する方法です。これは、かなり短いコードで書けてしまいます。

サンプル用サウンドファイル
bush.wav

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
//This code has been arranged by Yasushi Noguchi. Last updated on July 1, 2008.
 
// Scrub
// by Krister Olsson <http ://www.tree-axis.com> 
 
// Loads a sample that can be played/paused by 
// clicking a button in the lower left-hand corner. 
// Playback head can be adjusted by clicking and dragging
 
// Created 1 May 2005
// Updated 2 May 2006
 
import krister.Ess.*;
 
AudioChannel myChannel;
 
void setup() {
  size(256,200);
  background(0);
 
  Ess.start(this);  //Essをスタートさせる
 
  //bush.wavを読み込んで、myChannelオブジェクトを作成
  myChannel=new AudioChannel("bush.wav");
 
  myChannel.play(Ess.FOREVER);    //ループ再生
  frameRate(30);
}
 
void draw() {
 
}
 
void mousePressed() {
  //もし、マウスが押されたときに再生していたら、
  if (myChannel.state==Ess.PLAYING) myChannel.pause();   //一時停止する
  else myChannel.resume();    //それ以外は一時停止解除
}
 
//終了する前にクリーンアップする
public void stop() {
  Ess.stop();
  super.stop();
}

3. エフェクト(reverb)

次はエフェクトです。代表的なエフェクトであるreverbをかけてみましょう。サンプルの音素材は先ほどと同じbush.wavを使います。基本的に上記のコードとそんなに変わらないので、reverbの部分だけ付け加えているような感じです。

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
//This code has been arranged by Yasushi Noguchi. Last updated on July 1, 2008.
 
// Example by Krister Olsson
// please check the followoing site for more details
//http://www.tree-axis.com/Ess/Reverb/Reverb.html
 
import krister.Ess.*;
 
AudioChannel myChannel;
Reverb myReverb;
 
void setup() {
  size(200,200);
 
  //Essをスタートさせる
  Ess.start(this);
 
  //buch.wavをインポートし、myChannelオブジェクトを作成
  myChannel=new AudioChannel("bush.wav");
  myReverb=new Reverb();  //Reverbオブジェクトを生成
  //最初の引数(0.0 ~ 1.0)を操作することによって、Reverbのかけ具合が調節できる
  //myReverb=new Reverb(1.0, 0, .5);  //Reverbオブジェクトを生成  
  myChannel.play(Ess.FOREVER);    //ループ再生
}
 
void draw() {
}
 
void mousePressed(){
  //マウスクリックごとにReverbをかけていく
  myReverb.filter(myChannel);
}
 
//終了する前にクリーンアップする
public void stop() {
  Ess.stop();
  super.stop();
}

エフェクトはその他にも色々あるので、下のマニュアルを見ながら試してみてください。
http://www.tree-axis.com/Ess/classes_AudioFilter_subclasses.html

4. Essのマニュアル

上記のサンプルはあくまでも初歩的なものでしかありません。Essや他のサウンド系ライブラリにはかなり多くの機能があります。興味がある人は是非独学で頑張ってみましょう(プログラミングって基本は独学なんです)。
http://www.tree-axis.com/Ess/index.html
 このサイトのclassの項目には、使える機能が全部載っている
他のサウンド系ライブラリ

5. サウンド素材サイト

無料のサウンド素材はネットにいくらでもあります。まあ、品質は様々ですが、いいものもあるので根気よく探してみましょう。
http://www.freesound.org/
http://www.soundclick.com/default.cfm

参考
サウンドの周波数解析のサンプル

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
import krister.Ess.*;
 
FFT myFFT;
int bands = 128;
 
AudioStream myStream;
AudioFile myFile;
 
void setup(){
  size(1024, 200);
  Ess.start(this);
  myFile = new AudioFile("ファイル名.aif", 0, Ess.READ);
 
  myStream = new AudioStream(128*1024);
  myStream.sampleRate(myFile.sampleRate);
  myStream.start();
 
  myFFT = new FFT(bands*2);
}
 
void draw(){
  background(176);
 
  myFFT.getSpectrum(myStream);
  stroke(255);
 
  for(int i = 0; i < bands; i ++){
    float x = (float)i/(float)(bands-1)*1024.0;
    float freY = max(0, myFFT.spectrum[i]*height*4);
 
    line(x, height, x, height - freY);
  }
}
 
void stop(){
  Ess.stop();
  super.stop();
}
 
void audioStreamWrite(AudioStream theStream){
  int sampleRead = myFile.read(myStream);
}