diff --git a/building/libs.xml b/building/libs.xml index 531a07713..897cf843e 100644 --- a/building/libs.xml +++ b/building/libs.xml @@ -18,6 +18,7 @@ + diff --git a/project.xml b/project.xml index 3d6399a14..76a1d0b58 100644 --- a/project.xml +++ b/project.xml @@ -115,6 +115,11 @@ + +
+ +
+ @@ -127,6 +132,8 @@ + + diff --git a/source/funkin/backend/assets/Paths.hx b/source/funkin/backend/assets/Paths.hx index 5b8d8395f..5b343cac6 100644 --- a/source/funkin/backend/assets/Paths.hx +++ b/source/funkin/backend/assets/Paths.hx @@ -81,25 +81,76 @@ class Paths return getPath('data/$key.ps1', library); static public function sound(key:String, ?library:String, ?ext:String) + { + if (ext == null) + for (path in Flags.SOUND_EXTENSIONS) { + var path = 'sounds/$key.$path'; + if (OpenFlAssets.exists(path)) + return getPath(path, library); + } + return getPath('sounds/$key.${ext != null ? ext : Flags.SOUND_EXT}', library); + } public static inline function soundRandom(key:String, min:Int, max:Int, ?library:String) return sound(key + FlxG.random.int(min, max), library); - inline static public function music(key:String, ?library:String, ?ext:String) + static public function music(key:String, ?library:String, ?ext:String) + { + if (ext == null) + for (path in Flags.SOUND_EXTENSIONS) + { + var path = 'music/$key.$path'; + if (OpenFlAssets.exists(getPath(path, library))) + return getPath(path, library); + } + return getPath('music/$key.${ext != null ? ext : Flags.SOUND_EXT}', library); + } - inline static public function voices(song:String, ?difficulty:String, ?suffix:String = "", ?ext:String) { + static public function voices(song:String, ?difficulty:String, ?suffix:String = "", ?ext:String) { if (difficulty == null) difficulty = Flags.DEFAULT_DIFFICULTY; + + if (ext == null) + for (e in Flags.SOUND_EXTENSIONS) + { + var path = 'songs/$song/song/Voices$suffix-${difficulty}.$e'; + trace(path + " | " + OpenFlAssets.exists(getPath(path, null))); + if (OpenFlAssets.exists(getPath(path, null))) + return getPath(path, null); + + path = 'songs/$song/song/Voices$suffix.$e'; + trace(path + " | " + OpenFlAssets.exists(getPath(path, null))); + if (OpenFlAssets.exists(getPath(path, null))) + return getPath(path, null); + } + if (ext == null) ext = Flags.SOUND_EXT; var diff = getPath('songs/$song/song/Voices$suffix-${difficulty}.${ext}', null); + trace(diff); return OpenFlAssets.exists(diff) ? diff : getPath('songs/$song/song/Voices$suffix.${ext}', null); } - inline static public function inst(song:String, ?difficulty:String, ?suffix:String = "", ?ext:String) { + static public function inst(song:String, ?difficulty:String, ?suffix:String = "", ?ext:String) { if (difficulty == null) difficulty = Flags.DEFAULT_DIFFICULTY; + + if (ext == null) + for (e in Flags.SOUND_EXTENSIONS) + { + var path = 'songs/$song/song/Inst$suffix-${difficulty}.$e'; + trace(path + " | " + OpenFlAssets.exists(getPath(path, null))); + if (OpenFlAssets.exists(getPath(path, null))) + return getPath(path, null); + + path = 'songs/$song/song/Inst$suffix.$e'; + trace(path + " | " + OpenFlAssets.exists(getPath(path, null))); + if (OpenFlAssets.exists(getPath(path, null))) + return getPath(path, null); + } + if (ext == null) ext = Flags.SOUND_EXT; var diff = getPath('songs/$song/song/Inst$suffix-${difficulty}.${ext}', null); + trace(diff); return OpenFlAssets.exists(diff) ? diff : getPath('songs/$song/song/Inst$suffix.${ext}', null); } diff --git a/source/funkin/backend/chart/ChartData.hx b/source/funkin/backend/chart/ChartData.hx index dfb514bde..c8ca39f43 100644 --- a/source/funkin/backend/chart/ChartData.hx +++ b/source/funkin/backend/chart/ChartData.hx @@ -39,6 +39,8 @@ typedef ChartMetaData = { public var ?instSuffix:String; public var ?vocalsSuffix:String; public var ?needsVoices:Bool; + + public var ?musicExt:String; } typedef ChartStrumLine = { diff --git a/source/funkin/backend/scripting/Script.hx b/source/funkin/backend/scripting/Script.hx index 8f7ee4372..3c0a9a7b8 100644 --- a/source/funkin/backend/scripting/Script.hx +++ b/source/funkin/backend/scripting/Script.hx @@ -107,7 +107,7 @@ class Script extends FlxBasic implements IFlxDestroyable { #if TRANSLATIONS_SUPPORT "TranslationUtil" => funkin.backend.utils.TranslationUtil, - "translate" => funkin.backend.utils.TranslationUtil.get, + "translate" => funkin.backend.utils.TranslationUtil.get, #end ]; } diff --git a/source/funkin/backend/system/Flags.hx b/source/funkin/backend/system/Flags.hx index 1b96f7260..3438056da 100644 --- a/source/funkin/backend/system/Flags.hx +++ b/source/funkin/backend/system/Flags.hx @@ -56,6 +56,11 @@ class Flags { public static var REPO_OWNER:String = "CodenameCrew"; public static var REPO_URL:String = 'https://github.com/$REPO_OWNER/$REPO_NAME'; + public static var SOUND_EXTENSIONS:Array = [ + #if web "mp3" #else "ogg" #end, + "opus" + ]; + /** * Preferred sound extension for the game's audio files. * Currently is set to `mp3` for web targets, and `ogg` for other targets. diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index 952fdacac..1baac0a08 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -608,9 +608,9 @@ class Charter extends UIState { Conductor.setupSong(PlayState.SONG); noteTypes = PlayState.SONG.noteTypes; - FlxG.sound.setMusic(FlxG.sound.load(Paths.inst(__song, __diff, PlayState.SONG.meta.instSuffix))); - if (Assets.exists(Paths.voices(__song, __diff, PlayState.SONG.meta.vocalsSuffix))) - vocals = FlxG.sound.load(Paths.voices(__song, __diff, PlayState.SONG.meta.vocalsSuffix)); + FlxG.sound.setMusic(FlxG.sound.load(Paths.inst(__song, __diff, PlayState.SONG.meta.instSuffix, PlayState.SONG.meta.musicExt))); + if (Assets.exists(Paths.voices(__song, __diff, PlayState.SONG.meta.vocalsSuffix, PlayState.SONG.meta.musicExt))) + vocals = FlxG.sound.load(Paths.voices(__song, __diff, PlayState.SONG.meta.vocalsSuffix, PlayState.SONG.meta.musicExt)); else vocals = new FlxSound(); diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx index 76752ac43..b28d9dc01 100644 --- a/source/funkin/game/PlayState.hx +++ b/source/funkin/game/PlayState.hx @@ -1129,11 +1129,11 @@ class PlayState extends MusicBeatState curSong = songData.meta.name.toLowerCase(); curSongID = curSong.replace(" ", "-"); - FlxG.sound.setMusic(inst = FlxG.sound.load(Assets.getMusic(Paths.inst(SONG.meta.name, difficulty, SONG.meta.instSuffix)))); + FlxG.sound.setMusic(inst = FlxG.sound.load(Assets.getMusic(Paths.inst(SONG.meta.name, difficulty, SONG.meta.instSuffix, SONG.meta.musicExt)))); - var vocalsPath = Paths.voices(SONG.meta.name, difficulty, SONG.meta.vocalsSuffix); + var vocalsPath = Paths.voices(SONG.meta.name, difficulty, SONG.meta.vocalsSuffix, SONG.meta.musicExt); if (SONG.meta.needsVoices && Assets.exists(vocalsPath)) - vocals = FlxG.sound.load(Options.streamedVocals ? Assets.getMusic(vocalsPath) : vocalsPath); + vocals = FlxG.sound.load(Options.streamedVocals ? Assets.getMusic(vocalsPath) : vocalsPath, SONG.meta.musicExt); else vocals = new FlxSound(); diff --git a/source/funkin/menus/FreeplayState.hx b/source/funkin/menus/FreeplayState.hx index 69fc3d8de..d82615356 100644 --- a/source/funkin/menus/FreeplayState.hx +++ b/source/funkin/menus/FreeplayState.hx @@ -259,7 +259,7 @@ class FreeplayState extends MusicBeatState var dontPlaySongThisFrame = false; autoplayElapsed += elapsed; if (!disableAutoPlay && !songInstPlaying && (autoplayElapsed > timeUntilAutoplay)) { - if (curPlayingInst != (curPlayingInst = Paths.inst(curSong.name, curDifficulties[curDifficulty], curSong.instSuffix))) { + if (curPlayingInst != (curPlayingInst = Paths.inst(curSong.name, curDifficulties[curDifficulty], curSong.instSuffix, curSong.musicExt))) { var streamed = false; if (Options.streamedMusic) { var sound = Assets.getMusic(curPlayingInst, true, false); diff --git a/source/openfl/utils/Assets.hx b/source/openfl/utils/Assets.hx index c14b9f2c9..5ac054dcf 100644 --- a/source/openfl/utils/Assets.hx +++ b/source/openfl/utils/Assets.hx @@ -22,6 +22,9 @@ import lime.utils.Assets as LimeAssets; import lime.media.AudioBuffer; import lime.media.vorbis.VorbisFile; #end +#if OPUS_AUDIO_PLAYBACK +import hxopus.Opus; +#end /** The Assets class provides a cross-platform interface to access @@ -288,13 +291,10 @@ class Assets var sound = cache.getSound(id); if (isValidSound(sound)) - { return sound; - } } var buffer = LimeAssets.getAudioBuffer(id, false); - if (buffer != null) { #if flash @@ -304,12 +304,25 @@ class Assets #end if (useCache && cache.enabled) - { cache.setSound(id, sound); - } return sound; } + + #if OPUS_AUDIO_PLAYBACK + // Try to load as Opus if normal loading failed + var bytes = getBytes(id); + if (bytes != null) + { + var sound = Opus.toOpenFL(bytes); + + if (useCache && cache.enabled) + cache.setSound(id, sound); + + return sound; + } + #end + #end return null;