'How to assign sounds to channels in Pygame?

I'm trying to play multiple sounds simultaneously in Pygame. I have a background music and I want a rain sound to play continuously and play ocasional thunder sounds.

I have tried the following but my rain sound stops when thunder sound is playing. I have tried using channels but I don't know how to choose which channel to sound is playing from or if two channels can be played at once.

        var.rain_sound.play()

        if random.randint(0,80) == 10:                
            thunder = var.thunder_sound                
            thunder.play()

Thank you for your help



Solution 1:[1]

You can only play one Sound at a time per channel, but you can play multiple channels at once. If you don't name the channels, pygame selects an unused channel to play a Sound; by default, pygame has 8 channels around. You can specify a channel by creating a Channel object. As for looping a sound indefinitely, you can do that by playing a sound with the argument loops = -1. You can find the documentation for these classes and methods at http://www.pygame.org/docs/ref/mixer.html
I would also suggest using the built-in module time, particularly the sleep() function that pauses execution for a specified time in seconds. This is because pygame.mixer functions that play a Sound return ASAP long before the sound finishes playing, and when you try to play a 2nd Sound on the same channel, the 1st Sound is stopped to play the 2nd. So, to guarantee that your thunder Sound is played to completion, it's best to pause execution while it's playing. I put the sleep() line outside the if-statement because inside the if-statement, the sleep() line won't pause execution if the thunder Sound isn't played, so the loop would just loop very quickly to the next thunder Sound, outputting far more frequently than "occasional."

import pygame
import random
import time
import var

# initialize pygame.mixer
pygame.mixer.init(frequency = 44100, size = -16, channels = 1, buffer = 2**12) 
# init() channels refers to mono vs stereo, not playback Channel object

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

# plays loop of rain sound indefinitely until stopping playback on Channel,
# interruption by another Sound on same Channel, or quitting pygame
channel1.play(var.rain_sound, loops = -1)

# plays occasional thunder sounds
duration = var.thunder_sound.get_length() # duration of thunder in seconds
while True: # infinite while-loop
    # play thunder sound if random condition met
    if random.randint(0,80) == 10:
        channel2.play(var.thunder_sound)
    # pause while-loop for duration of thunder
    time.sleep(duration)

Solution 2:[2]

Pygame's find_channel function makes it very easy to play audio on an unused channel:

sound1 = pygame.mixer.Sound("sound.wav")
pygame.mixer.find_channel().play(sound1)

Note that by default, find_channel will return None if there are no free channels available. By passing it True, you can instead return the channel that's been playing audio the longest:

sound1 = pygame.mixer.Sound("sound.wav")
pygame.mixer.find_channel(True).play(sound1)

You may also be interested in the set_num_channels function, which lets you set the maximum number of audio channels:

pygame.mixer.set_num_channels(20)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Pikamander2