简单的Pygame音频

2024-05-19 03:02:47 发布

您现在位置:Python中文网/ 问答频道 /正文

如何使用Pygame的音频创建一个440赫兹的声音,使其永远流畅地播放?我想这应该很简单,但我不想用任何愚蠢的文件来完成任务。最后的目的是在我在另一个问题中问到的一个键被按住的时候弹奏一个音符。任何帮助都将非常感谢,因为我浪费了大量时间试图找到答案。


Tags: 文件答案目的声音时间浪费音频pygame
2条回答

在得到太多的“ValueError:Array depth must match number of mixer channels”和其他类似错误之后,我发现了这个工作示例http://www.mail-archive.com/pygame-users@seul.org/msg16140.html。它正确地生成了一个多维16位整数数组,该数组与立体声混频器一起工作。下面是一个最小的工作示例,主要是从上一个链接中提取必要的pygame位。在Python2.7.2中使用pygame.ver“1.9.1release”进行测试。

本例将在立体声设置中从一个扬声器播放440赫兹的音调,从另一个扬声器播放550赫兹的音调。在对duration进行了一些分析之后,我发现如果将“duration”变量设置为整数以外的任何值,声音循环中将弹出可听见的咔哒声。

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()

什么样的440赫兹的声音?在“440赫兹”有许多类型的波:正弦、锯子、正方形等。你可以用长笛吹a,这也可以算数。

假设您需要正弦波,那么看起来您可以使用pygame.sndarray.samples生成声音对象。(我还没有测试过)您可以使用以下命令创建示例:

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

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

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

samples设为整数个波长,它应该循环。

相关问题 更多 >

    热门问题