Как запустить звуковые петли в последовательности с Pygame? - PullRequest
1 голос
/ 06 апреля 2020

Я экспериментировал со странной идеей, которая у меня появилась на днях, и я хотел узнать, знает ли кто-нибудь способ решения проблемы, с которой я столкнулся

Итак, что я хотел сделать, так это объединение звуков, которые l oop случайное количество раз, а затем переходят к следующему звуку, который снова повторяется в течение другого случайного количества раз, а затем переходит к следующему и продолжает делать это, скажем, для 100 других звуки?

Это похоже на заранее определенный список звуков, который активируется в фиксированном порядке, но каждый звук имеет переменную «зацикливания», которая по сути является случайным целым числом между двумя числами, которое определяет, сколько раз этот звук повторяется до перейти к следующему.

Я сделал эту анимацию, потому что я сосал объяснения.

enter image description here

Я знаю, это звучит глупо, бессмысленно и немного безумно, но, как я уже сказал, это эксперимент.

он казался достаточно легким, поэтому я попробовал это:

(Кстати, я использую 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)

, но это также не сработало

Теперь я возился со временем. сон, и так как каждый звук имеет определенную c длительность, я думаю, что могу рассчитать время ожидания каждого l oop.

вот так, майб e:

sound2.wav длится 1,5 с, поэтому предположим, что случайное число равно 2, то есть 2 петли аудиоклипа 1,5 с

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, означает, что это почти совершенно бесполезно для меня.

Подвести итог ... если вы знаете способ заставить звуки пигмеев вести себя синхронно или, если есть более простое решение, которого я не вижу, пожалуйста, дайте мне знать.

1 Ответ

2 голосов
/ 06 апреля 2020

Простой способ сделать это - использовать функцию 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 довольно длинные (например: Несколько duck-quaks ). Я обрезал их до коротких звуков с помощью инструмента 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" )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...