Python 所生成的声音不会像应该的那样保存到文件中
我以pyaudio中预期的频率440hz生成声波,但即使我使用相同的样本阵列来保存wav文件,它也不会保存相同的声音,我也不知道为什么 代码如下:Python 所生成的声音不会像应该的那样保存到文件中,python,audio,pyaudio,wave,Python,Audio,Pyaudio,Wave,我以pyaudio中预期的频率440hz生成声波,但即使我使用相同的样本阵列来保存wav文件,它也不会保存相同的声音,我也不知道为什么 代码如下: import wave import numpy as np import pyaudio p = pyaudio.PyAudio() volume = 0.5 # range [0.0, 1.0] fs = 44100 # sampling rate, Hz, must be integer duration = 2.0 # in sec
import wave
import numpy as np
import pyaudio
p = pyaudio.PyAudio()
volume = 0.5 # range [0.0, 1.0]
fs = 44100 # sampling rate, Hz, must be integer
duration = 2.0 # in seconds, may be float
f = 440.0 # sine frequency, Hz, may be float
channels = 1
# open stream (2)
stream = p.open(format=pyaudio.paFloat32,
channels=channels,
rate=fs,
output=True)
def get_value(i):
return np.sin(f * np.pi * float(i) / float(fs))
samples = np.array([get_value(a) for a in range(0, fs)]).astype(np.float32)
for i in range(0, int(duration)):
stream.write(samples, fs)
wf = wave.open("test.wav", 'wb')
wf.setnchannels(channels)
wf.setsampwidth(3)
wf.setframerate(fs)
wf.setnframes(int(fs * duration))
wf.writeframes(samples)
wf.close()
# stop stream (4)
stream.stop_stream()
stream.close()
# close PyAudio (5)
p.terminate()
我认为主要问题是您使用的是
float32
数据类型,而wave
模块不支持该数据类型。
您可以使用int16
或int32
或手动转换的24位整数。
由于您使用的是wf.setsampwidth(3)
,我假设您想要使用24位数据
我写了一个(包括如何处理24位数据)和一个。
你也可能对我的教程感兴趣
由于您已经在使用NumPy,我建议您使用一个支持NumPy数组的库,该库支持开箱即用,并为您完成所有转换。
我个人倾向于使用这个模块,但我有很大的偏见。
对于播放,我还建议使用支持NumPy的库。这里我的建议是模块,但我在这里也很有偏见
如果您想遵循我的建议,您的代码可能会变成这样(包括处理volume
并修复窦房结参数中缺少的2
):
更新: 如果你想继续使用PyAudio,那很好。 但您必须手动将浮点数组(值从
-1.0
到1.0
)转换为适当范围内的整数,具体取决于要使用的数据类型。
我上面提到的第一个链接包含一个文件,该文件有一个函数float2pcm()
来实现这一点
以下是该函数的缩写版本:
def float2pcm(sig, dtype='int16'):
i = np.iinfo(dtype)
abs_max = 2 ** (i.bits - 1)
offset = i.min + abs_max
return (sig * abs_max + offset).clip(i.min, i.max).astype(dtype)
我认为主要问题是您使用的是
float32
数据类型,而wave
模块不支持该数据类型。
您可以使用int16
或int32
或手动转换的24位整数。
由于您使用的是wf.setsampwidth(3)
,我假设您想要使用24位数据
我写了一个(包括如何处理24位数据)和一个。
你也可能对我的教程感兴趣
由于您已经在使用NumPy,我建议您使用一个支持NumPy数组的库,该库支持开箱即用,并为您完成所有转换。
我个人倾向于使用这个模块,但我有很大的偏见。
对于播放,我还建议使用支持NumPy的库。这里我的建议是模块,但我在这里也很有偏见
如果您想遵循我的建议,您的代码可能会变成这样(包括处理volume
并修复窦房结参数中缺少的2
):
更新: 如果你想继续使用PyAudio,那很好。 但您必须手动将浮点数组(值从
-1.0
到1.0
)转换为适当范围内的整数,具体取决于要使用的数据类型。
我上面提到的第一个链接包含一个文件,该文件有一个函数float2pcm()
来实现这一点
以下是该函数的缩写版本:
def float2pcm(sig, dtype='int16'):
i = np.iinfo(dtype)
abs_max = 2 ** (i.bits - 1)
offset = i.min + abs_max
return (sig * abs_max + offset).clip(i.min, i.max).astype(dtype)
我不想使用sounddevice,因为它在windows 10上不工作,我尝试更改为int32,但当我将:aType(np.float32)更改为aType(np.int32)时,我没有听到声音,我设法使它工作,但是现在我听到了声音的咔嗒声,我怀疑咔嗒声来自于这样一个事实:你正在创建一个1秒的信号,然后播放两次?用我修改过的代码一次生成整个两秒钟的信号怎么样?另外,不要忘了
2
的因素,否则你的音调会太低。我在我的mac上测试了你的代码,它更好,不处理整数而不是浮点数也很好。。。太糟糕了,它不能在windows上工作,我想做一些能在3大OSs上工作的东西,sounddevice
模块通常能在所有3大OSs上工作,包括windows,特别是windows 10。不过,某些系统上似乎存在问题:。我不想使用sounddevice,因为它在windows 10上不工作,我尝试更改为int32,但当我将astype(np.float32)更改为astype(np.int32)时,我没有听到声音,我设法使它工作,但是现在我听到了声音的咔嗒声,我怀疑咔嗒声来自于这样一个事实:你正在创建一个1秒的信号,然后播放两次?用我修改过的代码一次生成整个两秒钟的信号怎么样?另外,不要忘了2
的因素,否则你的音调会太低。我在我的mac上测试了你的代码,它更好,不处理整数而不是浮点数也很好。。。太糟糕了,它不能在windows上工作,我想做一些能在3大OSs上工作的东西,sounddevice
模块通常能在所有3大OSs上工作,包括windows,特别是windows 10。不过,某些系统似乎存在问题:。