将numpy int16音频数组转换为float32

9

我有一些原始的二进制int16数据,我正在使用以下代码将其转换为numpy数组:

audio = np.fromstring(raw_data, dtype=np.int16)

这些数据是音频数据。当我将数据转换为float32时,音频被失真了:

audio = audio.astype(np.float32, order='C')

我正在将音频保存到磁盘上,以便使用SoundFile听取它:

soundfile.write('out.wav', audio, sample_rate)

如果我直接将音频写入磁盘而不进行astype操作,则不会发生失真(即);

# no distortion
audio = np.fromstring(raw_data, dtype=np.int16)
soundfile.write('out.wav', audio, sample_rate)

# distortion
audio = np.fromstring(raw_data, dtype=np.int16)
audio = audio.astype(np.float32, order='C')
soundfile.write('out.wav', audio, sample_rate)

这里应该采用什么正确的方法来转换数据类型呢?
1个回答

16

根据惯例,浮点音频数据被归一化到[-1.0,1.0]范围内,您可以通过缩放来实现此操作:

audio = audio.astype(np.float32, order='C') / 32768.0

这可能会为您解决问题,但您需要确保soundfile.write编写的wav头表明float32。它可以根据数组的dtype自动执行此操作。


有符号整数范围从-32768到32767。在转换过程中,我们不需要平衡范围吗?或者我们可以假设0是真正的零,有符号整数表示仅仅是不均衡的(可以表示-32768但不能表示32767)? - fodma1
1
@fodma1。是的,0是中心。我从不写出一个-32768的文件,但在阅读时,我不喜欢假设别人没有这样做,因此使用/32768.0。这只有0.00026分贝的差异,不值得冒溢出的风险。 - jaket
1
这种方法有两个证明:1)FFmpeg sources->scale = 1. / (1 << (avctx->bits_per_coded_sample - 1)); 2)声音文件测试:numpy.array_equal(soundfile.read('file.wav', dtype='int16')[0] / 32768, soundfile.read('file.wav', dtype='float32')[0]) - bartolo-otrit
@jaket 如果我有一个音频文件的numpy数组,我想从中检测出单词怎么办? - Manvi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接