Python 为什么我的输出会忽略其他样本,为什么频率是预期值的一半?
我在玩弄,我遇到了两个我无法解决的问题Python 为什么我的输出会忽略其他样本,为什么频率是预期值的一半?,python,python-3.x,wav,waveform,Python,Python 3.x,Wav,Waveform,我在玩弄,我遇到了两个我无法解决的问题 每隔一个样本的振幅为0。理想的行为是有一个连续的正弦波 产生的频率似乎是期望频率的一半。从数学上看,我不明白为什么。我知道如何修理它。我就是搞不懂原因。在我看来,将频率乘以2π,而不是4π,对我来说是有意义的 from functools import partial, wraps from math import pi, sin import struct import wave class Wave: def __init__(self, f
from functools import partial, wraps
from math import pi, sin
import struct
import wave
class Wave:
def __init__(self, frequency, amplitude=1.0, phase_shift=0.0, vertical_translation=0.0):
self.frequency = frequency
self.amplitude = amplitude
self.phase_shift = phase_shift
self.vertical_translation = vertical_translation
def __call__(self, time):
try:
amplitude = self.amplitude(time)
except TypeError:
amplitude = self.amplitude
try:
frequency = self.frequency(time)
except TypeError:
frequency = self.frequency
try:
phase_shift = self.phase_shift(time)
except TypeError:
phase_shift = self.phase_shift
try:
vertical_translation = self.vertical_translation(time)
except TypeError:
vertical_translation = self.vertical_translation
return amplitude * sin(2 * pi * frequency * time + phase_shift) + vertical_translation
if __name__ == '__main__':
SAMPLE_RATE = 96000
NUMBER_OF_CHANNELS = 1
SAMPLE_WIDTH = 4
MAX_AMPLITUDE = 2 ** (8 * SAMPLE_WIDTH - 1)
with wave.open('output.wav', 'w') as output:
output.setsampwidth(SAMPLE_WIDTH)
output.setnchannels(NUMBER_OF_CHANNELS)
output.setframerate(SAMPLE_RATE)
output.setcomptype('NONE', 'Uncompressed')
a440 = Wave(440)
for time in range(SAMPLE_RATE // a440.frequency):
sample = MAX_AMPLITUDE * a440(time / SAMPLE_RATE)
output.writeframes(struct.pack('l', round(sample)))
如果您有任何见解,我将不胜感激。我无法复制您的问题。运行代码后,我得到了一个理想的正弦波,其长度为预期长度(1/440Hz)≈ 0.0023s)在Audacity中检查.wav时:
我有一点要告诉你,你不能简单地把从
sin*MAX_振幅
中得到的东西取整。你必须向负无穷大方向截断。这是因为(比如)8位样本从-128到127,而不是从-128到128。有趣。当我将格式从'l'
更改为'd'
时,我将获得您的输出。显然,我的机器上的长整数是8字节,而您的机器必须使用4字节宽的长整数。好吧,开枪。平台无关代码就这么多了。@TylerCrompton没有意义,d
是双重格式。*耸耸肩*我可能在尝试'I'
时看到了结果。无论如何,我通过将表单更改为'{}s'.format(SAMPLE\u WIDTH)
并将要打包的值更改为SAMPLE.to\u bytes(SAMPLE\u WIDTH,'little',signed=True)
来修复它。此外,我不能仅使用地板
进行取整,因为样本可能完全等于最大振幅
。这是因为当使用二的补码时,可能有奇数个负值和偶数个正值。因此,我使用了floor
并将所有值剪切到允许范围之外。谢谢