2016-12-14 105 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

相關問題