Python 如何使用pygame按顺序运行声音循环?
我一直在试验前几天我得到的一个奇怪的想法,我想知道是否有人知道解决我遇到的问题的方法 所以,我想做的是一个声音的串联,循环一个随机的次数,然后移动到下一个声音,再循环一个随机的次数,然后移动到下一个,然后继续这样做,比如说,100个其他声音 这就像一个预先确定的声音列表,以固定的顺序激活,但每个声音都有一个“循环”变量,它本质上是两个数字之间的一个随机整数,决定了在进入下一个数字之前声音循环的次数 我制作这个动画是因为我不善于解释事情 我知道这听起来很愚蠢,毫无意义,有点疯狂,但正如我所说,这是一个实验 这似乎很容易,所以我尝试了以下方法: (顺便说一句,我正在使用Tkinter和pygame) 但问题是pygame不会等待每个循环结束,它会同时播放每个声音 然后,我突然想到,使用“For循环”可能会解决这个问题,可能类似于这样,但声音:Python 如何使用pygame按顺序运行声音循环?,python,python-3.x,audio,tkinter,pygame,Python,Python 3.x,Audio,Tkinter,Pygame,我一直在试验前几天我得到的一个奇怪的想法,我想知道是否有人知道解决我遇到的问题的方法 所以,我想做的是一个声音的串联,循环一个随机的次数,然后移动到下一个声音,再循环一个随机的次数,然后移动到下一个,然后继续这样做,比如说,100个其他声音 这就像一个预先确定的声音列表,以固定的顺序激活,但每个声音都有一个“循环”变量,它本质上是两个数字之间的一个随机整数,决定了在进入下一个数字之前声音循环的次数 我制作这个动画是因为我不善于解释事情 我知道这听起来很愚蠢,毫无意义,有点疯狂,但正如我所说,这
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)
但它也不起作用
现在我在胡闹时间。睡眠,因为每个声音都有一个特定的持续时间,我想我可以计算出每个循环必须等待的时间
像这样,也许:
sound2.wav持续1.5s,所以假设随机数为2,即1.5s声音片段的2个循环
2*1.5s=3s
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)
但到目前为止,这一切都非常不稳定、混乱和怪异,而事实上,时间冻结意味着它对我几乎毫无用处
总而言之。。。如果您知道一种使pygame声音同步运行的方法,或者有一种更简单的解决方案,我没有看到,请告诉我 一种简单的方法是使用
pygame.mixer.Channel()
函数set\u 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上的很多声音都很长(例如:多个鸭子叫声)。我用这个工具把它们剪成短促的声音,在两边留下一瞬间的安静
编辑:
要将其更改为预先确定的列表,只需保留当前_声音的记录
# 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" )
#声音列表
所有声音=[喇叭、嘎嘎声、嘎吱声、吠声、叮当声、狼吞虎咽声]
#从第一个声音开始
通道2.播放(所有声音[0])
当前声音索引=0
...
对于pygame.event.get()中的事件:
如果(event.type==pygame.QUIT):
完成=正确
elif(event.type==pygame.USEREVENT+1):
#通道2声音结束,开始下一个声音!
当前声音指数+=1
如果(当前声音索引
哇,非常感谢你,金斯利,这真是太有洞察力了。我很抱歉在我最初的帖子中说得不够清楚,但我想做的是一个“预先确定”的声音列表,其中每个声音循环基于一个随机间隔,该间隔与当时播放的声音相关,但你的回答给了我一些尝试的想法。我在原来的帖子中添加了一个小动画,旁边还有一个更清晰的解释,因为我在解释事情方面太糟糕了。再次感谢你,如果我误解了你的答案,我道歉(我不是真正的程序员)不用担心,很高兴我能帮上忙。要使上面的示例播放预先确定的列表,只需保留一条记录,记录从所有声音中播放的声音索引,然后播放下一个,而不是随机播放。@Austin.W-请参见编辑。这有点接近你需要的。我想从这一点上你可以很容易地计算出随机的比赛时间。嗯,我非常感谢你@Kingsley,我真的很感激你。现在我正在尝试实现“循环随机化器”,我相信我最终会找到答案的
# 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" )