11package funkin .audio .waveform ;
22
33import funkin .util .TimerUtil ;
4+ import haxe .ds .Vector ;
5+ import haxe .io .Bytes ;
46
57class WaveformDataParser
68{
@@ -51,11 +53,31 @@ class WaveformDataParser
5153 var pointsPerSecond : Float = sampleRate / samplesPerPoint ; // 172 samples per second for most songs is plenty precise while still being performant..
5254
5355 // TODO: Make this work better on HTML5.
54- var soundData : lime.utils. Int16Array = cast soundBuffer .data ;
56+ var soundData : Bytes = soundBuffer .data .toBytes ();
57+ var fakeBitsPerSample : Int = bitsPerSample ;
58+ var minSampleValue : Int ;
59+ var maxSampleValue : Int ;
60+
61+ switch (bitsPerSample )
62+ {
63+ case 8 :
64+ minSampleValue = INT8_MIN ;
65+ maxSampleValue = INT8_MAX ;
66+ case 16 :
67+ minSampleValue = INT16_MIN ;
68+ maxSampleValue = INT16_MAX ;
69+ case 32 :
70+ // We'll cheat by scaling the values to fit in a 16-bit range.
71+ minSampleValue = INT16_MIN ;
72+ maxSampleValue = INT16_MAX ;
73+ fakeBitsPerSample = 16 ;
74+ default :
75+ throw ' Unsupported bits per sample: $bitsPerSample ' ;
76+ }
5577
5678 var soundDataRawLength : Int = soundData .length ;
57- var soundDataSampleCount : Int = Std . int ( Math .ceil (soundDataRawLength / channels / (bitsPerSample == 16 ? 2 : 1 ) ));
58- var outputPointCount : Int = Std . int ( Math .ceil (soundDataSampleCount / samplesPerPoint ) );
79+ var soundDataSampleCount : Int = Math .ceil (soundDataRawLength / channels / (bitsPerSample / 8 ));
80+ var outputPointCount : Int = Math .ceil (soundDataSampleCount / samplesPerPoint );
5981
6082 // trace('Interpreting audio buffer:');
6183 // trace(' sampleRate: ${sampleRate}');
@@ -68,22 +90,19 @@ class WaveformDataParser
6890 // trace(' soundDataRawLength/4: ${soundDataRawLength / 4}');
6991 // trace(' outputPointCount: ${outputPointCount}');
7092
71- var minSampleValue : Int = bitsPerSample == 16 ? INT16_MIN : INT8_MIN ;
72- var maxSampleValue : Int = bitsPerSample == 16 ? INT16_MAX : INT8_MAX ;
73-
74- var outputData : Array <Int > = [];
93+ var outputData : Vector <Int > = new Vector <Int >(outputPointCount * 2 * channels );
7594
7695 var perfStart : Float = TimerUtil .start ();
7796
97+ // minChannel1, maxChannel1, minChannel2, maxChannel2, ...
98+ var values : Vector <Int > = new Vector <Int >(2 * channels );
99+
78100 for (pointIndex in 0 ... outputPointCount )
79101 {
80- // minChannel1, maxChannel1, minChannel2, maxChannel2, ...
81- var values : Array <Int > = [];
82-
83102 for (i in 0 ... channels )
84103 {
85- values . push ( bitsPerSample == 16 ? INT16_MAX : INT8_MAX ) ;
86- values . push ( bitsPerSample == 16 ? INT16_MIN : INT8_MIN ) ;
104+ values [ i * 2 ] = maxSampleValue ;
105+ values [ i * 2 + 1 ] = minSampleValue ;
87106 }
88107
89108 var rangeStart = pointIndex * samplesPerPoint ;
@@ -95,20 +114,31 @@ class WaveformDataParser
95114 for (channelIndex in 0 ... channels )
96115 {
97116 var sampleIndex : Int = sampleIndex * channels + channelIndex ;
98- var sampleValue = soundData [sampleIndex ];
117+ var sampleValue : Int = switch (bitsPerSample )
118+ {
119+ case 8 :
120+ final byte = soundData .get (sampleIndex );
121+ (byte & 0x80 ) != 0 ? (byte | ~ 0xFF ) : (byte & 0xFF );
122+ case 16 :
123+ final word = soundData .getUInt16 (sampleIndex * 2 );
124+ (word & 0x8000 ) != 0 ? (word | ~ 0xFFFF ) : (word & 0xFFFF );
125+ case 32 :
126+ Std .int (soundData .getFloat (sampleIndex * 4 ) * INT16_MAX );
127+ default :
128+ 0 ;
129+ }
99130
100131 if (sampleValue < values [channelIndex * 2 ]) values [(channelIndex * 2 )] = sampleValue ;
101132 if (sampleValue > values [channelIndex * 2 + 1 ]) values [(channelIndex * 2 ) + 1 ] = sampleValue ;
102133 }
103134 }
104135
105136 // We now have the min and max values for the range.
106- for (value in values )
107- outputData .push (value );
137+ Vector .blit (values , 0 , outputData , pointIndex * values .length , values .length );
108138 }
109139
110140 var outputDataLength : Int = Std .int (outputData .length / channels / 2 );
111- var result = new WaveformData (null , channels , sampleRate , samplesPerPoint , bitsPerSample , outputPointCount , outputData );
141+ var result = new WaveformData (null , channels , sampleRate , samplesPerPoint , fakeBitsPerSample , outputPointCount , outputData . toArray () );
112142
113143 trace (' [WAVEFORM] Interpreted audio buffer in ${TimerUtil .seconds (perfStart )}.' );
114144
0 commit comments