Pygame音频代码无效

时间:2014-07-22 13:13:22

标签: python audio numpy pygame sine

这个代码似乎运行正常,但除了打开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()

1 个答案:

答案 0 :(得分:1)

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


一些修改:

  • 你必须淡化现有声音而不是为fadeout创建新声音(因为pygame会同时播放) - 我使用curren_played来保持现有声音。
  • ESCAPEENTER无需检查声音类型。
  • 您忘了pygame.init()初始化屏幕,调音台和其他内容。
  • 因为我遇到方波问题所以我在例子中使用正弦波。
  • 我将sonund添加到c键 - 这样你就可以同时播放两个声音
  • 我使用大写名称作为SINE_WAVE_TYPE等常量值。

您可以在mainloop之前创建wave并将其保留在current_played中,并在按current_played时在RETURN中生成新的wave

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()