PyGameExamplesAndAnswers

StackOverflow            reply.it reply.it

“Don’t Use a Comment When You Can Use a Function or a Variable”
Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship


Music and sound

Related Stack Overflow questions:

PyGame has 2 different modules for playing sound and music, the pygame.mixer module and the pygame.mixer.music module. This module contains classes for loading Sound objects and controlling playback. The difference is explained in the documentation:

The difference between the music playback and regular Sound playback is that the music is streamed, and never actually loaded all at once. The mixer system only supports a single music stream at once.

Sound

Related Stack Overflow questions:

If you want to play a single wav file, you have to initialize the module and create a pygame.mixer.Sound() object from the file. Invoke play() to start playing the file. Finally, you have to wait for the file to play.

Use get_length() to get the length of the sound in seconds and wait for the sound to finish: (The argument to pygame.time.wait() is in milliseconds)

import pygame

pygame.mixer.init()
my_sound = pygame.mixer.Sound('my_sound.wav')
my_sound.play()
pygame.time.wait(int(my_sound.get_length() * 1000))

Alternatively you can use pygame.mixer.get_busy to test if a sound is being mixed. Query the status of the mixer continuously in a loop.
In the loop, you need to delay the time by either pygame.time.delay or pygame.time.Clock.tick. In addition, you need to handle the events in the application loop. See pygame.event.get() respectively pygame.event.pump():

For each frame of your game, you will need to make some sort of call to the event queue. This ensures your program can internally interact with the rest of the operating system.

import pygame
pygame.init()

pygame.mixer.init()
my_sound = pygame.mixer.Sound('my_sound.wav')
my_sound.play()

while pygame.mixer.get_busy():
    pygame.time.delay(10)
    pygame.event.poll()

Sound from buffer

Related Stack Overflow questions:

Numpy arrays can be loaded directly to a pygame.mixer.Sound object and play it:

import pygame
import numpy as np

pygame.mixer.init()

buffer = np.sin(2 * np.pi * np.arange(44100) * 440 / 44100).astype(np.float32)
sound = pygame.mixer.Sound(buffer)

sound.play(0)
pygame.time.wait(int(sound.get_length() * 1000))

See pygame.sndarray.array():

Creates a new array for the sound data and copies the samples. The array will always be in the format returned from pygame.mixer.get_init().

In your case, for some reason, the mixer seems to have created a stereo sound format with 2 channels. You can verify that by

print(pygame.mixer.get_init())

Use numpy.reshape to convert the one-dimensional array to a two-dimensional 44100x1 array. Then use numpy.repeat to convert the 44100x1 array to a 44100x2 array, with the 1st channel copied to the 2nd channel:

import pygame
import numpy as np

pygame.mixer.init(frequency=44100, size=-16, channels=1)

size = 44100
buffer = np.random.randint(-32768, 32767, size)
buffer = np.repeat(buffer.reshape(size, 1), 2, axis = 1)

sound = pygame.sndarray.make_sound(buffer)
sound.play()
pygame.time.wait(int(sound.get_length() * 1000))

Alternatively, you can create a random sound for each channel separately:

import pygame
import numpy as np

pygame.mixer.init(frequency=44100, size=-16, channels=1)

size = 44100
buffer = np.random.randint(-32768, 32767, size*2)
buffer = buffer.reshape(size, 2)

sound = pygame.sndarray.make_sound(buffer)
sound.play()
pygame.time.wait(int(sound.get_length() * 1000))

Music

Related Stack Overflow questions:

📁 Minimal example - Play music 1

📁 Minimal example - Play music 2

If you want to play a mp3 file, you need to initialize the module. Load the file with pygame.mixer.music.load. Invoke pygame.mixer.music.play() to start playback of the music stream. Finally, you have to wait for the file to play.
Use pygame.mixer.music.get_busy() to test if a sound is being mixed. Query the status of the mixer continuously in a loop.
In the loop, you need to delay the time by either pygame.time.delay or pygame.time.Clock.tick. In addition, you need to handle the events in the application loop. See pygame.event.get() respectively pygame.event.pump():

For each frame of your game, you will need to make some sort of call to the event queue. This ensures your program can internally interact with the rest of the operating system.

import pygame
pygame.init()

pygame.mixer.init()
pygame.mixer.music.load('my_music.mp3')
pygame.mixer.music.play()

clock = pygame.time.Clock()
while pygame.mixer.music.get_busy():
    clock.tick(60)
    pygame.event.poll()

The unit of the time parameter to pygame.mixer.music.fadeout() is milliseconds. 1 second is 1000 milliseconds:

pygame.mixer.music.load(audio1)
pygame.mixer.music.play()

# play for 12.5 seconds
pygame.time.wait(12500)

# fade out for 10 seconds
pygame.mixer.music.fadeout(10000)
pygame.time.wait(10000)

Repeat music

Related Stack Overflow questions:

Multiple music files parallel

Related Stack Overflow questions:

Music file open dialog

Related Stack Overflow questions:

Volume

Related Stack Overflow questions:

Pause

Related Stack Overflow questions:

Unload music resources

Related Stack Overflow questions:

Time

Related Stack Overflow questions: