mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-12-18 12:02:33 -05:00
198 lines
4.1 KiB
Haxe
198 lines
4.1 KiB
Haxe
package funkin.audio;
|
|
|
|
import flixel.group.FlxGroup.FlxTypedGroup;
|
|
import flixel.sound.FlxSound;
|
|
|
|
/**
|
|
* A group of FlxSounds that are all synced together.
|
|
* Unlike FlxSoundGroup, you cann also control their time and pitch.
|
|
*/
|
|
class SoundGroup extends FlxTypedGroup<FlxSound>
|
|
{
|
|
public var time(get, set):Float;
|
|
|
|
public var volume(get, set):Float;
|
|
|
|
public var pitch(get, set):Float;
|
|
|
|
public function new()
|
|
{
|
|
super();
|
|
}
|
|
|
|
@:deprecated("Create sound files and call add() instead")
|
|
public static function build(song:String, ?files:Array<String> = null):SoundGroup
|
|
{
|
|
var result = new SoundGroup();
|
|
|
|
if (files == null)
|
|
{
|
|
// Add an empty voice.
|
|
result.add(new FlxSound());
|
|
return result;
|
|
}
|
|
|
|
for (sndFile in files)
|
|
{
|
|
var snd:FlxSound = new FlxSound().loadEmbedded(Paths.voices(song, '$sndFile'));
|
|
FlxG.sound.list.add(snd); // adds it to sound group for proper volumes
|
|
result.add(snd); // adds it to main group for other shit
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Finds the largest deviation from the desired time inside this SoundGroup.
|
|
*
|
|
* @param targetTime The time to check against.
|
|
* If none is provided, it checks the time of all members against the first member of this SoundGroup.
|
|
* @return The largest deviation from the target time found.
|
|
*/
|
|
public function checkSyncError(?targetTime:Float):Float
|
|
{
|
|
var error:Float = 0;
|
|
|
|
forEachAlive(function(snd) {
|
|
if (targetTime == null) targetTime = snd.time;
|
|
else
|
|
{
|
|
var diff:Float = snd.time - targetTime;
|
|
if (Math.abs(diff) > Math.abs(error)) error = diff;
|
|
}
|
|
});
|
|
return error;
|
|
}
|
|
|
|
/**
|
|
* Add a sound to the group.
|
|
*/
|
|
public override function add(sound:FlxSound):FlxSound
|
|
{
|
|
var result:FlxSound = super.add(sound);
|
|
|
|
if (result == null) return null;
|
|
|
|
// We have to play, then pause the sound to set the time,
|
|
// else the sound will restart immediately when played.
|
|
result.play(true, 0.0);
|
|
result.pause();
|
|
result.time = this.time;
|
|
|
|
result.onComplete = function() {
|
|
this.onComplete();
|
|
}
|
|
|
|
// Apply parameters to the new sound.
|
|
result.pitch = this.pitch;
|
|
result.volume = this.volume;
|
|
|
|
return result;
|
|
}
|
|
|
|
public dynamic function onComplete():Void {}
|
|
|
|
/**
|
|
* Pause all the sounds in the group.
|
|
*/
|
|
public function pause()
|
|
{
|
|
forEachAlive(function(sound:FlxSound) {
|
|
sound.pause();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Play all the sounds in the group.
|
|
*/
|
|
public function play(forceRestart:Bool = false, startTime:Float = 0.0, ?endTime:Float)
|
|
{
|
|
forEachAlive(function(sound:FlxSound) {
|
|
sound.play(forceRestart, startTime, endTime);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Resume all the sounds in the group.
|
|
*/
|
|
public function resume()
|
|
{
|
|
forEachAlive(function(sound:FlxSound) {
|
|
sound.resume();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Stop all the sounds in the group.
|
|
*/
|
|
public function stop()
|
|
{
|
|
forEachAlive(function(sound:FlxSound) {
|
|
sound.stop();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Remove all sounds from the group.
|
|
*/
|
|
public override function clear():Void
|
|
{
|
|
this.stop();
|
|
|
|
super.clear();
|
|
}
|
|
|
|
function get_time():Float
|
|
{
|
|
if (getFirstAlive() != null) return getFirstAlive().time;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
function set_time(time:Float):Float
|
|
{
|
|
forEachAlive(function(snd) {
|
|
// account for different offsets per sound?
|
|
snd.time = time;
|
|
});
|
|
|
|
return time;
|
|
}
|
|
|
|
function get_volume():Float
|
|
{
|
|
if (getFirstAlive() != null) return getFirstAlive().volume;
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
// in PlayState, adjust the code so that it only mutes the player1 vocal tracks?
|
|
function set_volume(volume:Float):Float
|
|
{
|
|
forEachAlive(function(snd) {
|
|
snd.volume = volume;
|
|
});
|
|
|
|
return volume;
|
|
}
|
|
|
|
function get_pitch():Float
|
|
{
|
|
#if FLX_PITCH
|
|
if (getFirstAlive() != null) return getFirstAlive().pitch;
|
|
else
|
|
#end
|
|
return 1;
|
|
}
|
|
|
|
function set_pitch(val:Float):Float
|
|
{
|
|
#if FLX_PITCH
|
|
trace('Setting audio pitch to ' + val);
|
|
forEachAlive(function(snd) {
|
|
snd.pitch = val;
|
|
});
|
|
#end
|
|
return val;
|
|
}
|
|
}
|