mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2025-03-23 05:15:14 -04:00
Rework offsets to be built into the FlxSound
This commit is contained in:
parent
1716ffc57f
commit
1abd587645
6 changed files with 168 additions and 52 deletions
source/funkin
audio
play/song
ui/debug/charting/handlers
util/assets
129
source/funkin/audio/FunkinSound.hx
Normal file
129
source/funkin/audio/FunkinSound.hx
Normal file
|
@ -0,0 +1,129 @@
|
|||
package funkin.audio;
|
||||
|
||||
#if flash11
|
||||
import flash.media.Sound;
|
||||
import flash.utils.ByteArray;
|
||||
#end
|
||||
import flixel.sound.FlxSound;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.system.FlxAssets.FlxSoundAsset;
|
||||
import openfl.Assets;
|
||||
#if (openfl >= "8.0.0")
|
||||
import openfl.utils.AssetType;
|
||||
#end
|
||||
|
||||
/**
|
||||
* A FlxSound which adds additional functionality:
|
||||
* - Delayed playback via negative song position.
|
||||
*/
|
||||
@:nullSafety
|
||||
class FunkinSound extends FlxSound
|
||||
{
|
||||
static var cache(default, null):FlxTypedGroup<FunkinSound> = new FlxTypedGroup<FunkinSound>();
|
||||
|
||||
/**
|
||||
* Are we in a state where the song should play but time is negative?
|
||||
*/
|
||||
var shouldPlay:Bool = false;
|
||||
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public override function update(elapsedSec:Float)
|
||||
{
|
||||
if (!playing && !shouldPlay) return;
|
||||
|
||||
if (_time < 0)
|
||||
{
|
||||
var elapsedMs = elapsedSec * Constants.MS_PER_SEC;
|
||||
_time += elapsedMs;
|
||||
if (_time >= 0)
|
||||
{
|
||||
_time = 0;
|
||||
shouldPlay = false;
|
||||
super.play();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
super.update(elapsedSec);
|
||||
}
|
||||
}
|
||||
|
||||
public override function play(forceRestart:Bool = false, startTime:Float = 0, ?endTime:Float):FunkinSound
|
||||
{
|
||||
if (!exists) return this;
|
||||
|
||||
if (forceRestart)
|
||||
{
|
||||
cleanup(false, true);
|
||||
}
|
||||
else if (playing || shouldPlay)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
if (startTime < 0)
|
||||
{
|
||||
shouldPlay = true;
|
||||
_time = startTime;
|
||||
this.endTime = endTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
if (_paused)
|
||||
{
|
||||
resume();
|
||||
}
|
||||
else
|
||||
{
|
||||
startSound(startTime);
|
||||
}
|
||||
|
||||
this.endTime = endTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new `FunkinSound` object.
|
||||
*
|
||||
* @param embeddedSound The embedded sound resource you want to play. To stream, use the optional URL parameter instead.
|
||||
* @param volume How loud to play it (0 to 1).
|
||||
* @param looped Whether to loop this sound.
|
||||
* @param group The group to add this sound to.
|
||||
* @param autoDestroy Whether to destroy this sound when it finishes playing.
|
||||
* Leave this value set to `false` if you want to re-use this `FunkinSound` instance.
|
||||
* @param autoPlay Whether to play the sound immediately or wait for a `play()` call.
|
||||
* @param onComplete Called when the sound finished playing.
|
||||
* @param onLoad Called when the sound finished loading. Called immediately for succesfully loaded embedded sounds.
|
||||
* @return A `FunkinSound` object.
|
||||
*/
|
||||
public static function load(embeddedSound:FlxSoundAsset, volume:Float = 1.0, looped:Bool = false, autoDestroy:Bool = false, autoPlay:Bool = false,
|
||||
?onComplete:Void->Void, ?onLoad:Void->Void):FunkinSound
|
||||
{
|
||||
var sound:FunkinSound = cache.recycle(construct);
|
||||
|
||||
sound.loadEmbedded(embeddedSound, looped, autoDestroy, onComplete);
|
||||
|
||||
sound.volume = volume;
|
||||
sound.group = FlxG.sound.defaultSoundGroup;
|
||||
if (autoPlay) sound.play();
|
||||
|
||||
// Call OnlLoad() because the sound already loaded
|
||||
if (onLoad != null && sound._sound != null) onLoad();
|
||||
|
||||
return sound;
|
||||
}
|
||||
|
||||
static function construct():FunkinSound
|
||||
{
|
||||
var sound:FunkinSound = new FunkinSound();
|
||||
|
||||
cache.add(sound);
|
||||
FlxG.sound.list.add(sound);
|
||||
|
||||
return sound;
|
||||
}
|
||||
}
|
|
@ -2,12 +2,13 @@ package funkin.audio;
|
|||
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.sound.FlxSound;
|
||||
import funkin.audio.FunkinSound;
|
||||
|
||||
/**
|
||||
* A group of FlxSounds that are all synced together.
|
||||
* Unlike FlxSoundGroup, you cann also control their time and pitch.
|
||||
* A group of FunkinSounds that are all synced together.
|
||||
* Unlike FlxSoundGroup, you can also control their time and pitch.
|
||||
*/
|
||||
class SoundGroup extends FlxTypedGroup<FlxSound>
|
||||
class SoundGroup extends FlxTypedGroup<FunkinSound>
|
||||
{
|
||||
public var time(get, set):Float;
|
||||
|
||||
|
@ -28,14 +29,13 @@ class SoundGroup extends FlxTypedGroup<FlxSound>
|
|||
if (files == null)
|
||||
{
|
||||
// Add an empty voice.
|
||||
result.add(new FlxSound());
|
||||
result.add(new FunkinSound());
|
||||
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
|
||||
var snd:FunkinSound = FunkinSound.load(Paths.voices(song, '$sndFile'));
|
||||
result.add(snd); // adds it to main group for other shit
|
||||
}
|
||||
|
||||
|
@ -67,9 +67,9 @@ class SoundGroup extends FlxTypedGroup<FlxSound>
|
|||
/**
|
||||
* Add a sound to the group.
|
||||
*/
|
||||
public override function add(sound:FlxSound):FlxSound
|
||||
public override function add(sound:FunkinSound):FunkinSound
|
||||
{
|
||||
var result:FlxSound = super.add(sound);
|
||||
var result:FunkinSound = super.add(sound);
|
||||
|
||||
if (result == null) return null;
|
||||
|
||||
|
@ -97,7 +97,7 @@ class SoundGroup extends FlxTypedGroup<FlxSound>
|
|||
*/
|
||||
public function pause()
|
||||
{
|
||||
forEachAlive(function(sound:FlxSound) {
|
||||
forEachAlive(function(sound:FunkinSound) {
|
||||
sound.pause();
|
||||
});
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ class SoundGroup extends FlxTypedGroup<FlxSound>
|
|||
*/
|
||||
public function play(forceRestart:Bool = false, startTime:Float = 0.0, ?endTime:Float)
|
||||
{
|
||||
forEachAlive(function(sound:FlxSound) {
|
||||
forEachAlive(function(sound:FunkinSound) {
|
||||
sound.play(forceRestart, startTime, endTime);
|
||||
});
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ class SoundGroup extends FlxTypedGroup<FlxSound>
|
|||
*/
|
||||
public function resume()
|
||||
{
|
||||
forEachAlive(function(sound:FlxSound) {
|
||||
forEachAlive(function(sound:FunkinSound) {
|
||||
sound.resume();
|
||||
});
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ class SoundGroup extends FlxTypedGroup<FlxSound>
|
|||
*/
|
||||
public function stop()
|
||||
{
|
||||
forEachAlive(function(sound:FlxSound) {
|
||||
forEachAlive(function(sound:FunkinSound) {
|
||||
sound.stop();
|
||||
});
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ class SoundGroup extends FlxTypedGroup<FlxSound>
|
|||
|
||||
function set_time(time:Float):Float
|
||||
{
|
||||
forEachAlive(function(snd) {
|
||||
forEachAlive(function(snd:FunkinSound) {
|
||||
// account for different offsets per sound?
|
||||
snd.time = time;
|
||||
});
|
||||
|
@ -169,7 +169,7 @@ class SoundGroup extends FlxTypedGroup<FlxSound>
|
|||
// in PlayState, adjust the code so that it only mutes the player1 vocal tracks?
|
||||
function set_volume(volume:Float):Float
|
||||
{
|
||||
forEachAlive(function(snd) {
|
||||
forEachAlive(function(snd:FunkinSound) {
|
||||
snd.volume = volume;
|
||||
});
|
||||
|
||||
|
@ -189,7 +189,7 @@ class SoundGroup extends FlxTypedGroup<FlxSound>
|
|||
{
|
||||
#if FLX_PITCH
|
||||
trace('Setting audio pitch to ' + val);
|
||||
forEachAlive(function(snd) {
|
||||
forEachAlive(function(snd:FunkinSound) {
|
||||
snd.pitch = val;
|
||||
});
|
||||
#end
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package funkin.audio;
|
||||
|
||||
import flixel.sound.FlxSound;
|
||||
import funkin.audio.FunkinSound;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
|
||||
class VoicesGroup extends SoundGroup
|
||||
{
|
||||
var playerVoices:FlxTypedGroup<FlxSound>;
|
||||
var opponentVoices:FlxTypedGroup<FlxSound>;
|
||||
var playerVoices:FlxTypedGroup<FunkinSound>;
|
||||
var opponentVoices:FlxTypedGroup<FunkinSound>;
|
||||
|
||||
/**
|
||||
* Control the volume of only the sounds in the player group.
|
||||
|
@ -31,14 +31,14 @@ class VoicesGroup extends SoundGroup
|
|||
public function new()
|
||||
{
|
||||
super();
|
||||
playerVoices = new FlxTypedGroup<FlxSound>();
|
||||
opponentVoices = new FlxTypedGroup<FlxSound>();
|
||||
playerVoices = new FlxTypedGroup<FunkinSound>();
|
||||
opponentVoices = new FlxTypedGroup<FunkinSound>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a voice to the player group.
|
||||
*/
|
||||
public function addPlayerVoice(sound:FlxSound):Void
|
||||
public function addPlayerVoice(sound:FunkinSound):Void
|
||||
{
|
||||
super.add(sound);
|
||||
playerVoices.add(sound);
|
||||
|
@ -46,7 +46,7 @@ class VoicesGroup extends SoundGroup
|
|||
|
||||
function set_playerVolume(volume:Float):Float
|
||||
{
|
||||
playerVoices.forEachAlive(function(voice:FlxSound) {
|
||||
playerVoices.forEachAlive(function(voice:FunkinSound) {
|
||||
voice.volume = volume;
|
||||
});
|
||||
return playerVolume = volume;
|
||||
|
@ -59,10 +59,10 @@ class VoicesGroup extends SoundGroup
|
|||
snd.time = time;
|
||||
});
|
||||
|
||||
playerVoices.forEachAlive(function(voice:FlxSound) {
|
||||
playerVoices.forEachAlive(function(voice:FunkinSound) {
|
||||
voice.time -= playerVoicesOffset;
|
||||
});
|
||||
opponentVoices.forEachAlive(function(voice:FlxSound) {
|
||||
opponentVoices.forEachAlive(function(voice:FunkinSound) {
|
||||
voice.time -= opponentVoicesOffset;
|
||||
});
|
||||
|
||||
|
@ -71,7 +71,7 @@ class VoicesGroup extends SoundGroup
|
|||
|
||||
function set_playerVoicesOffset(offset:Float):Float
|
||||
{
|
||||
playerVoices.forEachAlive(function(voice:FlxSound) {
|
||||
playerVoices.forEachAlive(function(voice:FunkinSound) {
|
||||
voice.time += playerVoicesOffset;
|
||||
voice.time -= offset;
|
||||
});
|
||||
|
@ -80,33 +80,17 @@ class VoicesGroup extends SoundGroup
|
|||
|
||||
function set_opponentVoicesOffset(offset:Float):Float
|
||||
{
|
||||
opponentVoices.forEachAlive(function(voice:FlxSound) {
|
||||
opponentVoices.forEachAlive(function(voice:FunkinSound) {
|
||||
voice.time += opponentVoicesOffset;
|
||||
voice.time -= offset;
|
||||
});
|
||||
return opponentVoicesOffset = offset;
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float):Void
|
||||
{
|
||||
forEachAlive(function(snd) {
|
||||
if (snd.time < 0)
|
||||
{
|
||||
// Sync the time without calling update().
|
||||
// time gets reset if it's negative.
|
||||
snd.time += elapsed * 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
snd.update(elapsed);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a voice to the opponent group.
|
||||
*/
|
||||
public function addOpponentVoice(sound:FlxSound):Void
|
||||
public function addOpponentVoice(sound:FunkinSound):Void
|
||||
{
|
||||
super.add(sound);
|
||||
opponentVoices.add(sound);
|
||||
|
@ -114,7 +98,7 @@ class VoicesGroup extends SoundGroup
|
|||
|
||||
function set_opponentVolume(volume:Float):Float
|
||||
{
|
||||
opponentVoices.forEachAlive(function(voice:FlxSound) {
|
||||
opponentVoices.forEachAlive(function(voice:FunkinSound) {
|
||||
voice.volume = volume;
|
||||
});
|
||||
return opponentVolume = volume;
|
||||
|
|
|
@ -2,6 +2,7 @@ package funkin.play.song;
|
|||
|
||||
import flixel.sound.FlxSound;
|
||||
import funkin.audio.VoicesGroup;
|
||||
import funkin.audio.FunkinSound;
|
||||
import funkin.data.IRegistryEntry;
|
||||
import funkin.data.song.SongData.SongCharacterData;
|
||||
import funkin.data.song.SongData.SongChartData;
|
||||
|
@ -532,16 +533,16 @@ class SongDifficulty
|
|||
}
|
||||
|
||||
// Add player vocals.
|
||||
if (voiceList[0] != null) result.addPlayerVoice(new FlxSound().loadEmbedded(Assets.getSound(voiceList[0])));
|
||||
if (voiceList[0] != null) result.addPlayerVoice(FunkinSound.load(Assets.getSound(voiceList[0])));
|
||||
// Add opponent vocals.
|
||||
if (voiceList[1] != null) result.addOpponentVoice(new FlxSound().loadEmbedded(Assets.getSound(voiceList[1])));
|
||||
if (voiceList[1] != null) result.addOpponentVoice(FunkinSound.load(Assets.getSound(voiceList[1])));
|
||||
|
||||
// Add additional vocals.
|
||||
if (voiceList.length > 2)
|
||||
{
|
||||
for (i in 2...voiceList.length)
|
||||
{
|
||||
result.add(new FlxSound().loadEmbedded(Assets.getSound(voiceList[i])));
|
||||
result.add(FunkinSound.load(Assets.getSound(voiceList[i])));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package funkin.ui.debug.charting.handlers;
|
|||
import flixel.system.FlxAssets.FlxSoundAsset;
|
||||
import flixel.system.FlxSound;
|
||||
import funkin.audio.VoicesGroup;
|
||||
import funkin.audio.FunkinSound;
|
||||
import funkin.play.character.BaseCharacter.CharacterType;
|
||||
import funkin.util.FileUtil;
|
||||
import funkin.util.assets.SoundUtil;
|
||||
|
@ -165,7 +166,7 @@ class ChartEditorAudioHandler
|
|||
{
|
||||
var trackId:String = '${charId}${instId == '' ? '' : '-${instId}'}';
|
||||
var vocalTrackData:Null<Bytes> = state.audioVocalTrackData.get(trackId);
|
||||
var vocalTrack:Null<FlxSound> = SoundUtil.buildFlxSoundFromBytes(vocalTrackData);
|
||||
var vocalTrack:Null<FunkinSound> = SoundUtil.buildSoundFromBytes(vocalTrackData);
|
||||
|
||||
if (state.audioVocalTrackGroup == null) state.audioVocalTrackGroup = new VoicesGroup();
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package funkin.util.assets;
|
||||
|
||||
import haxe.io.Bytes;
|
||||
import flixel.system.FlxSound;
|
||||
import openfl.media.Sound as OpenFLSound;
|
||||
import funkin.audio.FunkinSound;
|
||||
|
||||
class SoundUtil
|
||||
{
|
||||
|
@ -11,13 +12,13 @@ class SoundUtil
|
|||
* @param input The byte data.
|
||||
* @return The playable sound, or `null` if loading failed.
|
||||
*/
|
||||
public static function buildFlxSoundFromBytes(input:Null<Bytes>):Null<FlxSound>
|
||||
public static function buildSoundFromBytes(input:Null<Bytes>):Null<FunkinSound>
|
||||
{
|
||||
if (input == null) return null;
|
||||
|
||||
var openflSound:openfl.media.Sound = new openfl.media.Sound();
|
||||
var openflSound:OpenFLSound = new OpenFLSound();
|
||||
openflSound.loadCompressedDataFromByteArray(openfl.utils.ByteArray.fromBytes(input), input.length);
|
||||
var output:FlxSound = FlxG.sound.load(openflSound, 1.0, false);
|
||||
var output:FunkinSound = FunkinSound.load(openflSound, 1.0, false);
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue