3

Flex + AS3 を使用して単純なメトロノーム コンポーネントを作成しています。たとえば、500ミリ秒ごとに「tick1」サウンドを再生し、4回ごとに別のサウンド「tick2」を再生します。しかし、実際にはサウンド間の遅延は同等ではありません。少ない場合もあれば、少し大きい場合もあります。最新のChromeでテストしています。

ここに私のコード:

//Somewhere here button bound to the 'toggle' function

import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.media.SoundTransform;
import flash.media.SoundChannel;

private var bpm:Number = 120; //2 bit per second, delay=500ms
private var period:Number = 4;
private var timer:Timer = new Timer(bpm, period);

[Embed(source='sounds/1.mp3')]
private var tickSound1Class:Class;
private var tickSound1:Sound;

[Embed(source='sounds/2.mp3')]
private var tickSound2Class:Class;
private var tickSound2:Sound;

private var trans:SoundTransform = new SoundTransform(1);

private function init():void {
    ....

    tickSound1 = new tickSound1Class() as Sound;
    tickSound2 = new tickSound2Class() as Sound;

    update();


    timer.addEventListener(TimerEvent.TIMER, onTimerEvent);

    ....
}

private function update():void {
    timer.delay = 1000 * 60/bpm;
    timer.repeatCount = 0;
}

private function toggle():void {
    if (timer.running) {
        timer.reset();
        startStopButton.label = "Start";
    } else {
        update();
        timer.start();
        startStopButton.label = "Stop";
    }
}

private function onTimerEvent(event:TimerEvent):void {
    var t:Timer = event.currentTarget as Timer;

    if (t.currentCount % period == 0)
        tickSound1.play(0, 0, trans);
    else
        tickSound2.play(0, 0, trans);
}
4

1 に答える 1

2

主な理由は次の 2 つだと思います。

  1. TimerFlash Player のオブジェクトが不正確であることが知られており、オブジェクトの発火間の遅延が変動します。
  2. Sound.play()この方法では、サウンドが実際に再生を開始する前に遅延が発生します。理論的には、この遅延は変動する可能性があります。Chrome で使用されている Flash Player の PPAPI バージョンでは、遅延が特に顕著です。

いくつかの解決策があります。次のいずれかをお勧めします。

  1. メトロノーム サイクル全体 (tick1-pause1-tick2-pause2) の事前に構成されたサウンドを使用し、Sound.play()メソッドの 2 番目の引数を使用してループします。
  2. 動的なサウンド生成を使用します。

2 番目のオプションはより柔軟ですが、実装がより困難です。基本的に、オブジェクトの新しいインスタンスを作成し、そのイベントをSoundサブスクライブして、そのメソッドを呼び出す必要があります。ハンドラーで をチェックします。これにより、サウンド生成の現在の位置がミリ秒単位で表示されます。次に、tick1 または tick2 サウンドを再生するときが来たと判断した場合は、 を呼び出すか、tick1 または tick2オブジェクトを呼び出すか、そうでない場合は無音を書き込みます。SAMPLE_DATAplay()event.position / 44.1tickN.extract(event.data, ...)tickNSound

ダイナミック サウンド生成の詳細については、こちらを参照してください。

また、呼び出すと、プロパティを持つオブジェクトSound.play()が返されることに注意してください。現時点で再生されている(生成されていない)サウンドのミリ秒単位の位置であり、正確です。したがって、このプロパティを使用して、3 番目のアプローチを考え出すことができます。オブジェクトを作成し、ダイナミック サウンド生成ソリューションのようにハンドラーをセットアップしますが、無音 (ゼロ) を常にハンドラー内のオブジェクトに書き込みます。これは、実際にサウンドを再生せずにサウンド チャネルを取得するために必要です。次に、高フレーム レート (60 FPS) と可能な限り最小の遅延 (1 ミリ秒) を使用します。火事のたびにチェックSoundChannelpositionSoundSAMPLE_DATAevent.dataTimerTimersoundChannel.positionティック音を再生する時間かどうかを判断し、そうであれば、例で行っているように再生します。このアプローチは、不正確さの問題を解決する可能性がありますが、メソッドTimerによって引き起こされる遅延を処理することはできません。tickSound.play()

于 2013-02-09T21:54:51.677 に答える