多摩美 - サウンド&ネット 2014年度
第5回: Web応用2 – P5.jsでサウンドプログラミング
前回に引き続きp5.jsでWebブラウザ上でプログラミングしていきます。今回からは、p5.jsでサウンドを扱っていきます。最終目標のイメージとして、音と映像をインタラクティブに操作する作品、例えば、patatapのような作品をWebブラウザ上で発表します。
サンプルファイル
今回とりあげるプログラムのサンプルは、全て下記からダウンロード可能です。
サウンドファイルの準備
手元にサウンドファイルを準備します。もし、手元に適当なサウンドがない場合には、freesoundやsoundcloudからフリーのサウンド素材をダウンロードして使用しましょう。
最終的に作品で使用するサウンドは、金曜日のサウンドの授業で作成したもので作成します。
サウンドファイルを再生する
p5.sound.jsの読み込み
p5.jsでサウンド機能を使用するためには、まず始めにサウンド用のライブラリ「p5.sound.js」を有効にしなくてはいけません。「p5.sound.js」ライブラリを有効にするには、まずp5.jsのエディタを起動したら、index.htmlのタブを選択します。
9行目に注目してください。色がグレーになっています。これは「コメントアウト」といって、前後にある という記号によって、その内側が無視されるようになっています。このコメントアウトを解除することで、p5.sund.jsが有効になります。
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>
assetsフォルダの作成
次にサウンドファイルを格納するためのフォルダを準備します。今回は、プログラムの「資産」といった意味合いを込めて「assets」という名前のフォルダを作成します。フォルダは、index.htmlやsketch.jsがある階層に新規に作成します。
この「assets」フォルダの中に使用するファイルを格納します。例えば、「mySound.mp3」という名前のサウンドを使用する場合には、以下のような階層構造となります。
サウンドを再生
では、まずはシンプルに音をループ再生してみましょう。例えば、assetsフォルダに入れたサウンドファイルの名前が「se01.wav」だとすると、以下のようなプログラムをsketch.jsに記入します。
var sample;
function preload() {
sample = loadSound('assets/se01.wav');
}
function setup() {
createCanvas(320, 240);
sample.loop();
}
function draw() {
background(200);
}
プログラムを実行すると、音がループ再生されればOKです。
インタラクティブにサウンドを再生
キーダウンで再生
次に、サウンドの再生をインラクティブにしてみましょう。キーボードを押すとサウンドが再生されるように改造します。
var sample;
function preload() {
sample = loadSound('assets/se01.wav');
}
function setup() {
createCanvas(320, 240);
}
function draw() {
background(200);
}
function keyTyped() {
sample.play();
}
マウスクリックでサウンド再生
このプログラムは、keyPressed(k)をmousePressed()に変更すると、マウスを画面内でクリックすると再生するように変更可能です。
var sample;
function preload() {
sample = loadSound('assets/se01.wav');
}
function setup() {
createCanvas(320, 240);
}
function draw() {
background(200);
}
function mousePressed() {
sample.play();
}
複数の音を再生する
次に復習の種類の音を読み込んでキーボードで切り替えながら演奏してみましょう。この例では、assetsフォルダに
- se01.wav
- se02.wav
- se03.wav
- se04.wav
と4種類の音がそれぞれ入っていると過程して説明します。
音を複数扱うには、サウンドを格納する配列(変数のロッカー)のようなものを用意すると便利です。p5.jsではJavaScriptの配列の生成方法と同じ文法となります。
var sample = [];
こうすることで、
- sample[0]
- sample[1]
- sample[2]
- …
というように、連番でサウンドファイルを格納して再生することが可能となります。
サウンドは、タイプしたキーの種類によって変更するようにしてみましょう。その場合、keyPressed() ではなく keyTyped() を使用すると便利です。以下のようにして、キーの種類を識別します。キーの数だけ条件を指定することが可能です。
function keyTyped() {
if (key == 'a') {
// 「a」キーを押したときの処理
}
if (key == 's') {
// 「s」キーを押したときの処理
}
if (key == 'd') {
// 「d」キーを押したときの処理
}
if (key == 'f') {
// 「f」キーを押したときの処理
}
// ...
}
以上の方法をまとめて、以下のようなプログラムが作成されました。
var sample = [];
function setup() {
createCanvas(320, 240);
sample[0] = loadSound('assets/se01.wav');
sample[1] = loadSound('assets/se02.wav');
sample[2] = loadSound('assets/se03.wav');
sample[3] = loadSound('assets/se04.wav');
}
function draw() {
background(200);
}
function keyTyped() {
if (key == 'a') {
sample[0].play();
}
if (key == 's') {
sample[1].play();
}
if (key == 'd') {
sample[2].play();
}
if (key == 'f') {
sample[3].play();
}
}
このプログラムを実行してみましょう。キーの種類に応じて音が切り替わるはずです。
サウンドにアニメーションを追加する
いよいよ、それぞれのサウンドに対応するアニメーションを追加してみましょう。
ひとつひとつのサウンドは、独立したObjectとして作成して、それをメインのプログラム(sketch.js)から呼び出すという構造にしていきたいと思います。
個別のアニメーションを格納するための、animations.jsというファイルを新規に作成しましょう。メニューバーから「File > New File」を選択して、新規ファイルを「animations.js」という名前でプロジェクトに追加します。
その上で、index.htmlにanimations.jsを読み込む命令(12行目)を追加します。
index.htm
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<script src="sketch.js"></script>
<script src="animation.js"></script>
</body>
</html>
それぞれのアニメーションは、独立したオブジェクトとなります。例えば、各キーに対応するオブジェクトを以下のように名付けるとします。
- aキー : Animation_a
- sキー : Animation_s
- dキー : Animation_d
- fキー : Animation_f
それぞれのアニメーションは、新規に作成される際に初期化され、draw命令で描画するものとします。これを実現するために、animations.jsに下記のような雛形を作成します。
animations.js
// ------------------------------------------------------
// Animation A
function Anim_a() {
// Animation Aの初期設定
}
Anim_a.prototype.draw = function() {
// Animation Aの描画
};
// ------------------------------------------------------
// Animation S
function Anim_s() {
// Animation Sの初期設定
}
Anim_s.prototype.draw = function() {
// Animation Sの描画
};
// ------------------------------------------------------
// Animation D
function Anim_d() {
// Animation Dの初期設定
}
Anim_d.prototype.draw = function() {
// Animation Dの描画
};
// ------------------------------------------------------
// Animation F
function Anim_f() {
// Animation Fの初期設定
}
Anim_f.prototype.draw = function() {
// Animation Fの描画
};
この全てのアニメーションにそれぞれ別個の動きをデザインします。例えば、下記のように簡単な図形によるアニメーションを入れてみます。
animation.js
// ------------------------------------------------------
// Animation A
function Anim_a() {
this.x = width / 2;
this.y = height / 2;
this.diameter = 0;
this.speed = 10;
}
Anim_a.prototype.draw = function() {
noStroke();
fill(0, 127, 255);
ellipse(this.x, this.y, this.diameter, this.diameter);
this.diameter += this.speed;
};
// ------------------------------------------------------
// Animation S
function Anim_s() {
this.width = 0;
this.speed = 80;
}
Anim_s.prototype.draw = function() {
noStroke();
fill(255, 0, 0);
rectMode(CORNER);
rect(0, 0, this.width, height);
this.width += this.speed;
};
// ------------------------------------------------------
// Animation D
function Anim_d() {
this.rotate = 0;
this.size = 0;
this.speed = 50;
}
Anim_d.prototype.draw = function() {
push();
fill(255, 255, 0);
noStroke();
translate(width / 2, height / 2);
rotate(radians(this.rotate));
rectMode(CENTER);
rect(0, 0, this.size, this.size);
pop();
this.rotate += this.speed;
this.size += this.speed;
};
// ------------------------------------------------------
// Animation F
function Anim_f() {
this.bgColor = 255;
this.speed = -2;
}
Anim_f.prototype.draw = function() {
noStroke();
fill(this.bgColor);
rect(0, 0, width, height);
this.bgColor += this.speed;
};
最後にいよいよsketch.jsからそれぞれのアニメーションをキーを押したタイミングで実行されるように組み込んでみます。
sketch.js
var sample = [];
var animation;
var num;
function setup() {
createCanvas(320, 240);
sample[0] = loadSound('assets/se01.wav');
sample[1] = loadSound('assets/se02.wav');
sample[2] = loadSound('assets/se03.wav');
sample[3] = loadSound('assets/se04.wav');
}
function draw() {
background(0);
if(animation){
animation.draw();
}
}
function keyTyped() {
if (key == 'a') {
sample[0].play();
animation = new Anim_a();
}
if (key == 's') {
sample[1].play();
animation = new Anim_s();
}
if (key == 'd') {
sample[2].play();
animation = new Anim_d();
}
if (key == 'f') {
sample[3].play();
animation = new Anim_f();
}
}
これで完成です!! a, s, d, fのキーを押すと、対応するアニメーションとそれに付随するサウンドが再生されます。
フルスクリーンで再生する
せっかくアニメーションを作成したので、ブラウザの画面いっぱいにcanvasを拡げて再生したいものです。p5.jsではcreateCanvasの引数の指定で、Webブラウザの画面全体を使うことが可能です。sketch.jsを以下のように変更します。6行目の「createCanvas(windowWidth, windowHeight);」がポイントです。
sketch.js
var sample = [];
var animation;
var num;
function setup() {
createCanvas(windowWidth, windowHeight);
sample[0] = loadSound('assets/se01.wav');
sample[1] = loadSound('assets/se02.wav');
sample[2] = loadSound('assets/se03.wav');
sample[3] = loadSound('assets/se04.wav');
}
...
また、canvasの上と左に余白が生じないように、index.htmlも若干変更を加えます。12行目のbodyの開始要素に、余白を除去するCSSを直接書き込んでいます。
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body style="margin:0;">
<script src="sketch.js"></script>
<script src="animation.js"></script>
</body>
</html>
これで、Webブラウザの画面いっぱいで再生されるようになりました!!
実習
- 金曜日のサウンドの授業で作成したサウンドを全て、プログラムに読み込む
- キーボードを割り当て、全ての音を再生できるようにしてみる
- それぞれの音にあてはまるアニメーションはどのようなものか、考えてみる