【问题标题】:Pygame audio code not workingPygame音频代码不起作用
【发布时间】:2019-03-06 08:32:31
【问题描述】:

这段代码似乎运行正常,但实际上并没有任何它应该做的事情,除了打开 pygame 窗口。我正在寻找按下“z”键时播放的声音。

谁能看出这段代码有问题?

import pygame
from pygame.locals import *
import math
import numpy

size = (1200, 720)
screen = pygame.display.set_mode(size, pygame.HWSURFACE | pygame.DOUBLEBUF)
pygame.display.set_caption('Nibbles!')

SAMPLE_RATE = 22050 ## This many array entries == 1 second of sound.

def SineWave(freq=1000,volume=16000,length=1):
    num_steps = length*SAMPLE_RATE
    s = []
    for n in range(num_steps):
        value = int(math.sin(n * freq * (6.28318/SAMPLE_RATE) * length)*volume)
        s.append( [value,value] )
    x_arr = array(s)
    return x_arr

def SquareWave(freq=1000,volume=100000,length=1):
    length_of_plateau = SAMPLE_RATE / (2*freq)
    s = []
    counter = 0
    state = 1
    for n in range(length*SAMPLE_RATE):
        if state == 1:
            value = volume
        else:
            value = -volume
        s.append( [value,value] )

        counter += 1
        if counter == length_of_plateau:
            counter = 0
            if state == 1:
                state = -1
            else:
                state = 1

    x_arr = array(s)
    return x_arr

def MakeSound(arr):
    return pygame.sndarray.make_sound(arr)

def PlaySquareWave(freq=1000):
    MakeSound(SquareWave(freq)).play()

def PlaySineWave(freq=1000):
    MakeSound(SineWave(freq)).play()

def StopSineWave(freq=1000):
    MakeSound(SineWave(freq)).fadeout(350)

def StopSquareWave(freq=1000):
    MakeSound(SquareWave(freq)).fadeout(350)

_running = True
while _running:

    SineWaveType = 'Sine'
    SquareWaveType = 'Square'
    d = {SineWaveType:SquareWaveType, SquareWaveType:SineWaveType}
    Type = SineWaveType

    for event in pygame.event.get():
            if event.type == pygame.QUIT:
                _running = False

            if Type == 'Sine':

                if event.type == KEYDOWN:

                    #lower notes DOWN
                    if event.key == K_ESCAPE:
                        _running = False

                    if event.key == K_ENTER:
                        Type = d[Type]  #Toggle

                    elif event.key == K_z:
                        PlaySineWave(130.81)

                if event.type == KEYUP:

                    #lower notes UP

                    if event.key == K_z:
                        StopSineWave(130.81).fadeout(350)       #fade sound by .35 seconds

            elif Type == 'Square':

                if event.type == KEYDOWN:

                    #lower notes DOWN
                    if event.key == K_z:
                        PlaySquareWave(130.81)

                if event.type == KEYUP:

                    #lower notes UP

                    if event.key == K_z:
                        StopSquareWave(130.81).fadeout(350)     #fade sound by .35 seconds

pygame.quit()

【问题讨论】:

  • 您意识到您的_running 循环除了等待QUIT 之外什么都不做,对吧?您希望这段代码在什么时候真正任何事情?
  • 我现在觉得自己很蠢,完全没有注意到这一点。我已经编辑了原始帖子,现在它甚至无法打开 pygame 窗口,我这里还有什么遗漏吗?
  • 您确实需要掌握 Python 的基于缩进的作用域 - 从if Type == 'Sine': 到以下的所有内容都while 循环之外。
  • 我的实际代码不是这种情况,它就是这样粘贴到这里的,据我所知,所有缩进都是正确的,原帖已被再次编辑以显示这一点。
  • 每个循环你应该只通过event in pygame.event.get()一次,否则你可能会在寻找另一个事件时丢弃一个事件。

标签: python audio numpy pygame trigonometry


【解决方案1】:

编辑 (2019.03.06): 现在代码适用于 Python 3 - 感谢评论中的 Tomasz Gandor 建议。


一些修改:

  • 您必须淡出现有声音而不是创建新声音来淡出(因为 pygame 会同时播放两者) - 我使用 curren_played 来保留现有声音。
  • ESCAPEENTER 键不必检查声音类型。
  • 你忘了pygame.init() 初始化屏幕、混音器和其他东西。
  • 因为我在使用方波时遇到问题,所以我在示例中使用了正弦波。
  • 我在c 键上添加了sonund - 这样您就可以同时播放两个声音
  • 我对常量值使用大写名称,例如SINE_WAVE_TYPE

您可以在mainloop 之前创建波形并将其保存在current_played 中,并在您按RETURN 时在current_played 中生成新波形 .

import pygame
from pygame.locals import *
import math
import numpy

#----------------------------------------------------------------------
# functions
#----------------------------------------------------------------------

def SineWave(freq=1000, volume=16000, length=1):

    num_steps = length * SAMPLE_RATE
    s = []

    for n in range(num_steps):
        value = int(math.sin(n * freq * (6.28318/SAMPLE_RATE) * length) * volume)
        s.append( [value, value] )

    return numpy.array(s, dtype=numpy.int32) # added dtype=numpy.int32 for Python3

def SquareWave(freq=1000, volume=100000, length=1):

    num_steps = length * SAMPLE_RATE
    s = []

    length_of_plateau = SAMPLE_RATE / (2*freq)

    counter = 0
    state = 1

    for n in range(num_steps):

        value = state * volume
        s.append( [value, value] )

        counter += 1

        if counter == length_of_plateau:
            counter = 0
            state *= -1

    return numpy.array(s, dtype=numpy.int32) # added dtype=numpy.int32 for Python3

def MakeSound(arr):
    return pygame.sndarray.make_sound(arr)

def MakeSquareWave(freq=1000):
    return MakeSound(SquareWave(freq))

def MakeSineWave(freq=1000):
    return MakeSound(SineWave(freq))

#----------------------------------------------------------------------
# main program
#----------------------------------------------------------------------

pygame.init()

size = (1200, 720)
screen = pygame.display.set_mode(size, pygame.HWSURFACE | pygame.DOUBLEBUF)
pygame.display.set_caption('Nibbles!')

SAMPLE_RATE = 22050 ## This many array entries == 1 second of sound.

SINE_WAVE_TYPE = 'Sine'
SQUARE_WAVE_TYPE = 'Square'

sound_types = {SINE_WAVE_TYPE:SQUARE_WAVE_TYPE, SQUARE_WAVE_TYPE:SINE_WAVE_TYPE}

current_type = SINE_WAVE_TYPE

current_played = { 'z': None, 'c': None }

_running = True
while _running:

    for event in pygame.event.get():

        if event.type == pygame.QUIT:
            _running = False

        # some keys don't depend on `current_type`

        elif event.type == KEYDOWN:

            if event.key == K_ESCAPE:
                _running = False

            if event.key == K_RETURN:
                current_type = sound_types[current_type]  #Toggle
                print('new type:', current_type) # added () for Python3

        # some keys depend on `current_type`

        if current_type == SINE_WAVE_TYPE:

            if event.type == KEYDOWN:

                #lower notes DOWN

                if event.key == K_z:
                    print(current_type, 130.81) # added () for Python3
                    current_played['z'] = MakeSineWave(130.81)
                    current_played['z'].play()

                elif event.key == K_c:
                    print(current_type, 180.81) # added () for Python3
                    current_played['c'] = MakeSineWave(180.81)
                    current_played['c'].play()

            elif event.type == KEYUP:

                #lower notes UP

                if event.key == K_z:
                    current_played['z'].fadeout(350)
                elif event.key == K_c:
                    current_played['c'].fadeout(350)

        elif current_type == SQUARE_WAVE_TYPE:

            if event.type == KEYDOWN:

                #lower notes DOWN

                if event.key == K_z:
                    print(current_type, 80.81) # added () for Python3
                    current_played['z'] = MakeSineWave(80.81)
                    #current_played['z'] = MakeSquareWave(130.81)
                    current_played['z'].play()

                elif event.key == K_c:
                    print(current_type, 180.81) # added () for Python3
                    current_played['c'] = MakeSineWave(180.81)
                    #current_played['c'] = MakeSquareWave(130.81)
                    current_played['c'].play()

            elif event.type == KEYUP:

                #lower notes UP

                if event.key == K_z:
                    current_played['z'].fadeout(350)
                elif event.key == K_c:
                    current_played['c'].fadeout(350)

pygame.quit()

【讨论】:

  • 有效!对于 Python 3,运行 2to3(只是 print 语句),并为 numpy 数组指定 dtype=np.int32 (import numpy as np)。
  • @TomaszGandor - 谢谢。这段代码已经有将近 5 年的历史了,但是根据您的建议,它仍然很有用。 (PL: Dzięki. Ten kod ma prawie 5 lat ale z Twoim sugestiami wciąż może być przydatny)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-06
  • 1970-01-01
  • 2017-10-02
  • 2013-01-08
  • 1970-01-01
  • 2021-06-01
  • 1970-01-01
相关资源
最近更新 更多