我找到了播放声音的代码:
from array import array # need a newline between normal text and code, edited to make it so
from time import sleep
import pygame
from pygame.mixer import Sound, get_init, pre_init
class Note(Sound):
def __init__(self, frequency, volume=.1):
self.frequency = frequency
Sound.__init__(self, self.build_samples())
self.set_volume(volume)
def build_samples(self):
period = int(round(get_init()[0] / self.frequency))
samples = array("h", [0] * period)
amplitude = 2 ** (abs(get_init()[1]) - 1) - 1
for time in range(period):
if time < period / 2:
samples[time] = amplitude
else:
samples[time] = -amplitude
return samples
if __name__ == "__main__":
pre_init(44100, -16, 1, 1024)
pygame.init()
Note(440).play(-1)
sleep(5)
为方便起见,我使用此方法:
def playSound(hz,ms):
pre_init(44100, -16, 1, 1024)
Note(hz).play(ms)
为ms设置-1会无限播放声音。
我的问题是我无法控制声音停止的时间。我试过在它上面播放另一个听不见的频率,但两者都可以同时播放。关于如何在释放钥匙时结束播放声音的任何想法?
答案 0 :(得分:3)
您必须定期"mainloop"
来检查密钥。
但系统仅将关键事件发送到活动窗口,因此您必须创建窗口。
import pygame
import array
class Note(pygame.mixer.Sound):
def __init__(self, frequency, volume=.1):
self.frequency = frequency
pygame.mixer.Sound.__init__(self, self.build_samples())
self.set_volume(volume)
def build_samples(self):
period = int(round(pygame.mixer.get_init()[0] / self.frequency))
samples = array.array("h", [0] * period)
amplitude = 2 ** (abs(pygame.mixer.get_init()[1]) - 1) - 1
for time in range(period):
if time < period / 2:
samples[time] = amplitude
else:
samples[time] = -amplitude
return samples
if __name__ == "__main__":
# --- init ---
pygame.mixer.pre_init(44100, -16, 1, 1024)
pygame.init()
screen = pygame.display.set_mode((100, 100))
# --- objects ---
tones = {
pygame.K_q: Note(440),
pygame.K_w: Note(340),
pygame.K_e: Note(540)
}
# --- mainloop ---
running = True
while running:
for event in pygame.event.get():
# closing window
if event.type == pygame.QUIT:
running = False
# pressing key
elif event.type == pygame.KEYDOWN:
if event.key in tones:
print('press:', event.key)
tones[event.key].play(-1)
# releasing key
elif event.type == pygame.KEYUP:
if event.key in tones:
print('release:', event.key)
tones[event.key].stop()
# --- end ---
pygame.quit()
编辑:显示按键的示例。
BTW:某些键盘不会发送超过4个按键。
import pygame
import array
class Note(pygame.mixer.Sound):
def __init__(self, frequency, volume=.1):
self.frequency = frequency
pygame.mixer.Sound.__init__(self, self.build_samples())
self.set_volume(volume)
def build_samples(self):
period = int(round(pygame.mixer.get_init()[0] / self.frequency))
samples = array.array("h", [0] * period)
amplitude = 2 ** (abs(pygame.mixer.get_init()[1]) - 1) - 1
for time in range(period):
if time < period / 2:
samples[time] = amplitude
else:
samples[time] = -amplitude
return samples
if __name__ == "__main__":
# --- init ---
pygame.mixer.pre_init(44100, -16, 1, 1024)
pygame.init()
screen = pygame.display.set_mode((110, 100))
# --- objects ---
keys = [
(pygame.K_q, 140),
(pygame.K_w, 240),
(pygame.K_e, 340),
(pygame.K_r, 440),
(pygame.K_t, 540),
]
tones = {}
pressed = {}
for key, val in keys:
tones[key] = Note(val)
pressed[key] = False
# --- mainloop ---
running = True
while running:
# - events -
for event in pygame.event.get():
# closing window
if event.type == pygame.QUIT:
running = False
# pressing key
elif event.type == pygame.KEYDOWN:
if event.key in tones:
#print('press:', event.key)
tones[event.key].play(-1)
pressed[event.key] = True
# releasing key
elif event.type == pygame.KEYUP:
if event.key in tones:
#print('release:', event.key)
tones[event.key].stop()
pressed[event.key] = False
# - draws -
# clear screen
screen.fill((0,0,0))
# draw pressed keys
for idx, key in enumerate(keys):
if key[0] in pressed and pressed[key[0]]:
x = 21*idx
pygame.draw.rect(screen, (255,255,255), (x, 0, 20, 50))
# send buffer on monitor
pygame.display.flip()
# --- end ---
pygame.quit()
答案 1 :(得分:2)
我问Cemetech并得到了这个解决方案:
from array import array
import pygame
from pygame.mixer import Sound, get_init, pre_init
class Note(pygame.mixer.Sound):
def __init__(self, frequency, volume=.1):
self.frequency = frequency
Sound.__init__(self, self.build_samples())
self.set_volume(volume)
def build_samples(self):
period = int(round(get_init()[0] / self.frequency))
samples = array("h", [0] * period)
amplitude = 2 ** (abs(get_init()[1]) - 1) - 1
for time in range(period):
if time < period / 2:
samples[time] = amplitude
else:
samples[time] = -amplitude
return samples
pre_init(44100, -16, 1, 1024)
pygame.init()
screen = pygame.display.set_mode([640, 480], 0)
sounds = {}
keymap = {
pygame.K_z: 880,
pygame.K_x: 440
}
while True:
evt = pygame.event.wait()
if evt.type == pygame.QUIT:
break
elif evt.type == pygame.KEYDOWN:
if evt.key in keymap:
note = Note(keymap[evt.key])
note.play(-1)
sounds[evt.key] = note
elif evt.type == pygame.KEYUP:
if evt.key in sounds:
sounds.pop(evt.key).stop()
pygame.quit()
它似乎正常工作并且可以用于多个音符。谢谢大家!