Skip to content

Commit 4fda378

Browse files
NotHyper-474Hundrec
authored andcommitted
WaveformDataParser: 32bit float audio support
1 parent 146a6cd commit 4fda378

File tree

2 files changed

+31
-22
lines changed

2 files changed

+31
-22
lines changed

source/funkin/audio/waveform/WaveformData.hx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,12 @@ class WaveformData
7272
return (channelData == null) ? buildChannelData()[index] : channelData[index];
7373
}
7474

75-
public function get(index:Int):Int
75+
public inline function get(index:Int):Int
7676
{
7777
return data[index] ?? 0;
7878
}
7979

80-
public function set(index:Int, value:Int)
80+
public inline function set(index:Int, value:Int)
8181
{
8282
data[index] = value;
8383
}
@@ -88,8 +88,9 @@ class WaveformData
8888
*/
8989
public function maxSampleValue():Int
9090
{
91+
// TODO: Should this still be cached?
9192
if (_maxSampleValue != 0) return _maxSampleValue;
92-
return _maxSampleValue = Std.int(Math.pow(2, bits));
93+
return _maxSampleValue = 1 << bits;
9394
}
9495

9596
/**

source/funkin/audio/waveform/WaveformDataParser.hx

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,16 @@ class WaveformDataParser
4848
var samplesPerPoint:Int = 256; // I don't think we need to configure this.
4949

5050
// TODO: Make this work better on HTML5.
51-
var soundData:lime.utils.Int16Array = cast soundBuffer.data;
52-
53-
var soundDataSampleCount:Int = Std.int(Math.ceil(soundData.length / channels / (bitsPerSample == 16 ? 2 : 1)));
54-
var outputPointCount:Int = Std.int(Math.ceil(soundDataSampleCount / samplesPerPoint));
51+
var soundData:haxe.io.Bytes = soundBuffer.data.toBytes();
52+
var soundDataSampleCount:Int = Math.ceil(soundData.length / channels / (bitsPerSample / 8));
53+
var outputPointCount:Int = Math.ceil(soundDataSampleCount / samplesPerPoint);
5554

5655
// Pre-allocate Vector with exact final size for better performance and memory efficiency
5756
var outputDataLength:Int = outputPointCount * channels * 2;
5857
var outputData = new haxe.ds.Vector<Int>(outputDataLength);
5958

60-
// Reusable min/max tracking arrays to avoid allocation in the loop
61-
var minValues = new haxe.ds.Vector<Int>(channels);
62-
var maxValues = new haxe.ds.Vector<Int>(channels);
59+
// Reusable min/max tracking array to avoid allocation in the loop
60+
var values = new haxe.ds.Vector<Int>(channels * 2);
6361

6462
for (pointIndex in 0...outputPointCount)
6563
{
@@ -69,31 +67,41 @@ class WaveformDataParser
6967
// Reset min/max values for this range
7068
for (i in 0...channels)
7169
{
72-
minValues[i] = bitsPerSample == 16 ? INT16_MAX : INT8_MAX;
73-
maxValues[i] = bitsPerSample == 16 ? INT16_MIN : INT8_MIN;
70+
values[i * 2] = bitsPerSample == 8 ? INT8_MAX : INT16_MAX;
71+
values[i * 2 + 1] = bitsPerSample == 8 ? INT8_MIN : INT16_MIN;
7472
}
7573

7674
// Process all samples in this range
7775
for (sampleIndex in rangeStart...rangeEnd)
7876
{
7977
for (channelIndex in 0...channels)
8078
{
81-
var sampleValue:Int = soundData[sampleIndex * channels + channelIndex];
82-
83-
if (sampleValue < minValues[channelIndex]) minValues[channelIndex] = sampleValue;
84-
if (sampleValue > maxValues[channelIndex]) maxValues[channelIndex] = sampleValue;
79+
var sampleIndex:Int = sampleIndex * channels + channelIndex;
80+
var sampleValue:Int = switch (bitsPerSample)
81+
{
82+
case 8:
83+
final byte = soundData.get(sampleIndex);
84+
(byte & 0x80) != 0 ? (byte | ~0xFF) : (byte & 0xFF);
85+
case 16:
86+
final word = soundData.getUInt16(sampleIndex * 2);
87+
(word & 0x8000) != 0 ? (word | ~0xFFFF) : (word & 0xFFFF);
88+
case 32:
89+
Std.int(soundData.getFloat(sampleIndex * 4) * INT16_MAX);
90+
default:
91+
0;
92+
}
93+
94+
if (sampleValue < values[channelIndex * 2]) values[channelIndex * 2] = sampleValue;
95+
if (sampleValue > values[channelIndex * 2 + 1]) values[channelIndex * 2 + 1] = sampleValue;
8596
}
8697
}
8798

8899
// Write directly to final positions in output Vector
89-
var baseIndex:Int = pointIndex * channels * 2;
90-
for (channelIndex in 0...channels)
91-
{
92-
outputData[baseIndex + channelIndex * 2] = minValues[channelIndex];
93-
outputData[baseIndex + channelIndex * 2 + 1] = maxValues[channelIndex];
94-
}
100+
var baseIndex:Int = pointIndex * values.length;
101+
haxe.ds.Vector.blit(values, 0, outputData, baseIndex, values.length);
95102
}
96103

104+
if (bitsPerSample == 32) bitsPerSample = 16;
97105
var result = new WaveformData(null, channels, soundBuffer.sampleRate, samplesPerPoint, bitsPerSample, outputPointCount, outputData.toArray());
98106

99107
return result;

0 commit comments

Comments
 (0)