Open yusufmte opened 2 days ago
explored this in pygame - see play_sound() function in #11
With pygame.mixer.music, the sounds are intrinsically played in the background, so they are non-blocking. However, we frequently have multiple sounds played in rapid succession (for example, reading off one score-number, then another, then the current server). A few options each of which is peupy:
def play_sound(file):
pygame.mixer.music.load(file)
pygame.mixer.music.play()
This causes the sounds played in rapid succession to interrupt each other rather than waiting for each other to finish.
def play_sound(file):
pygame.mixer.music.load(file)
pygame.mixer.music.play()
while pygame.mixer.music.get_busy():
pygame.time.Clock().tick(10)
This works (and also ensures the last sound file played will finish before the program closes), but it is blocking.
def play_sound(file):
if pygame.mixer.music.get_busy():
pygame.mixer.music.queue(file)
else:
pygame.mixer.music.load(file)
pygame.mixer.music.play()
This initially seemed promising and it is non-blocking. If there is a sound playing, queue() will load up another to automatically play after that one finishes. However, only one thing can be in the queue at a time (and I don't see a way to check what is in the queue or whether it is occupied). The end result is that if you have enough things in rapid succession, the 3rd thing might boot the 2nd thing out of the queue before it could be loaded up, and not all of them play.
Instead of using pygame.mixer.music we could also use pygame.mixer.Sound
It seems to support loading mp3 files
I think you create a "channel" and then use that same channel to play all sounds, then it should stop any already playing sound whenever you play a sound on that same channel.
Try this in ipython to see what I mean; I think it gets everything we want:
import pygame
from pygame.mixer import Sound, Channel
pygame.mixer.init()
c = Channel(0)
s = Sound("match_score.mp3")
s2 = Sound("game_score.mp3")
# try running these lines in quick succession to see how the playback gets interrupted
c.play(s)
c.play(s2)
But we don't want the playback to be interrupted unless there's a mouse-click, right? Otherwise, the scores will interrupt each other and we'll only hear who is serving. We want the next sound to start only when the first one is finished, or some way to concatenate mp3 files.
I see, that's right!
Okay so we actually sometimes want to interrupt, and sometimes we want to add things to a "queue" of sounds to be played in succession.
We might then need to use the pygame event system: https://www.pygame.org/docs/ref/mixer.html#pygame.mixer.Channel.set_endevent
The queue of sounds should respond to the end of playback of a sound by playing the next sound.
We have to learn in general how the pygame event system works in order to use that.
I think a playback manager class is appropriate here to handle the details. That class could have a method like play_now
that interrupts anything currently playing and drops the queue, and a method like play_later
that adds the sound to the queue of sounds waiting to be played
after discussion we decided to complete #7 before tackling this, since the solution to this could depend very much on what the main application loop is.
to make undo more reasonable