initial freeplay songs loading

This commit is contained in:
Cameron Taylor 2024-04-18 20:23:03 -04:00
parent 77446f28d7
commit 1b6febf01c
6 changed files with 127 additions and 25 deletions

View file

@ -126,6 +126,7 @@
<haxelib name="hxCodec" if="desktop" unless="hl" /> <!-- Video playback -->
<haxelib name="funkin.vis"/>
<haxelib name="FlxPartialSound" /> <!-- Loading partial sound data -->
<haxelib name="json2object" /> <!-- JSON parsing -->
<haxelib name="thx.semver" /> <!-- Version string handling -->

View file

@ -79,7 +79,7 @@
{
"props": {
"ignoreExtern": true,
"format": "^[a-z][A-Z][A-Z0-9]*(_[A-Z0-9_]+)*$",
"format": "^[a-zA-Z0-9]+(?:_[a-zA-Z0-9]+)*$",
"tokens": ["INLINE", "NOTINLINE"]
},
"type": "ConstantName"

View file

@ -1,5 +1,12 @@
{
"dependencies": [
{
"name": "FlxPartialSound",
"type": "git",
"dir": null,
"ref": "main",
"url": "https://github.com/FunkinCrew/FlxPartialSound.git"
},
{
"name": "discord_rpc",
"type": "git",
@ -171,4 +178,4 @@
"url": "https://github.com/FunkinCrew/thx.semver"
}
]
}
}

View file

@ -123,9 +123,17 @@ class Paths
return 'songs:assets/songs/${song.toLowerCase()}/Voices$suffix.${Constants.EXT_SOUND}';
}
public static function inst(song:String, ?suffix:String = ''):String
/**
* Gets the path to an `Inst.mp3/ogg` song instrumental from songs:assets/songs/`song`/
* @param song name of the song to get instrumental for
* @param suffix any suffix to add to end of song name, used for `-erect` variants usually
* @param withExtension if it should return with the audio file extension `.mp3` or `.ogg`.
* @return String
*/
public static function inst(song:String, ?suffix:String = '', ?withExtension:Bool = true):String
{
return 'songs:assets/songs/${song.toLowerCase()}/Inst$suffix.${Constants.EXT_SOUND}';
var ext:String = withExtension ? '.${Constants.EXT_SOUND}' : '';
return 'songs:assets/songs/${song.toLowerCase()}/Inst$suffix$ext';
}
public static function image(key:String, ?library:String):String
@ -153,3 +161,11 @@ class Paths
return FlxAtlasFrames.fromSpriteSheetPacker(image(key, library), file('images/$key.txt', library));
}
}
enum abstract PathsFunction(String)
{
var MUSIC;
var INST;
var VOICES;
var SOUND;
}

View file

@ -11,7 +11,11 @@ import funkin.audio.waveform.WaveformDataParser;
import funkin.data.song.SongData.SongMusicData;
import funkin.data.song.SongRegistry;
import funkin.util.tools.ICloneable;
import funkin.util.flixel.sound.FlxPartialSound;
import funkin.Paths.PathsFunction;
import openfl.Assets;
import lime.app.Future;
import lime.app.Promise;
import openfl.media.SoundMixer;
#if (openfl >= "8.0.0")
import openfl.utils.AssetType;
@ -342,20 +346,52 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
FlxG.log.warn('Tried and failed to find music metadata for $key');
}
}
var music = FunkinSound.load(Paths.music('$key/$key'), params?.startingVolume ?? 1.0, params.loop ?? true, false, true);
if (music != null)
var pathsFunction = params.pathsFunction ?? MUSIC;
var pathToUse = switch (pathsFunction)
{
FlxG.sound.music = music;
case MUSIC: Paths.music('$key/$key');
case INST: Paths.inst('$key');
default: Paths.music('$key/$key');
}
// Prevent repeat update() and onFocus() calls.
FlxG.sound.list.remove(FlxG.sound.music);
var shouldLoadPartial = params.partialParams?.loadPartial ?? false;
return true;
if (shouldLoadPartial)
{
var music = FunkinSound.loadPartial(pathToUse, params.partialParams?.start ?? 0, params.partialParams?.end ?? 1, params?.startingVolume ?? 1.0,
params.loop ?? true, false, true);
if (music != null)
{
music.onComplete(function(partialMusic:Null<FunkinSound>) {
@:nullSafety(Off)
FlxG.sound.music = partialMusic;
FlxG.sound.list.remove(FlxG.sound.music);
});
return true;
}
else
{
return false;
}
}
else
{
return false;
var music = FunkinSound.load(pathToUse, params?.startingVolume ?? 1.0, params.loop ?? true, false, true);
if (music != null)
{
FlxG.sound.music = music;
// Prevent repeat update() and onFocus() calls.
FlxG.sound.list.remove(FlxG.sound.music);
return true;
}
else
{
return false;
}
}
}
@ -415,6 +451,36 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
return sound;
}
/**
* Will load a section of a sound file, useful for Freeplay where we don't want to load all the bytes of a song
* @param path The path to the sound file
* @param start The start time of the sound file
* @param end The end time of the sound file
* @param volume Volume to start at
* @param looped Whether the sound file should loop
* @param autoDestroy Whether the sound file should be destroyed after it finishes playing
* @param autoPlay Whether the sound file should play immediately
* @return A FunkinSound object
*/
public static function loadPartial(path:String, start:Float = 0, end:Float = 1, volume:Float = 1.0, looped:Bool = false, autoDestroy:Bool = false,
autoPlay:Bool = true, ?onComplete:Void->Void, ?onLoad:Void->Void):Future<Null<FunkinSound>>
{
var promise:lime.app.Promise<Null<FunkinSound>> = new lime.app.Promise<Null<FunkinSound>>();
// split the path and get only after first :
// we are bypassing the openfl/lime asset library fuss
path = Paths.stripLibrary(path);
var soundRequest = FlxPartialSound.partialLoadFromFile(path, start, end);
soundRequest.onComplete(function(partialSound) {
var snd = FunkinSound.load(partialSound, volume, looped, autoDestroy, autoPlay, onComplete, onLoad);
promise.complete(snd);
});
return promise.future;
}
@:nullSafety(Off)
public override function destroy():Void
{
@ -498,4 +564,19 @@ typedef FunkinSoundPlayMusicParams =
* @default `true`
*/
var ?mapTimeChanges:Bool;
/**
* Which Paths function to use to load a song
* @default `MUSIC`
*/
var ?pathsFunction:PathsFunction;
var ?partialParams:PartialSoundParams;
}
typedef PartialSoundParams =
{
var loadPartial:Bool;
var start:Float;
var end:Float;
}

View file

@ -1244,22 +1244,19 @@ class FreeplayState extends MusicBeatSubState
else
{
// TODO: Stream the instrumental of the selected song?
var didReplace:Bool = FunkinSound.playMusic('freakyMenu',
FunkinSound.playMusic(daSongCapsule.songData.songId,
{
startingVolume: 0.0,
startingVolume: 0.5,
overrideExisting: true,
restartTrack: false
restartTrack: false,
pathsFunction: INST,
partialParams:
{
loadPartial: true,
start: 0,
end: 0.1
}
});
if (didReplace)
{
FunkinSound.playMusic('freakyMenu',
{
startingVolume: 0.0,
overrideExisting: true,
restartTrack: false
});
FlxG.sound.music.fadeIn(2, 0, 0.8);
}
}
grpCapsules.members[curSelected].selected = true;
}