11package funkin .vis .dsp ;
22
3+ import haxe .io .Bytes ;
4+ import lime .utils .UInt8Array ;
35import flixel .FlxG ;
46import flixel .math .FlxMath ;
57import funkin .vis ._internal .html5 .AnalyzerNode ;
@@ -8,6 +10,10 @@ import grig.audio.FFT;
810import grig .audio .FFTVisualization ;
911import lime .media .AudioSource ;
1012
13+ #if lime_vorbis
14+ import lime .media .vorbis .VorbisFile ;
15+ #end
16+
1117using grig .audio .lime .UInt8ArrayTools ;
1218
1319typedef Bar =
@@ -58,6 +64,9 @@ class SpectralAnalyzer
5864 #end
5965 private var _logGraphCache : Array <Int > = [];
6066 private var _mixedCache : Array <Float > = [];
67+ #if lime_vorbis
68+ private var vorbisBuffer : UInt8Array ;
69+ #end
6170
6271 private function freqToBin (freq : Float , mathType : MathType = Round ): Int
6372 {
@@ -193,8 +202,8 @@ class SpectralAnalyzer
193202
194203 return levels ;
195204 #else
196- var numOctets = Std .int (audioSource . buffer .bitsPerSample / 8 );
197- var wantedLength = fftN * numOctets * audioSource . buffer .channels ;
205+ var numOctets = Std .int (audioClip . audioBuffer .bitsPerSample / 8 );
206+ var wantedLength = fftN * numOctets * audioClip . audioBuffer .channels ;
198207 var startFrame = audioClip .currentFrame ;
199208
200209 if (startFrame < 0 )
@@ -203,9 +212,36 @@ class SpectralAnalyzer
203212 }
204213
205214 startFrame - = startFrame % numOctets ;
206- var segment = audioSource .buffer .data .subarray (startFrame , min (startFrame + wantedLength , audioSource .buffer .data .length ));
207215
208- getSignal (segment , audioSource .buffer .bitsPerSample ); // Sets _buffer
216+ var endFrame : Int = min (startFrame + wantedLength , audioClip .audioBuffer .length );
217+
218+ #if lime_vorbis
219+ if (audioClip .streamed )
220+ {
221+ vorbisBuffer = null ;
222+
223+ @:privateAccess
224+ var vorbisFile = audioSource .buffer .__srcVorbisFile ;
225+
226+ // reading from VorbisFile will automatically move the position
227+ // which causes issues with playback, so we keep old time to go back to it
228+ var prevPos = vorbisFile .pcmTell ();
229+
230+ vorbisFile .pcmSeek (Std .int (startFrame / (numOctets + audioClip .audioBuffer .channels )));
231+
232+ @:privateAccess
233+ vorbisBuffer = readVorbisFileBuffer (vorbisFile , wantedLength );
234+
235+ vorbisFile .pcmSeek (prevPos );
236+
237+ getSignal (vorbisBuffer , audioClip .audioBuffer .bitsPerSample );
238+ }
239+ else
240+ #end
241+ {
242+ var segment : UInt8Array = audioSource .buffer .data .subarray (startFrame , endFrame );
243+ getSignal (segment , audioClip .audioBuffer .bitsPerSample );
244+ }
209245
210246 if (audioSource .buffer .channels > 1 ) {
211247 var wantedArrayLength = Std .int (_buffer .length / audioSource .buffer .channels );
@@ -290,6 +326,43 @@ class SpectralAnalyzer
290326 return _buffer ;
291327 }
292328
329+ #if lime_vorbis
330+ // Pretty much copied from
331+ // https://github.com/openfl/lime/blob/develop/src/lime/_internal/backend/native/NativeAudioSource.hx#L212
332+ function readVorbisFileBuffer (vorbisFile : VorbisFile , length : Int ): UInt8Array
333+ {
334+ if (vorbisBuffer == null || vorbisBuffer .length != length )
335+ vorbisBuffer = new UInt8Array (length );
336+
337+ var read : Int = 0 ;
338+ var total : Int = 0 ;
339+ var readMax : Int = 4096 ;
340+
341+ while (total < length )
342+ {
343+ readMax = 4096 ;
344+
345+ if (readMax > length - total )
346+ {
347+ readMax = length - total ;
348+ }
349+
350+ read = vorbisFile .read (vorbisBuffer .buffer , total , readMax );
351+
352+ if (read > 0 )
353+ {
354+ total + = read ;
355+ }
356+ else
357+ {
358+ break ;
359+ }
360+ }
361+
362+ return vorbisBuffer ;
363+ }
364+ #end
365+
293366 @:generic
294367 static inline function clamp <T : Float >(val : T , min : T , max : T ): T
295368 {
0 commit comments