カテゴリー別アーカイブ: Sound

AACオーディオをNetStreamで再生する際の問題点

ちょっとはまったのでメモ。
AACファイルをNetStreamを使って再生する場合、FLVと同様に・・・
rcv_ns.play(url_flv);
rcv_ns.seek(0);
rcv_ns.pause();

みたいな感じで、先頭に位置づけておいて、NetStream.resume()とNetStream.puase()を切り替えて、再生・一時停止を実装しています。例えば、こんな感じ。
if (isNowPlaying) {
//終了の場合は、巻き戻して再生
if (flg_finish) {
flg_finish = false;
rcv_ns.seek(0);
}
rcv_ns.resume();
} else {
rcv_ns.pause();
}
この状態で、NetStream.seek(0)で一時停止(NetStream.pause())した状態で放置しておくと、NetStream.resume()してもAACが再生されなくなってしまいます。つまり初期状態や先頭まで巻き戻した状態でそのままにしておくと、再生ボタンが効かなくなるということです。
FLVでテストしても問題は発生せず、どうもAACに固有の問題のようです。結局、NetStream.resume()の前には、強制的にNetStream.timeで位置合わせしてやることで解決しました。
if (isNowPlaying) {
//終了の場合は、巻き戻して再生
if (flg_finish) {
flg_finish = false;
rcv_ns.seek(0);
} else {
rcv_ns.seek(rcv_ns.time);
}
rcv_ns.resume();
} else {
rcv_ns.pause();
}
う〜ん、なんか釈然としないけど、バグなんだろうか?
直接は関係ないですが、AdobeのサイトにAAC関連の記事を見つけたので貼っておきます。NetStreamで読み込むAACにSoundTransformを使う方法なんて事も書いてあります。

Soundクラスでのシーク対応

Soundクラスによるサウンド再生でシークバーをつけたんだけど、Sound,SoundChannelクラスにはseek()がない。基本的にはSound.play(time)で時間指定をすればいいのだけれど、再生停止中に

sndCh = Sound.play(n);
snfCh.stop();
とやっても、SoundChannel.positionの値が更新されない。なので、再生停止中は、volumeを0にした状態で最小時間(1ms)再生してからSoundChannel.stop()することで対応してみた。他にいいやり方あるのかしらん?
以下、シーク対応を含むクラスです。
package {
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;
import flash.events.EventDispatcher;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.MovieClip;
import flash.events.Event;
import flash.net.URLRequest;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class SoundLoader extends Loader {
var snd:Sound;
var sndCh:SoundChannel;
var sndTF:SoundTransform = new SoundTransform();
var sndVol:Number;
var flg_play:Boolean;
var flg_repaet:Boolean;
var isNowPlaying:Boolean;
var fn_sndComplete:Function;
var timer:Timer;
const time_interval:Number = 1;
function SoundLoader(url:String,isPlay:Boolean,
isRepeat:Boolean,fn:Function=null) {
flg_play = isPlay;
flg_repaet = isRepeat;
fn_sndComplete = fn;
//再生中フラグ:初期化
isNowPlaying = false;
//サウンド:ロード
snd = new Sound();
snd.addEventListener(Event.COMPLETE,loadCompleteHandler);
var urlReq:URLRequest = new URLRequest(url);
snd.load(urlReq);
}
//sound:ロード完了時の処理
function loadCompleteHandler(evt:Event):void {
if (flg_play) {
sndCh = snd.play(0);
sndCh.addEventListener(Event.SOUND_COMPLETE,
  soundCompleteHandler);
isNowPlaying = true;
}
}
//sound:再生終了時の処理
function soundCompleteHandler(evt:Event):void {
trace(“再生終了!”);
if (flg_repaet) {
//repeat:あり
sndCh = snd.play(0);
sndCh.addEventListener(Event.SOUND_COMPLETE,
  soundCompleteHandler);
} else {
//repeat:なし
isNowPlaying = false;
//再生後の処理が指定されている場合:実行
if (fn_sndComplete != null) {
fn_sndComplete();
}
}
}
//sound:再生
public function playSound():void {
var pausePosition:int;
if (sndCh == null) {
//初回再生の場合
pausePosition = 0;
} else if (sndCh.position == snd.length) {
//最後まで再生した場合
pausePosition = 0;
} else {
//それ以外
pausePosition = sndCh.position;
}
sndCh = snd.play(pausePosition);
sndCh.soundTransform = sndTF;
sndCh.addEventListener(Event.SOUND_COMPLETE,
  soundCompleteHandler);
isNowPlaying = true;
}
//sound:一時停止
public function stopSound():void {
sndCh.stop();
sndCh.removeEventListener(Event.SOUND_COMPLETE,
 soundCompleteHandler);
isNowPlaying = false;
}
//sound:巻き戻し
public function rewSound():void {
if (isNowPlaying) {
//再生中
sndCh.stop();
sndCh = snd.play(0);
sndCh.removeEventListener(Event.SOUND_COMPLETE,
 soundCompleteHandler);
} else {
//停止中
//sndCh.stop();
sndCh = snd.play(0);
sndCh.stop();
}
}
//sound:リピート切替
public function repeatSound(isRepeat:Boolean):void {
flg_repaet = isRepeat;
}
//sound:再生位置取得
public function getPosition():Number {
var pos_return:Number;
if (sndCh == null) {
//一度も再生していない場合
pos_return = 0;
} else {
//再生済みの場合
pos_return = sndCh.position;
}
return pos_return;
}
//sound:長さ取得
public function getLength():Number {
return snd.length;
}
//sound:再生位置合わせ
public function setPosition(position_sound:Number,
flg_play:Boolean):void {
//再生位置:指定
sndCh = snd.play(position_sound);
if (flg_play) {
//—再生
sndCh.addEventListener(Event.SOUND_COMPLETE,
  soundCompleteHandler);
isNowPlaying = true;
} else {
//—再生しない
//現在のボリューム:保存
sndVol = sndTF.volume;
//位置移動用にvolumeをゼロにする
var tf:SoundTransform = new SoundTransform(0);
sndCh.soundTransform = tf;
//サウンド位置合わせタイマー:起動
setIntervalTimer_sound();
}
}
//—————————————————
// sound.play()>SoundChannel.stop()を連続させても、
// SoundChannel.positionの値が変更されないので、
// 最小時間(1ms)だけ無音で再生してから停止する。
//—————————————————
//サウンド位置合わせタイマー:起動

function setIntervalTimer_sound():void {
timer = new Timer(time_interval,1);
timer.addEventListener(TimerEvent.TIMER, onStopSound_timer);
timer.start();
}
//サウンド位置合わせタイマー:サウンド停止
function onStopSound_timer(event:TimerEvent):void {
//再生停止
sndCh.stop();
//volume:元に戻す
var tf:SoundTransform = new SoundTransform(sndVol);
sndCh.soundTransform = tf;
}
}
}

swf全体でのサウンド制御

AS3.0ではサウンド制御も変更されていて、基本的にSoundクラスとSoundChannelクラスを使う。例えば、外部mp3を再生する場合は。こんな感じ。

var sd_song:Sound;
var sd_channel:SoundChannel;

function xInitSound_song():void {
sd_song = new Sound();
var url:String = “mp3/” + “Pissism-Blade.mp3”;
var urlReq:URLRequest = new URLRequest(url);

sd_song.addEventListener(Event.COMPLETE,onCompleteSound_load);
sd_song.load(urlReq);
}

function onCompleteSound_load(evt:Event):void {
trace(“—ロード完了”,evt.target);
}

function xStartSound_song(evt:MouseEvent):void {
sd_channel = sd_song.play();
}

xInitSound_song();
btn_play.addEventListener(MouseEvent.CLICK,xStartSound_song);

で、使用しているチャンネルの音量は、SoundChannel.soundTransform.volumeで制御することになるのだけれど、

function xVolume0_song(evt:MouseEvent):void {
var st:SoundTransform = sd_channel.soundTransform
st.volume = 0
sd_channel.soundTransform = st
}

と書いても、サウンド再生中は制御できる(volume=0になる)けど、停止しているときに0にしても再び再生するとvolumeは0にはならない。要はSoundChannelのsoundTransformは再生しているSoundクラスに対してのみ有効ということらしい。SoundChannelという器の設定ではないんですね。
コレだと全体の音量制御ができない。いろいろ検索してみたら、SoundMixer.soundTransformで制御すると、swf全体の制御が出来るらしい。

function xVolume0_song(evt:MouseEvent):void {
var st:SoundTransform = SoundMixer.soundTransform;
st.volume = 0;
SoundMixer.soundTransform = st;
}

SoundMixerクラスを使うことで、swf全体のサウンド制御ができ、かつサウンドの再生・停止に依存せずに音量制御ができる。
検索中に下記サイトでこの辺の制御をクラス化したものを発見。コレ、便利そう。