Merge remote-tracking branch 'origin/main'

This commit is contained in:
Frakits
2025-08-01 20:33:15 +03:00
5 changed files with 103 additions and 65 deletions
+50 -36
View File
@@ -38,6 +38,54 @@ class AudioAnalyzer {
else return inline ArrayBufferIO.getUint8(buffer, position) - 128;
}
/**
* Gets levels from the frequencies with specified sample rate.
* @param frequencies Frequencies input.
* @param sampleRate Sample Rate input.
* @param barCount How much bars to get.
* @param levels The output for getting the values, to avoid memory leaks (Optional).
* @param delta How much delta for smoothen the values from the previous levels values (Optional).
* @param minDb The minimum decibels to cap (Optional, default -70.0).
* @param maxDb The maximum decibels to cap (Optional, default -10.0).
* @param minFreq The minimum frequency to cap (Optional, default 20.0).
* @param maxFreq The maximum frequency to cap (Optional, default 22000.0).
* @return Output of levels/bars
*/
public static function getLevelsFromFrequencies(frequencies:Array<Float>, sampleRate:Int, barCount:Int, ?levels:Array<Float>, delta = 0.0, minDb = -70.0, maxDb = -10.0, minFreq = 20.0, maxFreq = 22000.0):Array<Float> {
if (levels == null) levels = [];
levels.resize(barCount);
var logMin = Math.log(minFreq), logMax = Math.log(maxFreq);
var logRange = logMax - logMin, dbRange = maxDb - minDb, n = frequencies.length;
inline function calculateScale(i:Int)
return CoolUtil.bound(Math.exp(logMin + (logRange * i / (barCount + 1))) * n * 2 / sampleRate, 0, n - 1);
var s1 = calculateScale(0), s2;
var i1 = Math.floor(s1), i2;
var v, range;
for (i in 0...barCount) {
if ((range = (s2 = calculateScale(i + 1)) - s1) < 1) {
i2 = Math.ceil(s2);
if (i2 == i1) v = frequencies[i1] * range;
else v = (frequencies[i1] + (frequencies[i2] - frequencies[i1]) * (s1 - i1)) * range;
}
else {
v = frequencies[i1] * (Math.ceil(s1) - i1);
if (i1 != (i2 = Math.floor(s2))) {
while (++i1 < i2) v += frequencies[i1];
v += frequencies[i2] * (s2 - Math.floor(s2));
}
}
i1 = Math.floor(s1 = s2);
v = ((20 * Math.log(v) / 2.302585092994046) - minDb) / dbRange;
if (delta > 0 && delta < 1 && v < levels[i]) levels[i] -= Math.pow(levels[i] - v, 2.302585092994046) * delta;
else levels[i] = v;
}
return levels;
}
/**
* The current sound to analyze.
*/
@@ -184,42 +232,8 @@ class AudioAnalyzer {
* @param maxFreq The maximum frequency to cap (Optional, default 22000.0).
* @return Output of levels/bars
*/
public function getLevels(startPos:Float, barCount:Int, ?levels:Array<Float>, delta = 0.0, minDb = -70.0, maxDb = -10.0, minFreq = 20.0, maxFreq = 22000.0):Array<Float> {
__frequencies = getFrequencies(startPos, __frequencies);
if (levels == null) levels = [];
levels.resize(barCount);
var logMin = Math.log(minFreq), logMax = Math.log(maxFreq);
var logRange = logMax - logMin, dbRange = maxDb - minDb;
inline function calculateScale(i:Int)
return CoolUtil.bound(Math.exp(logMin + (logRange * i / (barCount + 1))) * fftN / buffer.sampleRate, 0, __N2 - 1);
var s1 = calculateScale(0), s2;
var i1 = Math.floor(s1), i2;
var v, range;
for (i in 0...barCount) {
if ((range = (s2 = calculateScale(i + 1)) - s1) < 1) {
i2 = Math.ceil(s2);
if (i2 == i1) v = __frequencies[i1] * range;
else v = (__frequencies[i1] + (__frequencies[i2] - __frequencies[i1]) * (s1 - i1)) * range;
}
else {
v = __frequencies[i1] * (Math.ceil(s1) - i1);
if (i1 != (i2 = Math.floor(s2))) {
while (++i1 < i2) v += __frequencies[i1];
v += __frequencies[i2] * (s2 - Math.floor(s2));
}
}
i1 = Math.floor(s1 = s2);
v = ((20 * Math.log(v) / 2.302585092994046) - minDb) / dbRange;
if (delta > 0 && delta < 1 && v < levels[i]) levels[i] -= Math.pow(levels[i] - v, 2) * delta;
else levels[i] = v;
}
return levels;
}
public function getLevels(startPos:Float, barCount:Int, ?levels:Array<Float>, ?delta:Float, ?minDb:Float, ?maxDb:Float, ?minFreq:Float, ?maxFreq:Float):Array<Float>
return inline getLevelsFromFrequencies(__frequencies = getFrequencies(startPos, __frequencies), buffer.sampleRate, barCount, levels, delta, minDb, maxDb, minFreq, maxFreq);
/**
* Gets frequencies from an attached FlxSound from startPos.
+6 -4
View File
@@ -63,9 +63,11 @@ final class WindowUtils {
* @param image The image to set as the icon.
**/
public static inline function setWindow(?name:String, ?image:String)
{
Lib.application.window.setIcon(lime.graphics.Image.fromBytes(Assets.getBytes(Flags.MOD_ICON != null ? Flags.MOD_ICON : image)));
title = Flags.MOD_NAME != null ? Flags.MOD_NAME : title;
{
// Coded by HeroEyad using Pigeon Text Editor v2.03 (E.G.E. Edition)
Lib.application.window.setIcon(lime.graphics.Image.fromBytes(Assets.getBytes(image != null ? image : Flags.MOD_ICON)));
title = name != null ? name : Flags.MOD_NAME;
// End of HeroEyad Code. Coded by HeroEyad.
}
/**
@@ -90,4 +92,4 @@ final class WindowUtils {
@:noCompletion private inline static function set_winTitle(value:String):String {
return title = value;
}
}
}
+19 -10
View File
@@ -633,16 +633,22 @@ class Charter extends UIState {
// create events
rightEventsGroup.autoSort = leftEventsGroup.autoSort = false;
var __last:CharterEvent = null;
var __lastTime:Float = Math.NaN;
for (e in PlayState.SONG.events) {
if (e == null) continue;
if (__last != null && __lastTime == e.time) {
__last.events.push(e);
} else {
__last = new CharterEvent(Conductor.getStepForTime(e.time), [e]);
__lastTime = e.time;
(__last.global ? rightEventsGroup : leftEventsGroup).add(__last);
var lastLeftEvents:CharterEvent = null, lastRightEvents:CharterEvent = null, lastEvents:CharterEvent;
var lastLeftTime = Math.NaN, lastRightTime = Math.NaN, lastTime:Float;
for (e in PlayState.SONG.events) if (e != null) {
if (e.global) {
lastEvents = lastRightEvents;
lastTime = lastRightTime;
}
else {
lastEvents = lastLeftEvents;
lastTime = lastLeftTime;
}
if (lastEvents != null && lastTime == e.time) lastEvents.events.push(e);
else {
lastEvents = new CharterEvent(Conductor.getStepForTime(lastTime = e.time), [e], e.global);
(e.global ? rightEventsGroup : leftEventsGroup).add(lastEvents);
}
}
@@ -2278,6 +2284,9 @@ class Charter extends UIState {
public function buildEvents() {
PlayState.SONG.events = [];
for (ce in leftEventsGroup.members) for (e in ce.events) e.global = false;
for (ce in rightEventsGroup.members) for (e in ce.events) e.global = true;
var events:Array<CharterEvent> = leftEventsGroup.members.concat(rightEventsGroup.members);
events.sort(rightEventsGroup.sortEventsFilter.bind(FlxSort.ASCENDING));
for (e in events) for (event in e.events) {
+26 -13
View File
@@ -246,24 +246,37 @@ class FreeplayState extends MusicBeatState
autoplayElapsed += elapsed;
if (!disableAutoPlay && !songInstPlaying && (autoplayElapsed > timeUntilAutoplay || FlxG.keys.justPressed.SPACE)) {
if (curPlayingInst != (curPlayingInst = Paths.inst(songs[curSelected].name, songs[curSelected].difficulties[curDifficulty]))) {
var huh:Void->Void = function() {
var soundPath = curPlayingInst;
var sound = null;
if (Assets.exists(soundPath, SOUND) || Assets.exists(soundPath, MUSIC))
sound = Assets.getSound(soundPath);
else
FlxG.log.error('Could not find a Sound asset with an ID of \'$soundPath\'.');
var streamed = false;
if (Options.streamedMusic) {
var sound = Assets.getMusic(curPlayingInst, true, false);
streamed = sound != null;
if (sound != null && autoplayShouldPlay) {
if (streamed && autoplayShouldPlay) {
FlxG.sound.playMusic(sound, 0);
Conductor.changeBPM(songs[curSelected].bpm, songs[curSelected].beatsPerMeasure, songs[curSelected].stepsPerBeat);
}
}
if (!disableAsyncLoading) Main.execAsync(huh);
else huh();
if (!streamed) {
var huh:Void->Void = function() {
var soundPath = curPlayingInst;
var sound = null;
if (Assets.exists(soundPath, SOUND) || Assets.exists(soundPath, MUSIC))
sound = Assets.getSound(soundPath);
else
FlxG.log.error('Could not find a Sound asset with an ID of \'$soundPath\'.');
if (sound != null && autoplayShouldPlay) {
FlxG.sound.playMusic(sound, 0);
Conductor.changeBPM(songs[curSelected].bpm, songs[curSelected].beatsPerMeasure, songs[curSelected].stepsPerBeat);
}
}
if (!disableAsyncLoading) Main.execAsync(huh);
else huh();
}
}
songInstPlaying = true;
if(disableAsyncLoading) dontPlaySongThisFrame = true;
if (disableAsyncLoading && !Options.streamedMusic) dontPlaySongThisFrame = true;
}
#end
@@ -423,8 +436,8 @@ class FreeplayState extends MusicBeatState
changeDiff(0, true);
#if PRELOAD_ALL
autoplayElapsed = 0;
songInstPlaying = false;
autoplayElapsed = 0;
songInstPlaying = false;
#end
coopText.visible = songs[curSelected].coopAllowed || songs[curSelected].opponentModeAllowed;
+2 -2
View File
@@ -241,7 +241,7 @@ class Assets
return null;
}
public static function getMusic(id:String, useCache:Bool = true):Sound
public static function getMusic(id:String, useCache:Bool = true, staticFallback:Bool = true):Sound
{
#if (lime_vorbis && lime > "7.9.0" && !macro)
if (Options.streamedMusic) {
@@ -251,7 +251,7 @@ class Assets
if (vorbisFile != null) return Sound.fromAudioBuffer(AudioBuffer.fromVorbisFile(vorbisFile));
}
#end
return getSound(id, useCache);
return if (staticFallback) getSound(id, useCache); else null;
}
/**