[英]How to play sound samples continuously in pygame?
我想播放一个连续的正弦波(暂时),它会根据鼠标指针 position(暂时)改变其频率(暂时)。 因此,我生成并播放一帧长度的波(下面代码中的 1/2 秒)。 产生的声音在声音中有很小的间隙,足以非常显着。 增加单个声音的持续时间没有帮助,改变缓冲区大小没有帮助,使用 dtick 而不是 dt 没有帮助。
有没有办法以这种方式实现连续的声音? 还是有什么其他方式?
谢谢
版本:Python 3.9.3、pygame 2.0.1
最小(仍然很长)代码:
import numpy as np
import pygame
from pygame import Color
from pygame.locals import KEYDOWN, KMOD_CTRL, QUIT, K_q
fade_out = np.linspace(1, 0, 100)
fade_in = np.linspace(0, 1, 100)
bits = 16
sample_rate = 44100
max_sample = 2 ** (bits - 1) - 1
def gen_sound(duration, freq):
n_samples = int(duration / 1000 * sample_rate)
buf = np.zeros((n_samples, 2), dtype=np.int16)
buf[:, 0] = (
0.25
* max_sample
* np.sin(2 * np.pi * freq[0] * np.arange(n_samples) / sample_rate)
)
buf[:, 1] = (
0.25
* max_sample
* np.sin(2 * np.pi * freq[1] * np.arange(n_samples) / sample_rate)
)
buf[-100:, 0] = (buf[-100:, 0] * fade_out).astype(int)
buf[-100:, 1] = (buf[-100:, 1] * fade_out).astype(int)
buf[:100, 0] = (buf[:100, 0] * fade_in).astype(int)
buf[:100, 1] = (buf[:100, 1] * fade_in).astype(int)
return pygame.sndarray.make_sound(buf)
def main(argv: list = None):
# initialize sound
pygame.mixer.pre_init(sample_rate, -bits, 2, 512)
# initialize pygame
pygame.init()
size = (1000, 800)
surf = pygame.display.set_mode(size)
surf.fill(Color("black"))
clock = pygame.time.Clock()
# frames per second and duration of a frame in ms
FPS = 2
dt = 1000 / FPS
dtick = 1000 / FPS
# position of the mouse pointer, None means outside of the window
mpos = None
# event loop
while True:
events = pygame.event.get()
for e in events:
if e.type == QUIT:
return
# shutdown with C-q
if e.type == KEYDOWN:
if e.mod & KMOD_CTRL and e.key == K_q:
return
if pygame.mouse.get_focused():
mpos = pygame.mouse.get_pos()
else:
mpos = None
freq = mpos if mpos else (440, 440)
sound = gen_sound(dt, freq)
sound.play(loops=0, fade_ms=0)
pygame.display.update()
dtick = clock.tick(FPS)
if __name__ == "__main__":
main()
您可以在播放时直接修改Sound
数据,无需每帧调用.play()
。
def gen_sound(buf, freq):
buf[:, 0] = (
0.25
* max_sample
* np.sin(2 * np.pi * freq[0] * np.arange(n_samples) / sample_rate)
)
buf[:, 1] = (
0.25
* max_sample
* np.sin(2 * np.pi * freq[1] * np.arange(n_samples) / sample_rate)
)
主要是:
def main(argv: list = None):
# ...
clock = pygame.time.Clock()
buf = np.zeros((n_samples, 2), dtype=np.int16)
sound = pygame.sndarray.make_sound(buf)
buf = pygame.sndarray.samples(sound) # This is required because make_sound copies the array, but we want a reference
gen_sound(buf, (440, 440))
sound.play(loops=-1, fade_ms=0)
# ...
# event loop
while True:
# ...
freq = mpos if mpos else (440, 440)
gen_sound(buf, freq)
pygame.display.update()
dtick = clock.tick(FPS)
请注意,这将遇到此处描述和解决的问题,例如,正弦波转换不平滑。 但这超出了这个问题的 scope 和我的知识。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.