Support for 50 minute songs (html5 untested))
Experimental support for 3+ hour long songs comes later
This commit is contained in:
@@ -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