Playing multiple sounds at once

From ESE205 Wiki
Jump to navigation Jump to search


Introduction

This tutorial will explain different methods attempted in getting multiple sounds to play concurrently using python.

Steps

  • Pick wav files desired to be played.
  • Load wav files in code and save it to a variable that can be called later.
  • Find a line of code that will play the sound.
  • Find a line of code that will allow the sound to be played while different notes are being played at the same time.

Libraries tested

  • pydub
  • multiprocessing
  • multithreading
  • swmixer
  • pygame

Pydub and Pygame

These two libraries were used in finding the best way to play a sound by itself.

Using pydub:

from pydub import AudioSegment
from pydub.playback import play
sound = AudioSegment.from_wav('/home/pi/laserharp-sounds/samples/harpSound1.wav')
play(sound)


Using pygame:

import pygame
pygame.init()
pygame.mixer.init()
firstSound = pygame.mixer.music('/home/pi/laserharp-sounds/samples/ambi_dark.wav')
secondSound = pygame.mixer.music('/home/pi/laserharp-sounds/samples/ambi_choir.wav')
firstSound.play()
secondSound.play()

pygame.mixer.music is often used to produce sounds that are higher in quality. However, when trying to play multiple sounds at once, it is best to use pygame.mixer.Sound instead.

Multiprocessing and Multithreading

Using Multiprocessing:

from multiprocessing import Process
def play1():
 if(lightlevell > 800):
    s = pygame.mixer.sound.load('/home/pi/laserharp-sounds/1.wav')
    pygame.mixer.sound.play(-1)
def play2():
 if(lightlevel2 > 800):
    s = pygame.mixer.sound.load('/home/pi/laserharp-sounds/2.wav')
    pygame.mixer.sound.play(-1)
processes = []
if __name__=='__main__':
  processes.append(Process(target = play1))
  processes.append(Process(target = play2))
for process in processes:
  process.start()
for process in processes:
  process.join()

Using Multithreading:

from threading import Thread
def play1():
 if(lightlevell > 800):
    s = pygame.mixer.sound.load('/home/pi/laserharp-sounds/1.wav')
    pygame.mixer.sound.play(-1)
def play2():
 if(lightlevel2 > 800):
    s = pygame.mixer.sound.load('/home/pi/laserharp-sounds/2.wav')
    pygame.mixer.sound.play(-1)
threads = []
if __name__=='__main__':
  threads.append(Thread(target = play1))
  threads.append(Thread(target = play2))
for thread in threads:
  thread.start()
for thread in threads:
  thread.join()

The main difference between multiprocessing and multithreading is that multiprocessing uses separate memory spaces while multithreading uses the same memory space. Therefore, it would be easier to share objects with multithreading.

Multithreading with Swmixer

from threading import Thread
import swmixer
import os 
swmixer.init(samplerate=44100, chunksize=1024, stereo=False)
swmixer.start()
def play1():
 if(lightlevell > 800):
    a = swmixer.Sound('/home/pi/laserharp-sounds/1.wav')
    swmixer.play(-1)
def play2():
 if(lightlevel2 > 800):
    a = swmixer.Sound('/home/pi/laserharp-sounds/1.wav')
    swmixer.play(-1)
threads = []
if __name__=='__main__':
  threads.append(Thread(target = play1))
  threads.append(Thread(target = play2))
for thread in threads:
  thread.start()
for thread in threads:
  thread.join()


If you choose to use Java, this might be a useful link. It shows how to use Threads to play multiple sounds at once. - Java link

Pygame with Channels

#this is code from the final version of code used to program the Laser Harp. This is saying that if lasers 1 and/or 2 are broken, the wav file associated with that file will be played. 
import pygame
pygame.mixer.pre_init()
pygame.mixer.init()
pygame.init()
while true
if(light_level > 800):  # state 1
  pygame.mixer.Channel(0).play(pygame.mixer.Sound('/home/pi/laserharp-sounds/1.wav'))
if (light_level2 > 800):  # state 2
  pygame.mixer.Channel(1).play(pygame.mixer.Sound('/home/pi/laserharp-sounds/2.wav'))

Final version of code

Link to project

Laser Harp