如何使用pygame依次运行声音循环?

奥斯丁

我一直在尝试一个奇怪的想法,就是那天我得到了,我想知道是否有人知道解决我遇到的问题的方法

因此,我想做的是将一系列声音循环播放一次,然后移动到下一个声音,然后再循环播放另一次随机播放的声音,然后继续播放下一个声音,并继续执行此操作,假设还有其他100种声音?

这就像是按固定顺序激活的预定声音列表,但是每种声音都有一个“循环”变量,该变量本质上是两个数字之间的随机整数,用于确定在进入下一个声音之前声音循环循环多少次。

我之所以制作此动画,是因为我精于解释事物。

在此处输入图片说明

我知道这听起来很愚蠢,毫无意义并且有点疯狂,但是正如我所说的,这是一个实验。

看起来很容易,所以我尝试了这个:

(顺便说一句,我正在使用Tkinter和pygame)

def activate():

    random_number_1 = randint(0, 3)
    sound1 = pygame.mixer.Sound("sound2.wav")
    pygame.mixer.Sound.play(sound1, random_number_1)

    random_number_2 = randint(0, 3)
    sound2 = pygame.mixer.Sound("sound3.wav")
    pygame.mixer.Sound.play(sound2, random_number_2)

    random_number_3 = randint(0, 3)
    sound3 = pygame.mixer.Sound("sound4.wav")
    pygame.mixer.Sound.play(sound3, random_number_3)

    random_number_4 = randint(0, 3)
    sound4 = pygame.mixer.Sound("sound5.wav")
    pygame.mixer.Sound.play(sound4, random_number_4)

    random_number_5 = randint(0, 3)
    sound5 = pygame.mixer.Sound("sound6.wav")
    pygame.mixer.Sound.play(sound5, random_number_5)


button = Button(root, text="button", command=activate)
button.pack()

但问题在于pygame不会等待每个循环结束,而是同时播放每种声音

然后,我想到使用“ For Loops”可能会解决此问题,也许像这样但有声音:

def activate():
    randomnumber1 = randint(0, 3)
    for i in range(randomnumber1):
        print(1)

    randomnumber2 = randint(0, 3)
    for i in range(randomnumber2):
        print(2)

    randomnumber3 = randint(0, 3)
    for i in range(randomnumber3):
        print(3)

    randomnumber4 = randint(0, 3)
    for i in range(randomnumber4):
        print(4)

像这样:

def activate():
    randomnumber1 = randint(0, 3)
    for i in range(randomnumber1):
        sound1 = pygame.mixer.Sound("sound2.wav")
        pygame.mixer.Sound.play(sound1)

    randomnumber2 = randint(0, 3)
    for i in range(randomnumber2):
        sound2 = pygame.mixer.Sound("sound3.wav")
        pygame.mixer.Sound.play(sound2)

    randomnumber3 = randint(0, 3)
    for i in range(randomnumber3):
        sound3 = pygame.mixer.Sound("sound4.wav")
        pygame.mixer.Sound.play(sound3)

    randomnumber4 = randint(0, 3)
    for i in range(randomnumber4):
        sound4 = pygame.mixer.Sound("sound5.wav")
        pygame.mixer.Sound.play(sound4)

但是没用

然后我想起winsound是同步运行的,据我所知,您无法指定声音循环的次数,因此我尝试了:

def activate():
    randomnumber1 = randint(0, 3)
    for i in range(randomnumber1):
        winsound.PlaySound("sound2.wav", winsound.SND_ASYNC)

    randomnumber2 = randint(0, 3)
    for i in range(randomnumber2):
        winsound.PlaySound("sound3.wav", winsound.SND_ASYNC)

    randomnumber3 = randint(0, 3)
    for i in range(randomnumber3):
        winsound.PlaySound("sound4.wav", winsound.SND_ASYNC)

    randomnumber4 = randint(0, 3)
    for i in range(randomnumber4):
        winsound.PlaySound("sound5.wav", winsound.SND_ASYNC)

但是也没有用

现在,我正在弄混time.sleep,并且由于每种声音都有特定的持续时间,我想我可以计算出每个循环必须等待的时间。

这样,也许:

sound2.wav持续1.5s,所以说随机数是2,即1.5s声音片段的2个循环

2 * 1.5秒= 3秒

random_number_1 = randint(0, 3)
    sound1 = pygame.mixer.Sound("sound2.wav")
    pygame.mixer.Sound.play(sound1, random_number_1)
    time.sleep(random_number_1*1.5)

但是到目前为止,它一直是超级眨眼,凌乱和怪异的,而time.sleep冻结了Tkinter的事实意味着这对我几乎完全没有用。

总结一下...如果您知道一种使pygame声音同步运行的方法,或者有一个我没有看到的更简单的解决方案,请告诉我。

金斯利

一种简单的方法是使用pygame.mixer.Channel()函数set_endevent()

channel2 = pygame.mixer.Channel(1)
channel2.set_endevent( pygame.USEREVENT+1 )

pygame.USEREVENT+1当声音停止播放时,这将发送事件队列到您指定的任何事件(在此处)。

我做了一个简短的演示示例。它会发出很长的背景声音,然后连续发出随机的短声。pygame.USEREVENT+1收到事件时,一个新的声音将立即开始。

import pygame
import random

# Window size
WINDOW_WIDTH    = 400
WINDOW_HEIGHT   = 400
WINDOW_SURFACE  = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE

DARK_BLUE = (   3,   5,  54)

### initialisation
pygame.init()
pygame.mixer.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), WINDOW_SURFACE )
pygame.display.set_caption("Random Sound")

### sound
# create separate Channel objects for simultaneous playback
channel1 = pygame.mixer.Channel(0) # argument must be int
channel2 = pygame.mixer.Channel(1)

# define the event that's sent when a sound stops playing:
channel2.set_endevent( pygame.USEREVENT+1 )

# Rain sound from: https://www.freesoundslibrary.com/sound-of-rain-falling-mp3/ (CC BY 4.0)
rain_sound = pygame.mixer.Sound( 'rain-falling.ogg' )
channel1.play( rain_sound, -1 )   # loop the rain sound forever
# and ...  All are (CC BY 4.0)
# https://www.freesoundslibrary.com/car-horn-sound-effect/
# https://www.freesoundslibrary.com/duck-quack/ 
# https://www.freesoundslibrary.com/cash-register-sound-effect/
# https://www.freesoundslibrary.com/turkey-gobble-call/
# https://www.freesoundslibrary.com/single-ding-sound-effect/
# https://www.freesoundslibrary.com/dog-bark-sound-effect/
# 
horn     = pygame.mixer.Sound( 'car-horn2.ogg' )      # converted from MP3 to OGG
quack    = pygame.mixer.Sound( 'duck-quack.ogg' )
ca_ching = pygame.mixer.Sound( 'cash-register.ogg' )
bark     = pygame.mixer.Sound( 'dog-bark.ogg' )
ding     = pygame.mixer.Sound( 'single-ding.ogg' )
gobble   = pygame.mixer.Sound( 'turkey-gobble.ogg' )

# Sound list
all_sounds = [ horn, quack, ca_ching, bark, ding, gobble ]
# Start with a random sound
channel2.play( random.choice( all_sounds ) )

### Main Loop
clock = pygame.time.Clock()
done = False
while not done:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True
        elif ( event.type == pygame.USEREVENT+1 ):
            # Channel2 sound ended, start another!
            channel2.play( random.choice( all_sounds ) )
            print( "Sound ended" )

    # Update the window, but not more than 60fps
    window.fill( DARK_BLUE )
    pygame.display.flip()

    # Clamp FPS
    clock.tick_busy_loop(60)

pygame.quit()

freesoundslibrary.com上的许多声音都很长(例如:多次鸭叫声)。我使用工具Audacity将它们剪切为短声,在每一侧都留下了瞬间的安静。

编辑:要将其更改为预定列表,只需保留一个记录,即current_sound。

# Sound list
all_sounds = [ horn, quack, ca_ching, bark, ding, gobble ]
# Start with the first sound
channel2.play( all_sounds[ 0 ] )
current_sound_index = 0

...

    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True
        elif ( event.type == pygame.USEREVENT+1 ):
            # Channel2 sound ended, start the next sound!
            current_sound_index += 1
            if ( current_sound_index < len( all_sounds ) ):
                channel2.play( all_sounds[ current_sound_index ] )
                print( "Sound ended" )
            else:
                print( "Played all sounds" )

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章