From 2ead99cdf4d6b912acb8afe4a46af338327c6f43 Mon Sep 17 00:00:00 2001 From: Ralty <78720179+Raltyro@users.noreply.github.com> Date: Sun, 13 Jul 2025 21:10:42 +0700 Subject: [PATCH] Fix Mismatching Audio Streamed Buffer Size --- source/funkin/backend/utils/AudioAnalyzer.hx | 12 ++++++------ .../_internal/backend/native/NativeAudioSource.hx | 15 +++++++++------ source/openfl/media/SoundChannel.hx | 9 ++++----- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/source/funkin/backend/utils/AudioAnalyzer.hx b/source/funkin/backend/utils/AudioAnalyzer.hx index 1d944551..8d1d08e2 100644 --- a/source/funkin/backend/utils/AudioAnalyzer.hx +++ b/source/funkin/backend/utils/AudioAnalyzer.hx @@ -2,11 +2,11 @@ package funkin.backend.utils; import flixel.sound.FlxSound; import lime.media.AudioBuffer; -import lime.utils.ArrayBufferView; #if lime_vorbis import lime.media.vorbis.Vorbis; 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 @@ -72,12 +72,12 @@ class AudioAnalyzer { } #if lime_vorbis // As far i know, only native supports vorbis - var __buffer:ArrayBufferView; + var __buffer:ArrayBuffer; function __prepareVorbis():Bool @:privateAccess { if (buffer.__srcVorbisFile == null) return __vorbis != null; if (__vorbis != null) return true; if ((__vorbis = buffer.__srcVorbisFile.clone()) != null) { // IM HOPING IT HAVE A GC CLOSURE. - __buffer = new ArrayBufferView(0x1000, buffer.bitsPerSample == 32 ? Int32 : buffer.bitsPerSample == 16 ? Int16 : Int8); + __buffer = new ArrayBuffer(0x400 * buffer.channels * (buffer.bitsPerSample >> 3)); return true; } return false; @@ -95,17 +95,17 @@ class AudioAnalyzer { prevPos = Math.floor(endPos); } - var isBigEndian = lime.system.System.endianness == lime.system.Endian.BIG_ENDIAN, bufferSize = __buffer.length, buf = __buffer.buffer; + var isBigEndian = lime.system.System.endianness == lime.system.Endian.BIG_ENDIAN, bufferSize = __buffer.length; var max = 0, b = 0, pos = 0, w = 0, result; while (n > 0) { - n -= (result = __vorbis.read(buf, 0, n < bufferSize ? n : bufferSize, isBigEndian, __wordSize, true)); + n -= (result = __vorbis.read(__buffer, 0, n < bufferSize ? n : bufferSize, isBigEndian, __wordSize, true)); if (result == Vorbis.HOLE) continue; else if (result <= 0) break; while (pos < result) { while (w < buffer.bitsPerSample) { - b |= #if js buf[pos] #else buf.get(pos) #end << w; + b |= #if js __buffer[pos] #else __buffer.get(pos) #end << w; w += 8; pos++; } diff --git a/source/lime/_internal/backend/native/NativeAudioSource.hx b/source/lime/_internal/backend/native/NativeAudioSource.hx index 33368f95..3ef6b002 100644 --- a/source/lime/_internal/backend/native/NativeAudioSource.hx +++ b/source/lime/_internal/backend/native/NativeAudioSource.hx @@ -25,7 +25,7 @@ import lime.utils.ArrayBufferView; @:access(lime.media.AudioBuffer) @:access(lime.utils.ArrayBufferView) class NativeAudioSource { - private static var STREAM_BUFFER_SIZE:Int = 0x4000; // what if it was odd channels (excluding mono). + private static var STREAM_BUFFER_SIZE:Int = 0x1000; private static var STREAM_MAX_BUFFERS:Int = 32; private static var STREAM_TIMER_FREQUENCY:Int = 100; private static var STREAM_BUFFER_FREQUENCY:Int = 6; @@ -47,6 +47,7 @@ class NativeAudioSource { private var bufferDatas:Array; private var bufferTimes:Array; private var bufferSizes:Array; + private var bufferSize:Int; private var requestBuffers:Int; private var queuedBuffers:Int; private var toLoop:Int; @@ -107,11 +108,13 @@ class NativeAudioSource { dataLength = (samples = getFloat(buffer.__srcVorbisFile.pcmTotal())) * buffer.channels * (buffer.bitsPerSample >> 3); var constructor = buffer.bitsPerSample == 32 ? Int32 : buffer.bitsPerSample == 16 ? Int16 : Int8; + bufferSize = STREAM_BUFFER_SIZE * buffer.channels * (constructor == Int8 ? buffer.bitsPerSample >> 3 : 1); buffers = AL.genBuffers(STREAM_MAX_BUFFERS); - bufferDatas = [for (i in 0...STREAM_MAX_BUFFERS) new ArrayBufferView(STREAM_BUFFER_SIZE, constructor)]; + bufferDatas = [for (i in 0...STREAM_MAX_BUFFERS) new ArrayBufferView(bufferSize, constructor)]; bufferTimes = [for (i in 0...STREAM_MAX_BUFFERS) 0]; bufferSizes = [for (i in 0...STREAM_MAX_BUFFERS) 0]; unusedBuffers = []; + bufferSize *= constructor == Int8 ? 1 : buffer.bitsPerSample >> 3; } else #end { streamed = false; @@ -184,10 +187,10 @@ class NativeAudioSource { #if lime_vorbis var isBigEndian = lime.system.System.endianness == lime.system.Endian.BIG_ENDIAN, wordSize = parent.buffer.bitsPerSample >> 3; var size = dataLength - (streamTell() * parent.buffer.sampleRate * parent.buffer.channels * wordSize); - var n:Int = size < STREAM_BUFFER_SIZE ? Math.floor(size) : STREAM_BUFFER_SIZE; + var n:Int = size < bufferSize ? Math.floor(size) : bufferSize; var total = 0, result = 0, wasEOF = false; - while (total < STREAM_BUFFER_SIZE) { + while (total < bufferSize) { result = n > 0 ? parent.buffer.__srcVorbisFile.read(data.buffer, total, n, isBigEndian, wordSize, true) : 0; if (result == Vorbis.HOLE) continue; @@ -200,7 +203,7 @@ class NativeAudioSource { var samples = getSamples(loopTime != null ? loopTime + parent.offset : parent.offset); streamSeek(samples); - if ((size = dataLength - (getFloat(samples) * parent.buffer.channels * wordSize)) < (n = STREAM_BUFFER_SIZE - total)) + if ((size = dataLength - (getFloat(samples) * parent.buffer.channels * wordSize)) < (n = bufferSize - total)) n = Math.floor(size); } } @@ -211,7 +214,7 @@ class NativeAudioSource { } } - if (total < STREAM_BUFFER_SIZE) data.buffer.fill(total, n, 0); + if (total < bufferSize) data.buffer.fill(total, n, 0); if (result < 0) { trace('NativeAudioSource Streaming Bug! reading result is $result'); return result; diff --git a/source/openfl/media/SoundChannel.hx b/source/openfl/media/SoundChannel.hx index c5c042af..32f24c58 100644 --- a/source/openfl/media/SoundChannel.hx +++ b/source/openfl/media/SoundChannel.hx @@ -164,20 +164,19 @@ 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(samples * buffer.channels * wordSize); - var n = Math.floor(Math.min(buffer.sampleRate / 80, 600)), b = 0, w = 0, c = 0, i = 0, size = 0, buf; + var pos = Math.floor(samples * buffer.channels * wordSize), size = 0, i = 0, buf; + pos -= pos % wordSize; if (backend.streamed) { buf = backend.bufferDatas[i = NativeAudioSource.STREAM_MAX_BUFFERS - backend.queuedBuffers] #if !js .buffer #end; - pos %= (size = NativeAudioSource.STREAM_BUFFER_SIZE * wordSize); + size = backend.bufferSize; } else { buf = buffer.data #if !js .buffer #end; size = #if js buf.byteLength #else buf.length #end; } - pos -= pos % wordSize; - + var n = Math.floor(Math.min(buffer.sampleRate / 80, 512)), b = 0, w = 0, c = 0; while (n > 0) { if (wordSize == 1) b = #if js buf[pos] #else buf.get(pos) #end - bitSize; else {