◆PROCESSING 逆引きリファレンス
カテゴリー:音楽・演奏
BGMのバランスを制御する(minim編)
【解説】
minimは、PROCESSINGで手軽に音楽を演奏できるライブラリです。
minimについて、より詳しく知りたい方は下記公式サイト 様を参照して下さい。
音楽や効果音では、列車が走ってくるシーンのように、音が右から左、あるいは左から右へと移動しながら鳴ることがあります。
そうする事で、頭の中で本当に列車が走り抜けていくような感覚を演出するわけです。
(画像URL:illust-AC 様:メジマキ さん)
minimでもこのような効果を演出することが可能です。
音楽用語では左右の音量差の事を「パン(パンニング: panning)」とか「バランス」と呼びます。音楽関係に詳しくない私などは、どちらも同じものだと理解していましたが・・・厳密には異なるものなのだそうです。
理解した範囲によれば
パンとは、音(楽器など)が鳴っている方向の事
バランスとは、左右で聞こえる音量差の事
なのだそうです(たぶん・・・)。
興味がある方は
g200kg Music & Software 様
Adobe Premiere Pro 様
などのページが参考となります。
minimではパンとバランスを別々の命令でコントロールする事が可能です。
現在のパン、バランスを取得するには AudioPlayerクラスの getPan()、getBalance() メソッドを利用します。
パン、バランスを変更するにはAudioPlayerクラスの setPan()、setBalance() メソッドを利用します。
段階的にパンやバランスを変化(移動)させるには、AudioPlayerクラスのshiftPan()、shiftBalance() メソッドが便利です。
【構文】
●現在のパン値を取得する
float nowPan = player. getPan( );
●パン値を変更する
void player. setPan( float newPan ) ;
●現在のバランス値を取得する
float nowBalance = player. getBalance( ) ;
●バランス値を変更する
void player. setBalance( float newBalance ) ;
●段階的にパン値を変更する
void player. shiftPan( float fromPan, float toPan, int millis ) ;
●段階的にバランス値を変更する
void player. shiftBalance( float fromBal, float toBal, int millis ) ;
いずれも player は AudioPlayer クラスのインスタンス変数です。
【パラメータ】
nowPan : 取得するパン値
newPan : 設定するパン値
nowBalance : 取得するバランス値
newBalance : 設定するバランス値
fromPan : 開始パン値
toPan : 到達パン値
fromBal : 開始バランス値
toBal : 到達バランス値
millis : FromからToへ変化するミリセカンド
パン値、バランス値は共に-1 から 1 までの範囲となります。
-1 なら左側が最大、1なら右側が最大となります。
【注意】
「サポート機能を判定する(minim編)」の記事でも触れましたが、パンやバランスの制御はあなたのPC環境や利用する音楽データによってサポートされない事があります。
例えばモノラル音源の音を鳴らす場合は、いくらPCの環境が整っていてもパンやバランスを操作する事はできません。あたりまえ・・・ですね(汗)。パンやバランスが操作可能か否かを調べる方法については上記記事を参照してください。
パン値、バランス値は共に-1 から 1 までの範囲の値となります。
例えば getPan( ); した値が -1 の場合、全音源は左側に偏っています。1なら逆に右側に偏っています。もしも左右で完全に独立した音が鳴る音楽ファイルの場合は、どちらかでしか音が聞こえないことになります。
実際にはパンを左側に偏らせても、(例えば楽器を左側だけに配置しても)音が回り込んで右からも少しだけ聞こえるように、反対側の音が0になるようなステレオ音楽ファイルは稀です。
バランスも同様です。-1なら左に偏らせ、1なら右側に偏らせます。
(画像URL:illust-AC 様:色々愛さん、Designer758さん)
shiftPan() や shiftBalance() は FromからToにむけて、millisで指定した時間で段階的にパンやバランスを変化させます。
shiftPan( -1, 1, 5000 ); なら、一旦音源を左(-1)に偏らせた後に、5秒間(5000ミリセカンド)かけて右(1)まで徐々に移動させます。
なお、各命令に -1 から 1の範囲外の値を与えてもエラーにはなりません。かわりに意図しない音の鳴り方になる事があります。値の範囲はプログラマーが責任をもってね・・・という事のようです(汗)。
【関連記事】
- 音楽の再生準備を行う(minim編)
- サポート機能を判定する(minim編)
- BGMのボリュームを制御する(minim編)
- BGMの再生・停止を行う(minim編)
- BGMの再生位置を制御する(minim編)
- BGMの消音を制御する(minim編)
- 音楽ファイルのメタ情報を取得する(minim編)
- BGMの周波数を分析する(minim編)
サンプルプログラム
バランスを制御する例:
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 |
import ddf.minim.*; //宣言 Minim mini; //Minimオブジェクト変数 AudioPlayer player; //音楽制御用インスタンス int rlFlg; //左右切り替えフラグ int totalTime; //経過時間 //------------------------ // 初期処理関数 //------------------------ void setup(){ size(200,200); //Minimインスタンスを作成する mini = new Minim( this ); //音楽ファイルを読み込む player = mini.loadFile("walking.mp3"); //最初は左から右に向かって音を鳴らす player.setBalance( 0 ); rlFlg = LEFT; player.loop(); textAlign( LEFT , TOP ); frameRate( 60 ); totalTime = 0; } //------------------------ // 描画処理関数 //------------------------ void draw(){ background( 255 ); fill(0); if( totalTime % 310 == 0 ){ //5秒ちょいごとに左右を切り替える totalTime = 0; if( rlFlg == LEFT ){ //右側に切り替える player.shiftBalance( -1, 1, 5000 ); rlFlg = RIGHT; } else { //左側に切り替える player.shiftBalance( 1, -1, 500 ); rlFlg = LEFT; } } totalTime++; //経過時間を加算 if( rlFlg == LEFT ){ //今は右から左に音が移動中(次は左から右) text( "RIGHTからLEFT", 32,32 ); } else { //今は左から右に音が移動中(次は右から左) text( "LEFTからRIGHT", 32,32 ); } } |
上記サンプルで用いている音楽ファイル(walking.mp3)は5秒間の演奏時間がある音です。
これを(だいたい)5秒感覚で切り替えながら、左から右、右から左へと音のバランスを段階的に変化させています。
パンを制御する例:
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
import ddf.minim.*; //宣言 Minim mini; //Minimオブジェクト変数 AudioPlayer player; //音楽制御用インスタンス PImage speeker; //------------------------ //ボタンクラス //------------------------ class myButton{ PImage img = null; int bw, bh; int bx, by; //コンストラクタ myButton( String fileName ){ img = loadImage( fileName ); bw = img.width; bh = img.height; } //表示関数 void disp( int x, int y ){ bx = x; by = y; image( img, bx, by ); } //押下判定関数 boolean isPush( int x, int y ){ boolean ret = false; if( x > bx && x < bx + img.width && y > by && y < by + img.height ){ ret = true; } return( ret ); } } myButton button[]; float sx, sy; int len; int mode; //------------------------ // 初期処理関数 //------------------------ void setup(){ boolean breakFlg = false; //初期処理エラーFLG size(200,200); //Minimインスタンスを作成する mini = new Minim( this ); //音楽ファイルを読み込む player = mini.loadFile("se.mp3"); if( player == null ){ println( "loadFile() error" ); breakFlg = true; } //ボタンを生成する button = new myButton[3]; button[0] = new myButton( "left.png" ); button[1] = new myButton( "center.png" ); button[2] = new myButton( "right.png" ); //スピーカーの絵を読み込む speeker = loadImage( "speeker.png" ); if( breakFlg == true ){ //エラーなら終了 noLoop(); exit(); } //曲の長さを取得し、スピーカーを中央配置 len = player.length(); mode = CENTER; player.printControls(); } //------------------------ // 描画処理関数 //------------------------ void draw(){ background( 255 ); //ボタンを描画する int y = height - button[0].bh; button[0].disp( 0, y ); button[1].disp( (width-button[1].bw)/2, y ); button[2].disp( width - button[2].bw, y ); //スピーカーの絵を、パン状態に応じて移動する sy = 50; //左端からの位置を求める sx = map( player.position(),0f,len,0f,width-speeker.width); if( mode == RIGHT ){ //右から左へ移動する場合なら、右端からの位置に変換 sx = width - speeker.width - sx; } else if( mode == CENTER) { //中央なら、真ん中固定 sx = (width - speeker.width)/2; } image( speeker, sx, sy ); } void mouseClicked(){ //演奏中なら処理しない if( player.isPlaying() ) return; //ボタンが押されたか判定する for( int i = 0; i < 3; i++ ){ if( button[ i ].isPush( mouseX, mouseY )){ if( i == 0 ){ //左から右へパン移動 player.rewind(); player.shiftPan( -1, 1, len ); player.play(); mode = LEFT; } else if( i == 1 ){ //パンは中央固定 player.rewind(); player.setPan( 0 ); player.play(); mode = CENTER; } else { //右から左へパン移動 player.rewind(); player.shiftPan( 1, -1, len ); player.play(); mode = RIGHT; } } } } |
実行すると、左右の耳と、ヘッドホンをつけた猫が表示されます(笑)。
左右の耳をクリックすると、その方向から反対側に向けてヘリコプターが飛んで行く音がします。中央の猫を押すと、真ん中から音がします(音は移動しません)。
音の移動に合わせて、スピーカーの絵も動きます。
試して頂く場合は、se.mp3 という名前の音楽ファイルと、48×48ピクセルの left.png、right.png、center.png の各画像をご用意下さい。
<出力サンプル>
(画像URL:illust-AC 様:acworks さん、Yakko AC さん)
下記はサンプルプログラムと同じ動きになるように、 P5.js+P5.sound で書き直したものです。動作イメージを確認できます。※
※ブラウザーによっては下記サンプルが表示されない事があります。IE11はNGでした。動作イメージを確認したい方は、FireFox、Chrome、Edgeなどでお試しください。
演奏される効果音は、魔王魂 様から拝借しました。ありがとうございます。
本ページで利用しているアイコン画像は、下記サイト様より拝借しております。各画像の著作権は、それぞれのサイト様および作者にあります。