我想尽快将 wav 文件编码为 IMA ADPCM。
但是当我尝试编码我的文件(1:39 长度,44100 采样率,16 位,立体声)时,编码它需要大约 8 秒......
有没有办法让它更快?因为 8 秒对我来说看起来很慢......
另外,我尝试使用 Python 的 audioop 模块,但它仍然很慢而且我并不真的需要 audioop 的东西,所以我编写了自己的示例编码器/解码器。
我的代码:
steps = [
7, 8, 9, 10, 11, 12, 13, 14,
16, 17, 19, 21, 23, 25, 28, 31,
34, 37, 41, 45, 50, 55, 60, 66,
73, 80, 88, 97, 107, 118, 130, 143,
157, 173, 190, 209, 230, 253, 279, 307,
337, 371, 408, 449, 494, 544, 598, 658,
724, 796, 876, 963, 1060, 1166, 1282, 1411,
1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
32767
]
step_indices = [-1, -1, -1, -1, 2, 4, 6, 8]
def clamp(value, lower, upper):
return lower if (value < lower) else upper if (value > upper) else value
def decode_sample(sample, state: tuple) -> tuple:
predicted_sample = state[0] if (state) else 0
step_index = state[1] if (state) else 0
step = steps[step_index]
diff = step >> 3
if sample & 1: diff += step >> 2
if sample & 2: diff += step >> 1
if sample & 4: diff += step
if sample & 8: diff = -diff
predicted_sample = clamp(predicted_sample + diff, -32768, 32767)
step_index = clamp(step_index + step_indices[sample & 7], 0, 88)
return predicted_sample, step_index
def encode_sample(sample, state: tuple) -> tuple:
predicted_sample = state[0] if (state) else 0
step_index = state[1] if (state) else 0
step = steps[step_index]
sample_diff = sample - predicted_sample
encoded_sample = 8 if (sample_diff < 0) else 0
if encoded_sample:
sample_diff = -sample_diff
diff = step >> 3
if sample_diff >= step:
encoded_sample |= 4
sample_diff -= step
diff += step
step >>= 1
if sample_diff >= step:
encoded_sample |= 2
sample_diff -= step
diff += step
step >>= 1
if sample_diff >= step:
encoded_sample |= 1
diff += step
if encoded_sample & 8:
diff = -diff
predicted_sample = clamp(predicted_sample + diff, -32768, 32767)
step_index = clamp(step_index + step_indices[encoded_sample & 7], 0, 88)
return encoded_sample, (predicted_sample, step_index)
import wave
def encode_stereo():
with wave.open('mario.wav', 'r') as wav_file:
raw_samples = wav_file.readframes(wav_file.getnframes())
samples = memoryview(raw_samples).cast('h')
left_channel, right_channel = samples[::2], samples[1::2]
encoded = bytearray()
left_state = None
right_state = None
for i in range(len(left_channel)):
left_sample, left_state = encode_sample(left_channel[i], left_state)
right_sample, right_state = encode_sample(right_channel[i], right_state)
encoded.append(right_sample << 4 | left_sample)
with open('mario.adpcm', 'wb') as adpcm_file:
adpcm_file.write(encoded)
encode_stereo()