From 92ee5a280ace81b7c272e45c6495ba692400b2fe Mon Sep 17 00:00:00 2001 From: Ralty <78720179+Raltyro@users.noreply.github.com> Date: Sun, 27 Jul 2025 18:49:23 +0700 Subject: [PATCH] fix SoundChannel peaks & give AudioAnalyzer desc --- source/funkin/backend/utils/AudioAnalyzer.hx | 17 ++++++++++++++--- source/openfl/media/SoundChannel.hx | 14 ++++++++------ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/source/funkin/backend/utils/AudioAnalyzer.hx b/source/funkin/backend/utils/AudioAnalyzer.hx index 90d47d38..34bd3277 100644 --- a/source/funkin/backend/utils/AudioAnalyzer.hx +++ b/source/funkin/backend/utils/AudioAnalyzer.hx @@ -9,8 +9,13 @@ import lime.media.vorbis.VorbisFile; import lime.utils.ArrayBuffer; #end -// ORIGINAL CODES FROM YOSH & LUNAR https://github.com/CodenameCrew/YoshiCrafterEngine/blob/main/source/WaveformSprite.hx -// REWRITTEN BY RALTYRO +/** + * An utility that analyze FlxSounds, + * can be used to make waveform or real-time audio visualizer. + * + * FlxSound.amplitude does work in CNE so if any case if your only checking for peak of current + * time, use that instead. +**/ class AudioAnalyzer { public var sound:FlxSound; public var buffer:AudioBuffer; @@ -27,14 +32,20 @@ class AudioAnalyzer { var __vorbis:VorbisFile; #end + /** + * Creates an analyzer for specified FlxSound + * @param sound An FlxSound to analyze. + **/ public function new(sound:FlxSound) { this.sound = sound; __check(); } + /** + * TODO: IMPLEMENT FFT + **/ public function getLevels(levels:Array, barCount:Int, duration:Float):Float { __check(); - // TODO: implement FFT return 0; } diff --git a/source/openfl/media/SoundChannel.hx b/source/openfl/media/SoundChannel.hx index 6ccbf8ac..ae3ddf72 100644 --- a/source/openfl/media/SoundChannel.hx +++ b/source/openfl/media/SoundChannel.hx @@ -152,9 +152,7 @@ import lime.media.openal.AL; @:noCompletion private function __updatePeaks(time:Float):Bool { if (Math.abs(time - __lastPeakTime) < 8) return false; - __lastPeakTime = time; - __leftPeak = __rightPeak = 0; #if !macro if (!__isValid) return false; @@ -162,6 +160,7 @@ import lime.media.openal.AL; var buffer = __source.buffer; var wordSize = buffer.bitsPerSample >> 3, bitUnsignedSize = 1 << buffer.bitsPerSample, bitSize = 1 << (buffer.bitsPerSample - 1); var pos = Math.floor(time * buffer.sampleRate / 1000 * buffer.channels * wordSize), size = 0, buf; + var leftMin = 0, leftMax = 0, rightMin = 0, rightMax = 0; #if lime_cffi var backend = __source.__backend, i = 0; @@ -189,7 +188,10 @@ import lime.media.openal.AL; } if (b > bitSize) b -= bitUnsignedSize; } - ((c % 2 == 0) ? (if (__leftPeak < b) __leftPeak = b) : (if (__rightPeak < b) __rightPeak = b)); + if (c % 2 == 0) { + if (leftMax < b) leftMax = b; else if (leftMin < (b = -b)) leftMin = b; + } + else if (rightMax < b) rightMax = b; else if (rightMin < (b = -b)) rightMin = b; if (pos >= size) #if lime_cffi { if (!backend.streamed || ++i >= backend.bufferDatas.length) break; @@ -206,10 +208,10 @@ import lime.media.openal.AL; w = b = 0; } - if (buffer.channels == 1) __rightPeak = __leftPeak / bitSize; + if (buffer.channels == 1) __rightPeak = (__leftPeak = (leftMax + leftMin) / bitSize); else { - __leftPeak = __leftPeak / bitSize; - __rightPeak = __rightPeak / bitSize; + __leftPeak = (leftMax + leftMin) / bitSize; + __rightPeak = (rightMax + rightMin) / bitSize; } #end