简单的Pygame音频频率

时间:2011-10-19 03:39:59

标签: python audio pygame

如何使用Pygame音频创建一个能够流畅播放的440 Hz声音?我认为这应该很容易,但我不想使用任何愚蠢的文件来完成任务。这样做的最终目的是在我按照另一个问题提出的要求按下按键时播放音符。任何帮助都会非常感激,因为我浪费了大量的时间来寻找答案。

2 个答案:

答案 0 :(得分:7)

在获得完全过多的“ValueError:数组深度必须与混音器通道数匹配”以及其他类似错误后,我发现了这个工作示例http://www.mail-archive.com/pygame-users@seul.org/msg16140.html。它可以正确生成一个多维16位整数数组,可与立体声混音器配合使用。下面的最小工作示例,大部分从上一个链接中提取所需的pygame位。使用pygame.ver'1.9.1release'在Python 2.7.2中测试。

此示例将在立体声设置中播放一个扬声器的440 Hz音调和另一个扬声器的550 Hz音调。经过一段时间的游戏,我发现如果你将“持续时间”变量设置为整数以外的任何值,声音循环中会弹出声音点击。

import pygame
from pygame.locals import *

import math
import numpy

size = (1366, 720)

bits = 16
#the number of channels specified here is NOT 
#the channels talked about here http://www.pygame.org/docs/ref/mixer.html#pygame.mixer.get_num_channels

pygame.mixer.pre_init(44100, -bits, 2)
pygame.init()
_display_surf = pygame.display.set_mode(size, pygame.HWSURFACE | pygame.DOUBLEBUF)


duration = 1.0          # in seconds
#freqency for the left speaker
frequency_l = 440
#frequency for the right speaker
frequency_r = 550

#this sounds totally different coming out of a laptop versus coming out of headphones

sample_rate = 44100

n_samples = int(round(duration*sample_rate))

#setup our numpy array to handle 16 bit ints, which is what we set our mixer to expect with "bits" up above
buf = numpy.zeros((n_samples, 2), dtype = numpy.int16)
max_sample = 2**(bits - 1) - 1

for s in range(n_samples):
    t = float(s)/sample_rate    # time in seconds

    #grab the x-coordinate of the sine wave at a given time, while constraining the sample to what our mixer is set to with "bits"
    buf[s][0] = int(round(max_sample*math.sin(2*math.pi*frequency_l*t)))        # left
    buf[s][1] = int(round(max_sample*0.5*math.sin(2*math.pi*frequency_r*t)))    # right

sound = pygame.sndarray.make_sound(buf)
#play once, then loop forever
sound.play(loops = -1)


#This will keep the sound playing forever, the quit event handling allows the pygame window to close without crashing
_running = True
while _running:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            _running = False
            break

pygame.quit()

答案 1 :(得分:3)

什么样的440赫兹声音? “440赫兹”有很多类型的波浪:正弦,锯齿,方形等。你可以用长笛演奏A,这也可能算得上。

假设您想要一个正弦波,看起来您可以使用pygame.sndarray.samples生成一个Sound对象。 (我没有对此进行测试)您可以使用以下命令创建示例:

samples = [math.sin(2.0 * math.pi * frequency * t / sample_rate) for t in xrange(0, duration_in_samples)]

这是希望基本的正弦波。 frequency是所需频率,单位为Hz。 sample_rate是生成的音频中的采样数/秒:44100 Hz是典型值。 duration_in_samples是音频的长度。 (5 * 44100 == 5秒,如果您的音频采样率为44100 Hz。)

在传递给samples之前,您可能需要将numpy.array转换为pygame.sndarray.samples。文档表明音频应与pygame.mixer.get_init返回的格式匹配,因此请适当调整samples,但这是基本想法。 (mixer.get_init会告诉您上面的sample_rate变量,以及是否需要考虑立体声,以及是否需要调整波的幅度或移动它。)

samples长波整数,并且应该循环。