如何解决如何在pygame中连续播放声音样本?
我想播放一个连续的正弦波(暂时),它根据鼠标指针位置(暂时)改变其频率(暂时)。因此,我生成并播放一帧长度的波浪(以下代码中为 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,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)
请注意,这会遇到所描述和解决的问题 here,例如正弦波转换不平滑。但这超出了这个问题和我的知识范围。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。