music file priority thing

(updated a misleading comment, lols!)
This commit is contained in:
Kolo
2025-04-29 16:27:21 -04:00
committed by Eric
parent 5fdbd23a17
commit 31d3718e5c
3 changed files with 67 additions and 8 deletions
+58 -4
View File
@@ -14,6 +14,10 @@ import funkin.util.tools.ICloneable;
import funkin.util.flixel.sound.FlxPartialSound;
import funkin.Paths.PathsFunction;
import lime.app.Promise;
import lime.media.AudioSource;
import openfl.events.Event;
import openfl.media.Sound;
import openfl.media.SoundChannel;
import openfl.media.SoundMixer;
#if (openfl >= "8.0.0")
@@ -108,6 +112,11 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
return _waveformData;
}
/**
* If true, the game will forcefully add this sound's channel to the list of playing sounds.
*/
public var important:Bool = false;
/**
* Are we in a state where the song should play but time is negative?
*/
@@ -145,6 +154,14 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
else
{
super.update(elapsedSec);
@:privateAccess
{
if (important && _channel != null && !SoundMixer.__soundChannels.contains(_channel))
{
SoundMixer.__soundChannels.push(_channel);
}
}
}
}
@@ -431,13 +448,14 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
* @param persist Whether to keep this `FunkinSound` between states, or destroy it.
* @param onComplete Called when the sound finished playing.
* @param onLoad Called when the sound finished loading. Called immediately for succesfully loaded embedded sounds.
* @param important If `true`, the sound channel will forcefully be added onto the channel array, even if full. Use sparingly!
* @return A `FunkinSound` object, or `null` if the sound could not be loaded.
*/
public static function load(embeddedSound:FlxSoundAsset, volume:Float = 1.0, looped:Bool = false, autoDestroy:Bool = false, autoPlay:Bool = false,
persist:Bool = false, ?onComplete:Void->Void, ?onLoad:Void->Void):Null<FunkinSound>
persist:Bool = false, ?onComplete:Void->Void, ?onLoad:Void->Void, important:Bool = false):Null<FunkinSound>
{
@:privateAccess
if (SoundMixer.__soundChannels.length >= SoundMixer.MAX_ACTIVE_CHANNELS)
if (SoundMixer.__soundChannels.length >= SoundMixer.MAX_ACTIVE_CHANNELS && !important)
{
FlxG.log.error('FunkinSound could not play sound, channels exhausted! Found ${SoundMixer.__soundChannels.length} active sound channels.');
return null;
@@ -462,6 +480,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
sound.volume = volume;
sound.group = FlxG.sound.defaultSoundGroup;
sound.persist = persist;
sound.important = important;
// Make sure to add the sound to the list.
// If it's already in, it won't get re-added.
@@ -534,15 +553,50 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
this._label = 'unknown';
}
@:access(openfl.media.Sound)
@:access(openfl.media.SoundChannel)
@:access(openfl.media.SoundMixer)
override function startSound(startTime:Float)
{
if (!important)
{
super.startSound(startTime);
return;
}
_time = startTime;
_paused = false;
if (_sound == null) return;
// Create a channel manually if the sound is considered important.
var pan:Float = FlxMath.bound(SoundMixer.__soundTransform.pan + _transform.pan, -1, 1);
var volume:Float = FlxMath.bound(SoundMixer.__soundTransform.volume * _transform.volume, 0, MAX_VOLUME);
var audioSource:AudioSource = new AudioSource(_sound.__buffer);
audioSource.offset = Std.int(startTime);
audioSource.gain = volume;
var position:lime.math.Vector4 = audioSource.position;
position.x = pan;
position.z = -1 * Math.sqrt(1 - Math.pow(pan, 2));
audioSource.position = position;
_channel = new SoundChannel(_sound, audioSource, _transform);
_channel.addEventListener(Event.SOUND_COMPLETE, stopped);
pitch = _pitch;
active = true;
}
/**
* Play a sound effect once, then destroy it.
* @param key
* @param volume
* @return A `FunkinSound` object, or `null` if the sound could not be loaded.
*/
public static function playOnce(key:String, volume:Float = 1.0, ?onComplete:Void->Void, ?onLoad:Void->Void):Null<FunkinSound>
public static function playOnce(key:String, volume:Float = 1.0, ?onComplete:Void->Void, ?onLoad:Void->Void, important:Bool = false):Null<FunkinSound>
{
var result:Null<FunkinSound> = FunkinSound.load(key, volume, false, true, true, false, onComplete, onLoad);
var result:Null<FunkinSound> = FunkinSound.load(key, volume, false, true, true, false, onComplete, onLoad, important);
return result;
}
+1 -1
View File
@@ -255,7 +255,7 @@ class Countdown
var path = noteStyle.getCountdownSoundPath(step);
if (path == null) return null;
return FunkinSound.playOnce(path, Constants.COUNTDOWN_VOLUME);
return FunkinSound.playOnce(path, Constants.COUNTDOWN_VOLUME, null, null, true);
}
public static function decrement(step:CountdownStep):CountdownStep
+8 -3
View File
@@ -801,7 +801,7 @@ class SongDifficulty
{
var suffix:String = (instId != '') ? '-$instId' : '';
FlxG.sound.music = FunkinSound.load(Paths.inst(this.song.id, suffix), volume, looped, false, true);
FlxG.sound.music = FunkinSound.load(Paths.inst(this.song.id, suffix), volume, looped, false, true, false, null, null, true);
// Workaround for a bug where FlxG.sound.music.update() was being called twice.
FlxG.sound.list.remove(FlxG.sound.music);
@@ -948,16 +948,21 @@ class SongDifficulty
for (playerVoice in playerVoiceList)
{
if (!Assets.exists(playerVoice)) continue;
result.addPlayerVoice(FunkinSound.load(playerVoice));
result.addPlayerVoice(FunkinSound.load(playerVoice, 1.0, false, false, false, false, null, null, true));
}
// Add opponent vocals.
for (opponentVoice in opponentVoiceList)
{
if (!Assets.exists(opponentVoice)) continue;
result.addOpponentVoice(FunkinSound.load(opponentVoice));
result.addOpponentVoice(FunkinSound.load(opponentVoice, 1.0, false, false, false, false, null, null, true));
}
// Sometimes the sounds don't set their important value to true, so we have to do this manually.
result.forEach(function(snd:FunkinSound) {
snd.important = true;
});
result.playerVoicesOffset = offsets.getVocalOffset(characters.player, instId);
result.opponentVoicesOffset = offsets.getVocalOffset(characters.opponent, instId);