Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/355.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_Audio_Numpy_Pygame - Fatal编程技术网

Python方波函数-这里发生了什么?

Python方波函数-这里发生了什么?,python,audio,numpy,pygame,Python,Audio,Numpy,Pygame,我有一个在python中创建方波的函数,我似乎无法从中获得声音,但当我更改此函数时: value = state * volume s.append( [value, value] ) 为此: value = state * volume s.append( [0, value] ) 我得到了一个声音,但它的频率远高于我打算产生的130.81频率。以下是完整的代码: def SquareWave(freq=1000, volume=10000, length=1): num_ste

我有一个在python中创建方波的函数,我似乎无法从中获得声音,但当我更改此函数时:

value = state * volume
s.append( [value, value] )
为此:

value = state * volume
s.append( [0, value] )
我得到了一个声音,但它的频率远高于我打算产生的130.81频率。以下是完整的代码:

def SquareWave(freq=1000, volume=10000, length=1):

    num_steps = length * SAMPLE_RATE
    s = []

    length_of_plateau = SAMPLE_RATE / (2*freq)

    counter = 0
    state = 1

    for n in range(num_steps):

        value = state * volume
        s.append( [value, value] )

        counter += 1

        if counter == length_of_plateau:
            counter = 0
            state *= -1

    return numpy.array(s)

def MakeSound(arr):
    return pygame.sndarray.make_sound(arr)

def MakeSquareWave(freq=1000):
    return MakeSound(SquareWave(freq))
调用这些函数的代码块如下所示:

elif current_type == SQUARE_WAVE_TYPE:

            if event.type == KEYDOWN:

                #lower notes DOWN

                if event.key == K_z:
                    print current_type, 130.81
                    #current_played['z'] = MakeSineWave(80.81)
                    current_played['z'] = MakeSquareWave(130.81)
                    current_played['z'].play(-1)

                elif event.key == K_c:
                    print current_type, 180.81
                    #current_played['c'] = MakeSineWave(80.81)
                    current_played['c'] = MakeSquareWave(180.81)
                    current_played['c'].play(-1)

有人知道为什么会这样吗?这个方波函数真的正确吗?

问题的原因很可能是因为没有正确考虑浮点值

拿这个比较来说:

if counter == length_of_plateau:
这将比较整数
计数器
和浮点值
平台的长度

高原的长度\u
来自此作业:

length_of_plateau = SAMPLE_RATE / (2*freq)
频率为130.81,采样率为44100(我在这里猜测,您没有公布采样率的值),您得到:

length_of_plateau = 168.565094412
因此,整数永远不会等于该值

相反,我要做的是:

state = 1
next_plateau_end = length_of_plateau

counter = 0
for n in range(num_steps):
    value = state * volume
    s.append( [value, value] )

    if counter >= next_plateau_end:
        counter -= length_of_plateau
        state *= -1
    counter += 1

我们不是每次将计数器重置为0,而是减去平台的长度(这是一个浮点值)。这意味着原始代码中引入的舍入误差将随着时间的推移而平滑。

计数器的值与循环内平台的长度相比是多少,你能调试代码并找到这两个值的具体例子吗?用
打印值
看看你有什么值。我问的原因是我怀疑
plateau
的长度\u是一个浮点值,而
counter
是一个整数,因此,当频率为130.81时,它们在任何一点上变得相等的几率是零,或者也许是千载难逢更为正确。在任何情况下,请验证这些变量的值,看看它是否与我在这里所说的相符。@Lasse V.Karlsen你是对的,它必须是(例如)在
length\u of_plateau=int(SAMPLE\u RATE/(2*freq))
中的
int()
。我怀疑代码应该检查
计数器
是否大于某个值,该值最初设置为压板的长度,然后每次都将该值增加压板的长度。通过这种方式,您可以逐渐消除舍入误差。如果你简单地将其转换为int,你就没有获得130.81的频率(随着时间的推移),而是获得了一个永久的舍入误差。我不完全确定添加
[value,value]
的意义是什么,如果这将两个值添加到输出中,你就得不到正确的频率,但你是这里正确的最佳判断者。我100%确信浮点问题是导致程序生成错误波形的原因。答案很好,您还可以编写一个函数,在给定采样率下计算误差。我将对此进行一个更改,而不是
next\u plateau\u end+=length\u of\u plateau
,我会做
n-=高原的长度
。这样做的原因是,如果将其移植到C,则
n
将是有限整数类型。如果该有限整数类型为16位或32位,则按照当前编写的那样,
n
完全有可能在合理的时间内溢出(在44100 Hz时,2^31个样本~=13.5小时)。溢出时,一个循环将被扭曲。并不是说我犯过这个错误,哦,不。虽然我不会改变
n
,但我明白你的意思,所以让我编辑一下答案。最好是将平台的长度_四舍五入到最接近的整数,而不是试图随时间“平滑”错误。想想fft会是什么样子。