Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么我的正弦波频率扫描不正确?_Python_Python 3.x_Math_Wav_Waveform - Fatal编程技术网

Python 为什么我的正弦波频率扫描不正确?

Python 为什么我的正弦波频率扫描不正确?,python,python-3.x,math,wav,waveform,Python,Python 3.x,Math,Wav,Waveform,我正在尝试创建一个简单的WAV文件,它会发出变化的音调。但是,写入文件的波形与get\u sample返回的数据不对应 我预计音调会以对数方式变化,从A10(28160赫兹)开始,到A0(27.5赫兹)结束。每过一秒,音高应平稳下降一个八度 实际发生的事情很难解释。语气会发生变化,但会以意想不到的方式发生变化。让我的问题更奇怪的是,降低采样率会使问题恶化。在每秒48000个样本的情况下,音高迅速下降,然后再次上升,然后再次缓慢下降。在每秒3000个样本的情况下,也会发生类似的效果,但更极端、更混

我正在尝试创建一个简单的WAV文件,它会发出变化的音调。但是,写入文件的波形与
get\u sample
返回的数据不对应

我预计音调会以对数方式变化,从A10(28160赫兹)开始,到A0(27.5赫兹)结束。每过一秒,音高应平稳下降一个八度

实际发生的事情很难解释。语气会发生变化,但会以意想不到的方式发生变化。让我的问题更奇怪的是,降低采样率会使问题恶化。在每秒48000个样本的情况下,音高迅速下降,然后再次上升,然后再次缓慢下降。在每秒3000个样本的情况下,也会发生类似的效果,但更极端、更混乱。我做错了什么

from math import pi, sin
from sys import byteorder
import wave

def get_sample(time):
    frequency = a10 / 2.0 ** time
    # print('{:.15f} {:.15f} {:.15f}'.format(time, frequency, sin(pi2 * frequency * time)))
    return sin(pi2 * frequency * time)

pi2 = 2 * pi
a10 = 28160.0

NUMBER_OF_CHANNELS = 1
SAMPLE_RATE = 48000  # samples per second
SAMPLE_WIDTH = 3  # bytes
DURATION = 10  # seconds

MAX_SAMPLE_VALUE = 2 ** (SAMPLE_WIDTH * 8 - 1)

samples = bytearray()

for i in range(SAMPLE_RATE * DURATION):
    time = i / SAMPLE_RATE
    sample = round(get_sample(time) * MAX_SAMPLE_VALUE)

    if sample == MAX_SAMPLE_VALUE:
        sample -= 1

    samples.extend(sample.to_bytes(SAMPLE_WIDTH, byteorder, signed=True))

with wave.open('output.wav', 'wb') as output:
    output.setnchannels(NUMBER_OF_CHANNELS)
    output.setsampwidth(SAMPLE_WIDTH)
    output.setframerate(SAMPLE_RATE)
    output.setnframes(NUMBER_OF_CHANNELS * SAMPLE_RATE * DURATION)
    output.setcomptype('NONE', 'not compressed')

    output.writeframes(samples)

对于48000的采样率,28160Hz的频率过高

当采样率为3000Hz时,最大频率将小于1.5KHz

这与奈奎斯特采样率有关。简而言之,在给定采样率下,您可以采样的最大频率是采样率的1/2。实际上,它小于采样率的1/2

请参阅:

https://en.wikipedia.org/wiki/Nyquist_frequency
0

给定48000Hz的采样率,可以采样的最大频率为24000Hz。这个最大频率是理想化的,它会少得多

要捕获28160Hz频率,您需要大于56320Hz的采样率。比如说64000Hz,或者更好 96000Hz采样率

编辑:顺便问一下,为什么频率函数会上升到时间的幂次**

这会导致一些奇怪的锯齿效果

我认为应该是:

frequency = a10 * time

我懂了。。。你在做频率扫描。从而在每个采样时间调整频率

有两个问题

混叠 以fS速率采样的信号只有在不包含频率高于fS/2的分量时才能正确重构。当从样本(例如通过声卡)重建信号时,频率超出间隔[0,fS/2]的任何信号分量都会折叠到该间隔中

这被称为,可以通过在采样前对信号进行低通滤波或使采样率足够高来避免

在您的情况下,如果要对频率为28160 Hz的正弦波进行采样,采样率必须至少为56320 Hz

相位计算错误 相位是函数sin的参数。它对时间的导数是音高,这是我们听到的音调的音调

在这种情况下,如果我们将
frequency=a10/2.0**time
插入
pi2*frequency*time
,则相位为

pi2 * (a10 / 2.0 ** time) * time
或用符号表示:

φ=2π·A10·2−t·t

现在是

f=2π·A10·2−t·(1)− 自然对数 2·t)

而不是2π·A10·2−正如你所预料的那样

这是使用您的方法获得的实际频率扫描图(考虑到混叠,请注意曲线如何在0 Hz和24000 Hz的直线上反射),与您预期的结果对比:

这是相同的对数频率标度图,这是我们如何将频率视为音高的:

解决方案 通过进行以下更改,可以获得正确的结果:

  • 为采样率使用足够高的值

  • 不要直接从给定的时间计算样本,而是通过替换来保持一个相位值,该相位值以与预期频率成比例的速率递增(以2π缠绕,使其不会超出范围)


  • @mkrieger1,请参见编辑。一旦你成功地在28160 Hz的频率下产生纯音,你将无法听到:-)即使在将起始频率更改为A7(3520 Hz)并将持续时间更改为7秒后,我在保持48000 Hz的采样率时也会得到同样的效果。“反弹”似乎总是发生在1.44秒左右。您听到的“反弹”称为别名效应。Iit是当你的采样率对于给定的频率太慢时发生的情况。欠采样。48000 Hz的采样率如何不足以满足3520 Hz的音调?这是每个周期将近14个样本。这显然不太理想,但足以传达基调(尽管效果不佳)。如果我更改
    get_sample
    函数以发出恒定音调,则一切正常;场地很好/我对如何将扫描限制在起始频率和结束频率之间有点疑问?
    pi2 * (a10 / 2.0 ** time) * time
    
    def get_sample(time):
        frequency = a10 / 2.0 ** time
        return sin(pi2 * frequency * time)
    
    […]
    
    for i in range(SAMPLE_RATE * DURATION):
        time = i / SAMPLE_RATE
        sample = round(get_sample(time) * MAX_SAMPLE_VALUE)
    
    def get_frequency(time):
        frequency = a10 / 2.0 ** time
        return frequency
    
    […]
    
    phase = 0
    for i in range(SAMPLE_RATE * DURATION):
        time = i / SAMPLE_RATE
        f = get_frequency(time)
        phase = (phase + pi2 * f / SAMPLE_RATE) % pi2
        sample = round(sin(phase) * MAX_SAMPLE_VALUE)