【发布时间】:2021-04-16 18:41:09
【问题描述】:
我想播放一个连续的正弦波(暂时),它会根据鼠标指针的位置(暂时)改变其频率(暂时)。因此,我生成并播放一帧长度的波(下面代码中的 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()
【问题讨论】:
-
您可能希望对生成的波使用缓存,这样如果频率和持续时间没有改变,您就不会重新构建波。此外,如果声音在后台播放,您希望在声音停止时更新它(除非播放器中内置了声音队列,这很可能是。)而不是程序的每个循环。