Как рассчитать амплитуду с помощью OpenFL - PullRequest
1 голос
/ 13 февраля 2020

Я искал способ получить звуковую амплитуду звука, воспроизводимого в данный момент времени, и API OpenFL предложил методы leftPeak и rightPeak класса SoundChannel. После нескольких тестов я мог наблюдать, что значение, возвращаемое методом, всегда было одинаковым: 1 (предполагается, что оно возвращает значение от 0 до 1)!

После поиска в исходном коде я смог обнаружить что leftPeak и rightPeak были только опубликованными c свойствами, установленными в конструкторе нашего SoundChannel объекта, но никогда не обновляющимися, и нет функции, объясняющей, как это сделать.

Может пожалуйста, поддержите меня, разработайте метод, чтобы вернуть амплитуду обратно?

Я положил код класса чуть ниже, чтобы подтвердить то, что я сказал!

Заранее спасибо.


#if !flash
import openfl.events.Event;
import openfl.events.EventDispatcher;
#if lime
import lime.media.AudioSource;
#end

/**
    The SoundChannel class controls a sound in an application. Every sound is
    assigned to a sound channel, and the application can have multiple sound
    channels that are mixed together. The SoundChannel class contains a
    `stop()` method, properties for monitoring the amplitude
    (volume) of the channel, and a property for assigning a SoundTransform
    object to the channel.

    @event soundComplete Dispatched when a sound has finished playing.
**/
#if !openfl_debug
@:fileXml('tags="haxe,release"')
@:noDebug
#end
@:access(openfl.media.SoundMixer)
@:final @:keep class SoundChannel extends EventDispatcher
{
    /**
        The current amplitude(volume) of the left channel, from 0(silent) to 1
        (full amplitude).
    **/
    public var leftPeak(default, null):Float;

    /**
        When the sound is playing, the `position` property indicates in
        milliseconds the current point that is being played in the sound file.
        When the sound is stopped or paused, the `position` property
        indicates the last point that was played in the sound file.

        A common use case is to save the value of the `position`
        property when the sound is stopped. You can resume the sound later by
        restarting it from that saved position.

        If the sound is looped, `position` is reset to 0 at the
        beginning of each loop.
    **/
    public var position(get, set):Float;

    /**
        The current amplitude(volume) of the right channel, from 0(silent) to 1
        (full amplitude).
    **/
    public var rightPeak(default, null):Float;

    /**
        The SoundTransform object assigned to the sound channel. A SoundTransform
        object includes properties for setting volume, panning, left speaker
        assignment, and right speaker assignment.
    **/
    public var soundTransform(get, set):SoundTransform;

    @:noCompletion private var __isValid:Bool;
    @:noCompletion private var __soundTransform:SoundTransform;
    #if lime
    @:noCompletion private var __source:AudioSource;
    #end

    #if openfljs
    @:noCompletion private static function __init__()
    {
        untyped Object.defineProperties(SoundChannel.prototype, {
            "position": {
                get: untyped __js__("function () { return this.get_position (); }"),
                set: untyped __js__("function (v) { return this.set_position (v); }")
            },
            "soundTransform": {
                get: untyped __js__("function () { return this.get_soundTransform (); }"),
                set: untyped __js__("function (v) { return this.set_soundTransform (v); }")
            },
        });
    }
    #end

    @:noCompletion private function new(source:#if lime AudioSource #else Dynamic #end = null, soundTransform:SoundTransform = null):Void
    {
        super(this);

        leftPeak = 1;
        rightPeak = 1;

        if (soundTransform != null)
        {
            __soundTransform = soundTransform;
        }
        else
        {
            __soundTransform = new SoundTransform();
        }

        #if lime
        if (source != null)
        {
            __source = source;
            __source.onComplete.add(source_onComplete);
            __isValid = true;

            __source.play();
        }
        #end

        SoundMixer.__registerSoundChannel(this);
    }

    /**
        Stops the sound playing in the channel.
    **/
    public function stop():Void
    {
        SoundMixer.__unregisterSoundChannel(this);

        if (!__isValid) return;

        #if lime
        __source.stop();
        #end
        __dispose();
    }

    @:noCompletion private function __dispose():Void
    {
        if (!__isValid) return;

        #if lime
        __source.onComplete.remove(source_onComplete);
        __source.dispose();
        __source = null;
        #end
        __isValid = false;
    }

    @:noCompletion private function __updateTransform():Void
    {
        this.soundTransform = soundTransform;
    }

    // Get & Set Methods
    @:noCompletion private function get_position():Float
    {
        if (!__isValid) return 0;

        #if lime
        return __source.currentTime + __source.offset;
        #else
        return 0;
        #end
    }

    @:noCompletion private function set_position(value:Float):Float
    {
        if (!__isValid) return 0;

        #if lime
        __source.currentTime = Std.int(value) - __source.offset;
        #end
        return value;
    }

    @:noCompletion private function get_soundTransform():SoundTransform
    {
        return __soundTransform.clone();
    }

    @:noCompletion private function set_soundTransform(value:SoundTransform):SoundTransform
    {
        if (value != null)
        {
            __soundTransform.pan = value.pan;
            __soundTransform.volume = value.volume;

            var pan = SoundMixer.__soundTransform.pan + __soundTransform.pan;

            if (pan < -1) pan = -1;
            if (pan > 1) pan = 1;

            var volume = SoundMixer.__soundTransform.volume * __soundTransform.volume;

            if (__isValid)
            {
                #if lime
                __source.gain = volume;

                var position = __source.position;
                position.x = pan;
                position.z = -1 * Math.sqrt(1 - Math.pow(pan, 2));
                __source.position = position;

                return value;
                #end
            }
        }

        return value;
    }

    // Event Handlers
    @:noCompletion private function source_onComplete():Void
    {
        SoundMixer.__unregisterSoundChannel(this);

        __dispose();
        dispatchEvent(new Event(Event.SOUND_COMPLETE));
    }
}
#else
typedef SoundChannel = flash.media.SoundChannel;
#end
...