サウンドの再生

次に示すように、読み込んだサウンドは Sound オブジェクトの Sound.play() メソッドを呼び出すだけで再生できます。

var req = new air.URLRequest("smallSound.mp3"); 
var snd = new air.Sound(req); 
snd.play();

サウンドの再生操作

サウンドを再生するときは、次の操作を実行できます。

  • 特定の開始位置からサウンドを再生する

  • サウンドを一時停止し、後で同じ位置から再生を再開する

  • サウンドの再生が終了する正確な時間を知る

  • サウンドの再生の進行状況を追跡する

  • サウンドの再生中に音量またはバランスを変更する

再生中にこれらの操作を実行するには、SoundChannel、SoundMixer、SoundTransform の各クラスを使用します。

SoundChannel クラスは、単一のサウンドの再生を制御します。 SoundChannel.position プロパティは再生ヘッドと考えることができ、サウンドデータ内で再生中の現在位置を示します。

アプリケーションが Sound.play() メソッドを呼び出すと、再生を制御するために SoundChannel クラスの新しいインスタンスが作成されます。

アプリケーションは Sound.play() メソッドの startTime パラメーターとして、ミリ秒の単位で表した特定の開始位置を渡すことで、その位置からサウンドを再生できます。また、 Sound.play() メソッドの loops パラメーターで数値を渡すことで、間を置かずにサウンドを繰り返して再生する固定回数を指定できます。

Sound.play() メソッドを呼び出すときに startTime パラメーターと loops パラメーターの両方を指定すると、サウンドが毎回同じ開始位置から繰り返して再生されます。次のコードはこの例を示しています。

var req = new air.URLRequest("repeatingSound.mp3"); 
var snd = new air.Sound(); 
snd.play(1000, 3);

この例では、サウンドの先頭から 1 秒後の位置から連続して 3 回、サウンドを再生します。

サウンドの一時停止と再開

歌やポッドキャストのような長いサウンドをアプリケーションで再生する場合、通常は、ユーザーがサウンドの再生を一時停止および再開できるようにする必要があります。サウンドは文字通り一時的に休止させておくことはできず、停止させることしかできません。ただし、サウンドの再生はどこからでも開始できます。サウンドを停止した位置を記録しておき、後でその位置からサウンドの再生を開始できます。

例えば、次のようなサウンドファイルを読み込んで再生するコードがあるとします。

var req = new air.URLRequest("bigSound.mp3"); 
var snd = new air.Sound(req); 
var channel = snd.play();

サウンドを再生している間、 channel オブジェクトの position プロパティは、サウンドファイル内で現在再生されている位置を示します。アプリケーションでは次のようにして、サウンドの再生を停止する前に位置の値を保存できます。

var pausePosition = channel.position; 
channel.stop();

サウンドの再生を再開するには、保存しておいた位置の値を渡します。サウンドは停止したときと同じ位置から再開されます。

channel = snd.play(pausePosition);

再生の監視

サウンドの再生が停止したことをアプリケーションに認識させたい場合があります。その後で別のサウンドの再生を開始したり、前回の再生で使用したリソースをクリーンアップしたりできます。SoundChannel クラスは、サウンドの再生が終了すると soundComplete イベントを送出します。次の例で示すように、アプリケーションはこのイベントをリッスンして、適切なアクションを実行できます。

var snd = new air.Sound("smallSound.mp3"); 
var channel = snd.play(); 
s.addEventListener(air.Event.SOUND_COMPLETE, onPlaybackComplete); 
 
public function onPlaybackComplete(event) 
{ 
    air.trace("The sound has finished playing."); 
}

SoundChannel クラスは、再生中には progress イベントを送出しません。再生の進行状況を報告するために、アプリケーションで独自のタイミングメカニズムを設定してサウンド再生ヘッドの位置を追跡できます。

サウンドの再生済みの割合を計算するには、 SoundChannel.position プロパティの値を、再生しているサウンドデータの長さで割ります。

var playbackPercent = 100 * (channel.position / snd.length);

ただし、このコードが正確な再生済みの割合を報告するのは、再生を開始する前にサウンドデータが完全に読み込まれていた場合のみです。 Sound.length プロパティが示すのは、現時点で読み込まれているサウンドデータのサイズであり、サウンドファイル全体の最終的なサイズではありません。まだ読み込みが完了していないストリーミングサウンドの再生の進行を追跡するには、サウンドファイル全体の最終的なサイズを推定し、その値を使用して計算する必要があります。サウンドデータの最終的な長さは、次のように Sound オブジェクトの bytesLoaded プロパティと bytesTotal プロパティを使用して推定できます。

var estimatedLength = Math.ceil(snd.length / (snd.bytesLoaded / snd.bytesTotal)); 
var playbackPercent = 100 * (channel.position / estimatedLength);

次のコードは、大きいサウンドファイルを読み込み、 setInterval() 関数をタイミングメカニズムとして使用して、再生の進行状況を表示します。このコードが定期的に報告する再生済みの割合は、現在位置の値をサウンドデータの全長で割って得られたものです。

var snd = new air.Sound(); 
var url = "http://www.example.com/sounds/test.mp3"; 
var req = new air.URLRequest(url); 
snd.load(req); 
 
var channel = snd.play(); 
var timer = setInterval(monitorProgress, 100); 
snd.addEventListener(air.Event.SOUND_COMPLETE, onPlaybackComplete); 
 
function monitorProgress(event) 
{ 
    var estimatedLength = Math.ceil(snd.length / (snd.bytesLoaded / snd.bytesTotal)); 
    var playbackPercent = Math.round(100 * (channel.position / estimatedLength)); 
    air.trace("Sound playback is " + playbackPercent + "% complete."); 
} 
 
function onPlaybackComplete(event) 
{ 
    air.trace("The sound has finished playing."); 
    clearInterval(timer); 
}

サウンドデータの読み込みを開始した後、このコードは snd.play() メソッドを呼び出して、結果の SoundChannel オブジェクトを channel 変数に格納します。その後で monitorProgress() メソッドを追加し、 setInterval() 関数で繰り返し呼び出します。このコードでは、イベントリスナーを使用して、再生が完了すると発生する SoundChannel オブジェクトの soundComplete イベントをリッスンします。

monitorProgress() メソッドは、読み込み済みのデータの量に基づいてサウンドファイルの全体の長さを推定します。その後、現在の再生済みの割合を計算して表示します。

サウンド全体の再生が終了すると、 onPlaybackComplete() 関数を実行します。この関数は、 setInterval() 関数のコールバックメソッドを削除して、再生の終了後に進行状況の更新が表示されないようにします。

ストリーミングサウンドの停止

ストリーミング中のサウンド、つまり再生中にまだ読み込まれているサウンドの再生処理では、他の場合とは異なる動作が発生します。ストリーミングサウンドを再生している SoundChannel インスタンスで stop() メソッドを呼び出すと、サウンドの再生が停止した後、サウンドの先頭から再生が再開します。このようなことが発生するのは、サウンドの読み込み処理が進行中であるためです。ストリーミングサウンドの読み込みと再生の両方を停止するには、 Sound.close() メソッドを呼び出します。

サウンドの音量とバランスの制御

個々の SoundChannel オブジェクトは、サウンドの左右のステレオチャンネルを両方とも制御します。MP3 サウンドがモノラルサウンドの場合、SoundChannel オブジェクトの左右のステレオチャンネルに含まれる波形は同じです。

再生中のサウンドの各ステレオチャンネルの振幅を検出するには、SoundChannel オブジェクトの leftPeak プロパティと rightPeak プロパティを使用します。これらのプロパティは、サウンド波形自体のピーク振幅を示します。実際の再生音量を表してはいません。実際の再生音量は、サウンド波形の振幅と、SoundChannel オブジェクトおよび SoundMixer クラスで設定されている音量値の相関結果です。

SoundChannel オブジェクトの pan プロパティを使用すると、再生中の左右のチャンネルに異なる音量レベルを指定できます。pan プロパティに指定できる値は、-1 ~ 1 の範囲です。-1 という値は、左のチャンネルを最大音量で再生し、右のチャンネルを消音することを意味します。1 という値は、右のチャンネルを最大音量で再生し、左のチャンネルを消音することを意味します。-1 と 1 の間の値は、左と右のチャンネルの値を指定した値に比例して設定します。値 0 は、両方のチャンネルを均等に中程度の音量レベルで再生することを意味します。

次のコード例では、SoundTransform オブジェクトを作成し、音量の値を 0.6 に、バランスの値を -1(左上チャンネルは最大音量、右チャンネルは消音)に設定しています。その後、SoundTransform オブジェクトを play() メソッドにパラメーターとして渡します。 play() メソッドは、渡された SoundTransform オブジェクトを、再生を制御するために作成される新しい SoundChannel オブジェクトに適用します。

var req = new air.URLRequest("bigSound.mp3"); 
var snd = new air.Sound(req);  
var trans = new air.SoundTransform(0.6, -1); 
var channel = snd.play(0, 1, trans);

サウンドの再生中に、音量とバランスを変更できます。そのためには、SoundTransform オブジェクトの pan または volume プロパティを設定し、そのオブジェクトを SoundChannel オブジェクトの soundTransform プロパティとして適用します。

また、SoundMixer クラスの soundTransform プロパティを使用すると、すべてのサウンドに対してグローバルな音量とバランスの値を一度に設定することもできます。次に、この例を示します。

SoundMixer.soundTransform = new air.SoundTransform(1, -1);

また、SoundTransform オブジェクトを使用すると、Microphone オブジェクトの音量とバランスも設定できます( サウンド入力のキャプチャ を参照)。

次の例では、サウンドの再生中に、サウンドのバランスを左チャンネルから右チャンネルに変更してから元に戻しています。

var snd = new air.Sound();          
var req = new air.URLRequest("bigSound.mp3"); 
snd.load(req); 
 
var panCounter = 0; 
 
var trans = new air.SoundTransform(1, 0); 
var channel = snd.play(0, 1, trans); 
channel.addEventListener(air.Event.SOUND_COMPLETE,  
                            onPlaybackComplete); 
 
var timer = setInterval(panner, 100); 
 
function panner() 
{ 
    trans.pan = Math.sin(panCounter); 
    channel.soundTransform = trans; // or SoundMixer.soundTransform = trans; 
    panCounter += 0.05; 
} 
 
function onPlaybackComplete(event) 
{ 
    clearInterval(timer); 
}

このコードでは、最初にサウンドファイルを読み込んだ後、SoundTransform オブジェクトを作成し、volume を 1(最大音量)に、バランスを 0(左右均等)に設定します。次に、 snd.play() メソッドを呼び出し、SoundTransform オブジェクトをパラメーターとして渡します。

サウンドの再生中には、 panner() メソッドを繰り返して実行します。 panner() メソッドは、 Math.sin() 関数を使用して、-1 ~ 1 の範囲の値を生成します。この範囲は、 SoundTransform.pan プロパティに設定できる値に対応しています。SoundTransform オブジェクトの pan プロパティを新しい値に設定した後、チャンネルの soundTransform プロパティを、変更後の SoundTransform オブジェクトを使用するように設定します。

このコード例を実行する場合は、ファイル名 bigSound.mp3 をローカルの MP3 ファイルの名前に変更します。 その後で例を実行します。まず、左チャンネルの音量が大きくなって右チャンネルの音量が小さくなり、次にはその逆に音量が変化します。

この例では、SoundMixer クラスの soundTransform プロパティを設定することで同じ効果を実現することもできます。ただし、その場合は、この SoundChannel オブジェクトが再生している単一のサウンドだけではなく、その時点で再生しているすべてのサウンドのバランスが影響を受けます。