Skip to content

Commit 96d85a7

Browse files
authored
Merge pull request #13 from L4Vo5/24-and-32-bit-support
Add support for 24 and 32 bit .wav's
2 parents 2fd9821 + dfd3957 commit 96d85a7

1 file changed

Lines changed: 53 additions & 7 deletions

File tree

GDScriptAudioImport.gd

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,15 @@ func loadfile(filepath):
5656
return AudioStreamSample.new()
5757

5858
var bytes = file.get_buffer(file.get_len())
59-
6059
# if File is wav
6160
if filepath.ends_with(".wav"):
62-
6361
var newstream = AudioStreamSample.new()
6462

6563
#---------------------------
6664
#parrrrseeeeee!!! :D
67-
65+
66+
var bits_per_sample = 0
67+
6868
for i in range(0, 100):
6969
var those4bytes = str(char(bytes[i])+char(bytes[i+1])+char(bytes[i+2])+char(bytes[i+3]))
7070

@@ -90,6 +90,9 @@ func loadfile(filepath):
9090
if format_code == 0: format_name = "8_BITS"
9191
elif format_code == 1: format_name = "16_BITS"
9292
elif format_code == 2: format_name = "IMA_ADPCM"
93+
else:
94+
format_name = "UNKNOWN (trying to interpret as 16_BITS)"
95+
format_code = 1
9396
print ("Format: " + str(format_code) + " " + format_name)
9497
#assign format to our AudioStreamSample
9598
newstream.format = format_code
@@ -114,20 +117,25 @@ func loadfile(filepath):
114117
var bits_sample_channel = bytes[fsc0+12] + (bytes[fsc0+13] << 8)
115118
print ("BitsPerSample * Channel / 8: " + str(bits_sample_channel))
116119

117-
#aaaand bits per sample/bitrate [Bytes 14-15] - TODO: Handle different bitrates
118-
var bits_per_sample = bytes[fsc0+14] + (bytes[fsc0+15] << 8)
120+
#aaaand bits per sample/bitrate [Bytes 14-15]
121+
bits_per_sample = bytes[fsc0+14] + (bytes[fsc0+15] << 8)
119122
print ("Bits per sample: " + str(bits_per_sample))
120123

121-
122124
if those4bytes == "data":
125+
assert(bits_per_sample != 0)
126+
123127
var audio_data_size = bytes[i+4] + (bytes[i+5] << 8) + (bytes[i+6] << 16) + (bytes[i+7] << 24)
124128
print ("Audio data/stream size is " + str(audio_data_size) + " bytes")
125129

126130
var data_entry_point = (i+8)
127131
print ("Audio data starts at byte " + str(data_entry_point))
128132

129-
newstream.data = bytes.subarray(data_entry_point, data_entry_point+audio_data_size-1)
133+
var data = bytes.subarray(data_entry_point, data_entry_point+audio_data_size-1)
130134

135+
if bits_per_sample in [24, 32]:
136+
newstream.data = convert_to_16bit(data, bits_per_sample)
137+
else:
138+
newstream.data = data
131139
# end of parsing
132140
#---------------------------
133141

@@ -155,6 +163,44 @@ func loadfile(filepath):
155163
print ("ERROR: Wrong filetype or format")
156164
file.close()
157165

166+
# Converts .wav data from 24 or 32 bits to 16
167+
#
168+
# These conversions are SLOW in GDScript
169+
# on my one test song, 32 -> 16 was around 3x slower than 24 -> 16
170+
#
171+
# I couldn't get threads to help very much
172+
# They made the 24bit case about 2x faster in my test file
173+
# And the 32bit case abour 50% slower
174+
# I don't wanna risk it always being slower on other files
175+
# And really, the solution would be to handle it in a low-level language
176+
func convert_to_16bit(data: PoolByteArray, from: int) -> PoolByteArray:
177+
print("converting to 16-bit from %d" % from)
178+
var time = OS.get_ticks_msec()
179+
# 24 bit .wav's are typically stored as integers
180+
# so we just grab the 2 most significant bytes and ignore the other
181+
if from == 24:
182+
var j = 0
183+
for i in range(0, data.size(), 3):
184+
data[j] = data[i+1]
185+
data[j+1] = data[i+2]
186+
j += 2
187+
data.resize(data.size() * 2 / 3)
188+
# 32 bit .wav's are typically stored as floating point numbers
189+
# so we need to grab all 4 bytes and interpret them as a float first
190+
if from == 32:
191+
var spb := StreamPeerBuffer.new()
192+
var single_float: float
193+
var value: int
194+
for i in range(0, data.size(), 4):
195+
spb.data_array = data.subarray(i, i+3)
196+
single_float = spb.get_float()
197+
value = single_float * 32768
198+
data[i/2] = value
199+
data[i/2+1] = value >> 8
200+
data.resize(data.size() / 2)
201+
print("Took %f seconds for slow conversion" % ((OS.get_ticks_msec() - time) / 1000.0))
202+
return data
203+
158204

159205
# ---------- REFERENCE ---------------
160206
# note: typical values doesn't always match

0 commit comments

Comments
 (0)