Support for 50 minute songs (html5 untested))
Experimental support for 3+ hour long songs comes later
This commit is contained in:
+1
-1
@@ -1 +1 @@
|
||||
2036
|
||||
2042
|
||||
@@ -0,0 +1,253 @@
|
||||
package lime._internal.backend.html5;
|
||||
|
||||
import lime.math.Vector4;
|
||||
import lime.media.AudioSource;
|
||||
|
||||
@:access(lime.media.AudioBuffer)
|
||||
class HTML5AudioSource
|
||||
{
|
||||
private var completed:Bool;
|
||||
private var gain:Float;
|
||||
private var id:Int;
|
||||
private var length:Float;
|
||||
private var loops:Int;
|
||||
private var parent:AudioSource;
|
||||
private var playing:Bool;
|
||||
private var position:Vector4;
|
||||
|
||||
public function new(parent:AudioSource)
|
||||
{
|
||||
this.parent = parent;
|
||||
|
||||
id = -1;
|
||||
gain = 1;
|
||||
position = new Vector4();
|
||||
}
|
||||
|
||||
public function dispose():Void {}
|
||||
|
||||
public function init():Void {}
|
||||
|
||||
public function play():Void
|
||||
{
|
||||
#if lime_howlerjs
|
||||
if (playing || parent.buffer == null || parent.buffer.__srcHowl == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
playing = true;
|
||||
|
||||
var time = getCurrentTime();
|
||||
|
||||
completed = false;
|
||||
|
||||
var cacheVolume = untyped parent.buffer.__srcHowl._volume;
|
||||
untyped parent.buffer.__srcHowl._volume = parent.gain;
|
||||
|
||||
id = parent.buffer.__srcHowl.play();
|
||||
|
||||
untyped parent.buffer.__srcHowl._volume = cacheVolume;
|
||||
// setGain (parent.gain);
|
||||
|
||||
setPosition(parent.position);
|
||||
|
||||
parent.buffer.__srcHowl.on("end", howl_onEnd, id);
|
||||
|
||||
// Calling setCurrentTime causes html5 audio to replay from this position on next frame
|
||||
#if force_html5_audio
|
||||
if (time == 0) setCurrentTime(time);
|
||||
#else
|
||||
setCurrentTime(time);
|
||||
#end
|
||||
#end
|
||||
}
|
||||
|
||||
public function pause():Void
|
||||
{
|
||||
#if lime_howlerjs
|
||||
playing = false;
|
||||
|
||||
if (parent.buffer != null && parent.buffer.__srcHowl != null)
|
||||
{
|
||||
parent.buffer.__srcHowl.pause(id);
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
public function stop():Void
|
||||
{
|
||||
#if lime_howlerjs
|
||||
playing = false;
|
||||
|
||||
if (parent.buffer != null && parent.buffer.__srcHowl != null)
|
||||
{
|
||||
parent.buffer.__srcHowl.stop(id);
|
||||
parent.buffer.__srcHowl.off("end", howl_onEnd, id);
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
// Event Handlers
|
||||
private function howl_onEnd()
|
||||
{
|
||||
#if lime_howlerjs
|
||||
playing = false;
|
||||
|
||||
if (loops > 0)
|
||||
{
|
||||
loops--;
|
||||
stop();
|
||||
// currentTime = 0;
|
||||
play();
|
||||
return;
|
||||
}
|
||||
else if (parent.buffer != null && parent.buffer.__srcHowl != null)
|
||||
{
|
||||
parent.buffer.__srcHowl.stop(id);
|
||||
parent.buffer.__srcHowl.off("end", howl_onEnd, id);
|
||||
}
|
||||
|
||||
completed = true;
|
||||
parent.onComplete.dispatch();
|
||||
#end
|
||||
}
|
||||
|
||||
// Get & Set Methods
|
||||
public function getCurrentTime():Float
|
||||
{
|
||||
if (id == -1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if lime_howlerjs
|
||||
if (completed)
|
||||
{
|
||||
return getLength();
|
||||
}
|
||||
else if (parent.buffer != null && parent.buffer.__srcHowl != null)
|
||||
{
|
||||
var time = (parent.buffer.__srcHowl.seek(id) * 1000) - parent.offset;
|
||||
if (time < 0) return 0;
|
||||
return time;
|
||||
}
|
||||
#end
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function setCurrentTime(value:Float):Float
|
||||
{
|
||||
#if lime_howlerjs
|
||||
if (parent.buffer != null && parent.buffer.__srcHowl != null)
|
||||
{
|
||||
// if (playing) buffer.__srcHowl.play (id);
|
||||
var pos = (value + parent.offset) / 1000;
|
||||
if (pos < 0) pos = 0;
|
||||
parent.buffer.__srcHowl.seek(pos, id);
|
||||
}
|
||||
#end
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public function getGain():Float
|
||||
{
|
||||
return gain;
|
||||
}
|
||||
|
||||
public function setGain(value:Float):Float
|
||||
{
|
||||
#if lime_howlerjs
|
||||
// set howler volume only if we have an active id.
|
||||
// Passing -1 might create issues in future play()'s.
|
||||
|
||||
if (parent.buffer != null && parent.buffer.__srcHowl != null && id != -1)
|
||||
{
|
||||
parent.buffer.__srcHowl.volume(value, id);
|
||||
}
|
||||
#end
|
||||
|
||||
return gain = value;
|
||||
}
|
||||
|
||||
public function getLength():Float
|
||||
{
|
||||
if (length != 0)
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
#if lime_howlerjs
|
||||
if (parent.buffer != null && parent.buffer.__srcHowl != null)
|
||||
{
|
||||
return parent.buffer.__srcHowl.duration() * 1000;
|
||||
}
|
||||
#end
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function setLength(value:Float):Float
|
||||
{
|
||||
return length = value;
|
||||
}
|
||||
|
||||
public function getLoops():Int
|
||||
{
|
||||
return loops;
|
||||
}
|
||||
|
||||
public function setLoops(value:Int):Int
|
||||
{
|
||||
return loops = value;
|
||||
}
|
||||
|
||||
public function getPitch():Float
|
||||
{
|
||||
#if lime_howlerjs
|
||||
return parent.buffer.__srcHowl.rate();
|
||||
#else
|
||||
return 1;
|
||||
#end
|
||||
}
|
||||
|
||||
public function setPitch(value:Float):Float
|
||||
{
|
||||
#if lime_howlerjs
|
||||
parent.buffer.__srcHowl.rate(value);
|
||||
#end
|
||||
return getPitch();
|
||||
}
|
||||
|
||||
public function getPosition():Vector4
|
||||
{
|
||||
#if lime_howlerjs
|
||||
// This should work, but it returns null (But checking the inside of the howl, the _pos is actually null... so ¯\_(ツ)_/¯)
|
||||
/*
|
||||
var arr = parent.buffer.__srcHowl.pos())
|
||||
position.x = arr[0];
|
||||
position.y = arr[1];
|
||||
position.z = arr[2];
|
||||
*/
|
||||
#end
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
public function setPosition(value:Vector4):Vector4
|
||||
{
|
||||
position.x = value.x;
|
||||
position.y = value.y;
|
||||
position.z = value.z;
|
||||
position.w = value.w;
|
||||
|
||||
#if lime_howlerjs
|
||||
if (parent.buffer != null && parent.buffer.__srcHowl != null && parent.buffer.__srcHowl.pos != null) parent.buffer.__srcHowl.pos(position.x, position.y, position.z, id);
|
||||
// There are more settings to the position of the sound on the "pannerAttr()" function of howler. Maybe somebody who understands sound should look into it?
|
||||
#end
|
||||
|
||||
return position;
|
||||
}
|
||||
}
|
||||
@@ -34,16 +34,19 @@ class NativeAudioSource
|
||||
private var dataLength:Int;
|
||||
private var format:Int;
|
||||
private var handle:ALSource;
|
||||
private var length:Null<Int>;
|
||||
private var length:Null<Float>;
|
||||
private var loops:Int;
|
||||
private var parent:AudioSource;
|
||||
private var playing:Bool;
|
||||
private var position:Vector4;
|
||||
private var samples:Int;
|
||||
private var samples:Float;
|
||||
private var stream:Bool;
|
||||
private var streamTimer:Timer;
|
||||
private var timer:Timer;
|
||||
|
||||
private var pcmTotal:Int64;
|
||||
private var sampleRate:Int;
|
||||
|
||||
var disposed:Bool = false;
|
||||
|
||||
public function new(parent:AudioSource)
|
||||
@@ -107,7 +110,11 @@ class NativeAudioSource
|
||||
stream = true;
|
||||
|
||||
var vorbisFile = parent.buffer.__srcVorbisFile;
|
||||
dataLength = Std.int(Int64.toInt(vorbisFile.pcmTotal()) * parent.buffer.channels * (parent.buffer.bitsPerSample / 8));
|
||||
pcmTotal = vorbisFile.pcmTotal();
|
||||
var info = vorbisFile.info();
|
||||
sampleRate = info.rate;
|
||||
var _dataLength = pcmTotal * Int64.ofInt(parent.buffer.channels) * (Int64.ofInt(parent.buffer.bitsPerSample) / Int64.ofInt(8));
|
||||
dataLength = Int64.toInt(_dataLength);
|
||||
|
||||
buffers = new Array();
|
||||
bufferTimeBlocks = new Array();
|
||||
@@ -119,6 +126,8 @@ class NativeAudioSource
|
||||
}
|
||||
|
||||
handle = AL.createSource();
|
||||
|
||||
samples = Int64.toInt(pcmTotal);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -140,43 +149,15 @@ class NativeAudioSource
|
||||
{
|
||||
AL.sourcei(handle, AL.BUFFER, parent.buffer.__srcBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
samples = Std.int((dataLength * 8) / (parent.buffer.channels * parent.buffer.bitsPerSample));
|
||||
samples = Int64.toInt((Int64.make(0, dataLength) * Int64.ofInt(8)) / Int64.ofInt(parent.buffer.channels * parent.buffer.bitsPerSample));
|
||||
}
|
||||
|
||||
initBuffers.push(this);
|
||||
}
|
||||
|
||||
public function play():Void
|
||||
{
|
||||
/*var pitch:Float = AL.getSourcef (handle, AL.PITCH);
|
||||
trace(pitch);
|
||||
AL.sourcef (handle, AL.PITCH, pitch*0.9);
|
||||
pitch = AL.getSourcef (handle, AL.PITCH);
|
||||
trace(pitch); */
|
||||
/*var pos = getPosition();
|
||||
trace(AL.DISTANCE_MODEL);
|
||||
AL.distanceModel(AL.INVERSE_DISTANCE);
|
||||
trace(AL.DISTANCE_MODEL);
|
||||
AL.sourcef(handle, AL.ROLLOFF_FACTOR, 5);
|
||||
setPosition(new Vector4(10, 10, -100));
|
||||
pos = getPosition();
|
||||
trace(pos); */
|
||||
/*var filter = AL.createFilter();
|
||||
trace(AL.getErrorString());
|
||||
|
||||
AL.filteri(filter, AL.FILTER_TYPE, AL.FILTER_LOWPASS);
|
||||
trace(AL.getErrorString());
|
||||
|
||||
AL.filterf(filter, AL.LOWPASS_GAIN, 0.5);
|
||||
trace(AL.getErrorString());
|
||||
|
||||
AL.filterf(filter, AL.LOWPASS_GAINHF, 0.5);
|
||||
trace(AL.getErrorString());
|
||||
|
||||
AL.sourcei(handle, AL.DIRECT_FILTER, filter);
|
||||
trace(AL.getErrorString()); */
|
||||
|
||||
if (disposed) {
|
||||
trace("TRIED TO PLAY DISPOSED?? WTFFF");
|
||||
trace(haxe.CallStack.toString(haxe.CallStack.callStack()));
|
||||
@@ -373,7 +354,7 @@ class NativeAudioSource
|
||||
}
|
||||
|
||||
// Get & Set Methods
|
||||
public function getCurrentTime():Int
|
||||
public function getCurrentTime():Float
|
||||
{
|
||||
if (completed)
|
||||
{
|
||||
@@ -389,11 +370,11 @@ class NativeAudioSource
|
||||
}
|
||||
else
|
||||
{
|
||||
var offset = AL.getSourcei(handle, AL.BYTE_OFFSET);
|
||||
var offset:Int = AL.getSourcei(handle, AL.BYTE_OFFSET);
|
||||
var ratio = (offset / dataLength);
|
||||
var totalSeconds = samples / parent.buffer.sampleRate;
|
||||
|
||||
var time = Std.int(totalSeconds * ratio * 1000) - parent.offset;
|
||||
var time = totalSeconds * ratio * 1000 - parent.offset;
|
||||
|
||||
// var time = Std.int (AL.getSourcef (handle, AL.SEC_OFFSET) * 1000) - parent.offset;
|
||||
if (time < 0) return 0;
|
||||
@@ -404,7 +385,7 @@ class NativeAudioSource
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function setCurrentTime(value:Int):Int
|
||||
public function setCurrentTime(value:Float):Float
|
||||
{
|
||||
// `setCurrentTime()` has side effects and is never safe to skip.
|
||||
/* if (value == getCurrentTime())
|
||||
@@ -434,7 +415,7 @@ class NativeAudioSource
|
||||
var totalSeconds = samples / parent.buffer.sampleRate;
|
||||
|
||||
if (secondOffset < 0) secondOffset = 0;
|
||||
if (secondOffset > totalSeconds) secondOffset = totalSeconds;
|
||||
else if (secondOffset > totalSeconds) secondOffset = totalSeconds;
|
||||
|
||||
var ratio = (secondOffset / totalSeconds);
|
||||
var totalOffset = Std.int(dataLength * ratio);
|
||||
@@ -451,7 +432,7 @@ class NativeAudioSource
|
||||
timer.stop();
|
||||
}
|
||||
|
||||
var timeRemaining = Std.int((getLength() - value) / getPitch());
|
||||
var timeRemaining = (getLength() - value) / getPitch();
|
||||
|
||||
if (timeRemaining > 0)
|
||||
{
|
||||
@@ -491,17 +472,17 @@ class NativeAudioSource
|
||||
return value;
|
||||
}
|
||||
|
||||
public function getLength():Int
|
||||
public function getLength():Float
|
||||
{
|
||||
if (length != null)
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
return Std.int(samples / parent.buffer.sampleRate * 1000) - parent.offset;
|
||||
return (samples / parent.buffer.sampleRate * 1000) - parent.offset;
|
||||
}
|
||||
|
||||
public function setLength(value:Int):Int
|
||||
public function setLength(value:Float):Float
|
||||
{
|
||||
if (playing && length != value)
|
||||
{
|
||||
@@ -510,7 +491,7 @@ class NativeAudioSource
|
||||
timer.stop();
|
||||
}
|
||||
|
||||
var timeRemaining = Std.int((value - getCurrentTime()) / getPitch());
|
||||
var timeRemaining = (value - getCurrentTime()) / getPitch();
|
||||
|
||||
if (timeRemaining > 0)
|
||||
{
|
||||
@@ -553,7 +534,7 @@ class NativeAudioSource
|
||||
timer.stop();
|
||||
}
|
||||
|
||||
var timeRemaining = Std.int((getLength() - getCurrentTime()) / value);
|
||||
var timeRemaining = (getLength() - getCurrentTime()) / value;
|
||||
|
||||
if (timeRemaining > 0)
|
||||
{
|
||||
|
||||
@@ -13,9 +13,9 @@ class AudioSource
|
||||
{
|
||||
public var onComplete = new Event<Void->Void>();
|
||||
public var buffer:AudioBuffer;
|
||||
public var currentTime(get, set):Int;
|
||||
public var currentTime(get, set):Float;
|
||||
public var gain(get, set):Float;
|
||||
public var length(get, set):Int;
|
||||
public var length(get, set):Float;
|
||||
public var loops(get, set):Int;
|
||||
public var pitch(get, set):Float;
|
||||
public var offset:Int;
|
||||
@@ -69,12 +69,12 @@ class AudioSource
|
||||
}
|
||||
|
||||
// Get & Set Methods
|
||||
@:noCompletion private function get_currentTime():Int
|
||||
@:noCompletion private function get_currentTime():Float
|
||||
{
|
||||
return __backend.getCurrentTime();
|
||||
}
|
||||
|
||||
@:noCompletion private function set_currentTime(value:Int):Int
|
||||
@:noCompletion private function set_currentTime(value:Float):Float
|
||||
{
|
||||
return __backend.setCurrentTime(value);
|
||||
}
|
||||
@@ -89,12 +89,12 @@ class AudioSource
|
||||
return __backend.setGain(value);
|
||||
}
|
||||
|
||||
@:noCompletion private function get_length():Int
|
||||
@:noCompletion private function get_length():Float
|
||||
{
|
||||
return __backend.getLength();
|
||||
}
|
||||
|
||||
@:noCompletion private function set_length(value:Int):Int
|
||||
@:noCompletion private function set_length(value:Float):Float
|
||||
{
|
||||
return __backend.setLength(value);
|
||||
}
|
||||
|
||||
@@ -599,16 +599,16 @@ class Sound extends EventDispatcher
|
||||
#end
|
||||
}
|
||||
|
||||
var changeID:Int = 0;
|
||||
public function regen() {
|
||||
var audioBuffer = new AudioBuffer();
|
||||
var changeID:Int = 0;
|
||||
public function regen() {
|
||||
var audioBuffer = new AudioBuffer();
|
||||
audioBuffer.bitsPerSample = __buffer.bitsPerSample;
|
||||
audioBuffer.channels = __buffer.channels;
|
||||
audioBuffer.data = __buffer.data;
|
||||
audioBuffer.sampleRate = __buffer.sampleRate;
|
||||
|
||||
__buffer = audioBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Generates a new SoundChannel object to play back the sound. This method
|
||||
@@ -636,10 +636,10 @@ class Sound extends EventDispatcher
|
||||
return null;
|
||||
}
|
||||
|
||||
if (changeID < funkin.system.Main.changeID) {
|
||||
changeID = funkin.system.Main.changeID;
|
||||
regen();
|
||||
}
|
||||
if (changeID < funkin.system.Main.changeID) {
|
||||
changeID = funkin.system.Main.changeID;
|
||||
regen();
|
||||
}
|
||||
|
||||
if (sndTransform == null)
|
||||
{
|
||||
@@ -653,7 +653,7 @@ class Sound extends EventDispatcher
|
||||
var pan = SoundMixer.__soundTransform.pan + sndTransform.pan;
|
||||
|
||||
if (pan > 1) pan = 1;
|
||||
if (pan < -1) pan = -1;
|
||||
else if (pan < -1) pan = -1;
|
||||
|
||||
var volume = SoundMixer.__soundTransform.volume * sndTransform.volume;
|
||||
|
||||
@@ -680,23 +680,29 @@ class Sound extends EventDispatcher
|
||||
return new ID3Info();
|
||||
}
|
||||
|
||||
@:noCompletion private function get_length():Int
|
||||
@:noCompletion private function get_length():Float
|
||||
{
|
||||
#if lime
|
||||
if (__buffer != null)
|
||||
{
|
||||
#if (js && html5 && howlerjs)
|
||||
return Std.int(__buffer.src.duration() * 1000);
|
||||
return __buffer.src.duration() * 1000;
|
||||
#else
|
||||
if (__buffer.data != null)
|
||||
{
|
||||
var samples = (__buffer.data.length * 8) / (__buffer.channels * __buffer.bitsPerSample);
|
||||
return Std.int(samples / __buffer.sampleRate * 1000);
|
||||
// var samples = (__buffer.data.length * 8) / (__buffer.channels * __buffer.bitsPerSample);
|
||||
// return Std.int(samples / __buffer.sampleRate * 1000);
|
||||
var samples = (Int64.make(0, __buffer.data.length) * Int64.ofInt(8)) / Int64.ofInt(__buffer.channels * __buffer.bitsPerSample);
|
||||
var value = samples / Int64.ofInt(__buffer.sampleRate) * Int64.ofInt(1000);
|
||||
return Int64.toInt(value);
|
||||
}
|
||||
else if (__buffer.__srcVorbisFile != null)
|
||||
{
|
||||
var samples = Int64.toInt(__buffer.__srcVorbisFile.pcmTotal());
|
||||
return Std.int(samples / __buffer.sampleRate * 1000);
|
||||
//var samples = Int64.toInt(__buffer.__srcVorbisFile.pcmTotal());
|
||||
//return Std.int(samples / __buffer.sampleRate * 1000);
|
||||
var samples = __buffer.__srcVorbisFile.pcmTotal();
|
||||
var value = Int64.fromFloat(__buffer.__srcVorbisFile.timeTotal()) * 1000;
|
||||
return Int64.toInt(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
package openfl.media;
|
||||
|
||||
#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;
|
||||
|
||||
public var pitch(get, set):Float;
|
||||
|
||||
@: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 #if haxe4 js.Syntax.code #else __js__ #end ("function () { return this.get_position (); }"),
|
||||
set: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function (v) { return this.set_position (v); }")
|
||||
},
|
||||
"soundTransform": {
|
||||
get: untyped #if haxe4 js.Syntax.code #else __js__ #end ("function () { return this.get_soundTransform (); }"),
|
||||
set: untyped #if haxe4 js.Syntax.code #else __js__ #end ("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 = value - __source.offset;
|
||||
#end
|
||||
return value;
|
||||
}
|
||||
|
||||
@:noCompletion private function get_pitch():Float
|
||||
{
|
||||
if (!__isValid) return 1;
|
||||
|
||||
#if lime
|
||||
return __source.pitch;
|
||||
#else
|
||||
return 1;
|
||||
#end
|
||||
}
|
||||
|
||||
@:noCompletion private function set_pitch(value:Float):Float
|
||||
{
|
||||
if (!__isValid) return 1;
|
||||
|
||||
#if lime
|
||||
__source.pitch = value;
|
||||
#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;
|
||||
else 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
|
||||
Reference in New Issue
Block a user