2016-12-14 106 views
0

我发现这个代码,用于播放声音:如何在播放按键时播放给定Hz的音调,并在播放时停止播放?

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) 

把-1毫秒播放声音无限。

我的问题是我无法控制声音何时停止。我尝试过播放另一个听不清的频率,但两者都可以同时播放。关于如何在释放密钥时结束播放声音的任何想法?

+0

您需持于关键了处理器的'Note'实例,并调用'.stop()'就可以了。另一个选择是调用'pygame.mixer.stop()'来停止所有的声音,但是只有当你没有任何你想要继续播放的其他声音时才有效。 –

+0

你可以使用标准循环'为事件pygame.event.get():'和'如果event.type == pygame.KEYDOWN'和'if event.type == pygame.KEYUP' – furas

+0

@furas这可以,但只能可以在某个时间处理一个事件(按一个键使解释器停止检测前一个键) – TrumpetDude

回答

1

我问上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() 

它似乎正确地和多个音符工作。感谢大家!

2

您必须构建"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() 

编辑:例子显示按键。

顺便说一句:有些键盘不会发送超过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() 

enter image description here

+0

带有绘制按键的新示例。 – furas

相关问题