プロが教える店舗&オフィスのセキュリティ対策術

フレームに以下のような記述をしたのですが動作が変です。初期段階で「oto1」が鳴っており、インスタンス「b1」をクリックで止まります。これは想定どおりの動作なのですが、「b2」をクリックしても止まるのです。これは理解できません。
何が誤りなのか教えていただけませんでしょうか?
よろしくお願いいたします。
(インスタンス名は正しくつけています)

oto1 = new Sound();
oto2 = new Sound();
_root.oto1.attachSound("s1");
_root.oto2.attachSound("s2");

_root.oto1.start(0, 99);

this.b1.onRelease = function(){
_root.oto1.stop();
};
this.b2.onRelease = function(){
_root.oto2.stop();
};

A 回答 (2件)

同じ階層内で複数の音を扱っている時に特定の音を止めるには、Sound.stop の引数にリンケージ識別子を指定します。


各 onRelease イベントハンドラ内の stop を

 _root.oto1.stop( "s1" );



 _root.oto2.stop( "s2" );

に変更してみてください。
s1 はインスタンス b2 をクリックしても止まりません。
s2 を鳴らしている時は逆に、インスタンス b1 では止められなくなります。


タイムラインに音を挿入する場合は、「プロパティ」パネルにある「同期:」というリストで鳴らし方を指定できます。
この中に「ストップ」という項目があり、指定したサウンドだけを止めることができますが、これと同じ機能です。

------------------------------------------------------------------

Sound クラスのオブジェクトは、どのムービークリップの音を制御するかを指定することができます。
Sound オブジェクトを作る時に

 snd = new Sound( clip );

というように対象のインスタンス名を指定すると、指定されたムービークリップの音を制御する Sound オブジェクトになります。
省略した時は _root、つまりムービー全体の音を制御する Sound オブジェクトになります。

こんな設計になっている理由はいろいろあるのですが、一言で言うなら、音を多重的に管理できるように・・・でしょうか。
シンセサイザなどのコンピュータで出す音は、出力ポート数というものが決められています。
ポートは楽器を演奏する奏者のようなもので、ポートの数だけ同時に音を発声できます。
ActionScript ではムービークリップがサウンドの出力ポートのような役割を果たし、理論上はムービークリップの数だけ音を細かく制御できるようになっています。


しかし、単に”複数の音を鳴らしたいだけ”でしたら、実は音の数だけムービークリップを作る必要はありません。
ただ、Sound クラスのオブジェクトで同時に鳴らせるのは1種類だけ( attachSound を実行するたびに、鳴らすサウンドシンボルが切り替わる)ので、スクリプトで同時に何種類もの音を鳴らしたい場合は Sound オブジェクトは音の数だけ必要です。

ご質問文のスクリプトでは oto1 でしか音を鳴らしていませんが、oto2.start(); を実行してみるとよく分かります。
ともに _root の音を制御する Sound オブジェクトでありながら、2種類の音が同時に鳴ります。
これが、どちらも同じムービークリップの音を制御する Sound オブジェクトだったとしても同様です。

タイムラインにサウンドを入れる時も、レイヤーを分けると2種類以上の音を同時に出すことができます。
つまり、”音を鳴らすだけ”なら1つのムービークリップ(タイムライン)でも可能なのです。
Flash でのムービークリップは奏者というよりはむしろ楽団のようなもので、レイヤーが1人1人の奏者にあたると言えるかもしれませんね。


ムービークリップに分けて管理しなければならないのは、2種類の音を同時に鳴らし、1つはボリュームを大きくもう1つは小さく・・・というように、ボリュームやパンなどの出力設定を個別に分ける場合です。

1つのムービークリップ内にある音は、ボリュームやパン(スピーカーの出力位置)などは全て同じものに統一されてしまいます。
(レイヤーを使った時は違いますが、話がややこしくなるのでとりあえず置いておきます)
一方がフェードアウトしながら片方はフェードインするとか、ナレーションが再生されている間は BGM のボリュームを控えめにしてナレーションを目立たせたい・・・など、複数の音を違う出力設定で鳴らしたい時には、音の数だけムービークリップを分ける必要があります。

***************************

では、同じタイムライン内で別の音を同時に鳴らすことができるのに、止める時はなぜ2つとも同じように止まってしまうのでしょうか。


Flash では、音もムービークリップと同様に”サウンドシンボルのインスタンスを作る”という発想で考えます。
目に見えないもので想像しにくいのですが、サウンドインスタンスができた数だけ音が鳴り、インスタンスが削除されたら止まるものと思ってください。

Sound.start は、実行するたびにサウンドインスタンスを作成して音を鳴らします。
作成されたインスタンスは、サウンドシンボルの最後に達すると用済みになって削除され、音が止まります。


Sound.stop は逆に、稼動中のサウンドインスタンスを強制的に削除して音を止めるメソッドです。
何も指定しなければ、Sound オブジェクトの管理下にあるタイムラインに存在している、稼動中のサウンドインスタンス全てを削除します。

実はタイムラインを使って鳴らしている音でも、Sound オブジェクトが管理しているタイムライン内にあるものであれば削除の対象になります。
例えば、ムービークリップ clip があり、このタイムラインにサウンド s1 を入れているとします。
それとは別に、clip の音を制御する Sound オブジェクトの snd があって、attachSound と start で s2 という音を鳴らします。
この状態で

 snd.stop();

を実行すると、clip 内で稼動しているサウンドインスタンスが全て削除されて、タイムラインで鳴らしていた s1 もスクリプトで鳴らしていた s2 も止まります。

Sound.stop は指定した音だけを止めることもできます。
これが、冒頭でご紹介した使い方です。
止める音はリンケージの識別子で指定します。
例えば先の例で、

 snd.stop( "s1" );

とした時は s1 の方だけ止まります。
タイムラインで鳴らしている音でも、リンケージ識別子が設定されていればSound.stop で指定したものだけを止めることができます。

ちなみに、例えばタイムラインとスクリプトの両方で s1 を鳴らしていた場合、s1 のインスタンスは2つ存在していて二重に音が鳴っています。
この時に s1 を止めるように指示すると、どちらのインスタンスも削除されて止まります。
一般的にはこのような使い方はまずしないと思いますが、stop でリンケージ識別子を指定すると、その識別子を持つサウンドインスタンスが全て削除されるということです。

***************************

ところで、Sound オブジェクトは管理するムービークリップを選べると書きましたが。
_root の音を管理する Sound オブジェクトで stop(); を実行すると、どういうことになるでしょうか。


先述の通り、Sound.stop で止める音を指定しなかった場合は、タイムライン内で稼動中のサウンドインスタンス全てが削除されます。
_root の音を管理する Sound オブジェクトでは”タイムライン内”とはムービー内全てが管轄になりますから、ムービークリップ内で鳴らしている音も全て止まります。
音を止めるにはもう1つ、ムービー内の全ての音を止める stopAllSounds というアクションがありますが、_root の音を管理している Sound オブジェクトの stop(); を使った場合はこれと同等の機能になります。

ご提示のスクリプトで b1 と b2 のどちらをクリックしても音が止まってしまう理由も、ここにあります。
oto1 も oto2 もともに _root の音を制御する Sound オブジェクトなので、stop(); はムービー内の全ての音を止める命令として機能します。
そのために、s1 と s2 のどちらが鳴っているかに関係なく、どちらかのボタンが押されると有無を言わさずムービー内の全ての音が停止してしまうのです。


しかし、_root の音を管理する Sound オブジェクトの stop(); でムービークリップ内も含めた全ての音を一括して止めることはできても、リンケージ識別子で止める音を指定した時はムービークリップ内にある音は止まりません。
なぜこんなややこしい設計になっているのかは、よく分かりませんが。

------------------------------------------------------------------

Sound クラスは意外に複雑ですが、普通に使う分にはあまり細かく考えなくても、充分、多様な鳴らし方や演出ができます。

同時に複数の音を鳴らすのではなく同時に鳴らすのはあくまでも1つだけで、ミュージックプレイヤーのように何かのタイミングで単に鳴らす音を取り替えたいだけなら、取り替えるところで

 oto1.attachSound( "s2" );

というように、attachSound で違うサウンドシンボルに差し替えればいいだけです。
すると、次に oto1.start を実行した時は、新しく attachSound で関連付けた s2 が鳴ります。


サウンドの制御はこのサイトでも度々話題になっています。
いろいろな作例がありますので、興味がありましたら探してみてください。
    • good
    • 0
この回答へのお礼

いつもお世話になっていますm(_ _)m彡
なんと!stop(); の()内に記述とは思いつきませんでした。
今回の現象について「そんなばかな!」と格闘すること4時間、ついにあきらめて質問させていただきましたがこんなに詳細に解説いただき感動です。
本当にどうもありがとうございました。

お礼日時:2006/05/22 02:50

oto1 = new Sound();


だと,全ての音を対象としたSoundオブジェクトが作成されてしまうのでうまくできないのです。


なんと言うのですかね…
非常に説明しにくいのですが,
1サウンドに対して1MCが必要なのですよ。

サウンドを「切り替える」のように,
1つの Soundオブジェクト に対して,複数のSoundを切り替えてならす場合は,

_root.oto1 = new Sound(this);

のようにして,ムービークリップ this を指定すればいいのです。
私が回答したものではありませんが,
こちら↓を参考にしてみてください。
「質問:外部ムービーを読み込んだとき音が鳴らなくて困っています.」
http://oshiete1.goo.ne.jp/kotaeru.php3?q=1570737
 ↑教えて!goo  ↓OKWave (同じです)
http://okwave.jp/kotaeru.php3?q=1570737


そうではなくて,
複数の音を同時に存在させて,その音を同時に制御する場合は,
その音を埋め込む数だけムービークリップが必要となります。
ムービークリップを,実際に作成してインスタンス名を付けても良いですが,
面倒なのでスクリプトで,スクリプトで作るとすれば次のようになります。
最初の2行を付け加えて,次の2行を変更しているだけですが,前文書くと次のようになります。


_root.createEmptyMovieClip("soundMC1", 1);
_root.createEmptyMovieClip("soundMC2", 2);
oto1 = new Sound(_root.soundMC1);
oto2 = new Sound(_root.soundMC2);
_root.oto1.attachSound("s1");
_root.oto2.attachSound("s2");
_root.oto1.start(0, 99);
this.b1.onRelease = function() {
_root.oto1.stop();
};
this.b2.onRelease = function() {
_root.oto2.stop();
};


最初の2行で,深度1と2に空のMCを作成しています。
_root に複数のムービークリップがあって,
そのムービークリップ内タイムラインに音が挿入されている状態で,
それらの音を制御するという感じですね。
全てが目に見えない状態なのでイメージしにくいですが,
_root に複数のムービークリップがあって,
それらのタイムラインを stop() させたり play() させたりするような感じにとらえてもらうとわかりやすいかもしれません。


正式には上記のようにするのが正解だと思います。
ちょっと実験でしてみましたら,次のようなスクリプトでもできました。


oto1 = new Sound(this.b1);
oto2 = new Sound(this.b2);
_root.oto1.attachSound("s1");
_root.oto2.attachSound("s2");
_root.oto1.start(0, 99);
this.b1.onRelease = function() {
_root.oto1.stop();
};
this.b2.onRelease = function() {
_root.oto2.stop();
};


私の場合,「b1」と「b2」はボタンシンボルで作成したのですが,
なぜかそのボタンシンボルのインスタンスを指定しても,大丈夫なようです。
普通は,
new Sound() の () 内はムービークリップ(ムービークリップのタイムライン)を指定しますから,
この方法はやめた方がいいとは思いますが,簡単な方法としての裏技?です。
    • good
    • 0
この回答へのお礼

いつもお世話になっていますm(__)m彡
いや、ひょっとしたらFLASHのバグでは・・?などと空想していましたが私の勉強不足でしたね!
実験までやっていただき誠にありがとうございます。
これを基礎にステップアップいたします。

お礼日時:2006/05/22 02:42

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!