Page 1 of 1

Sound Loop GPIO Music Box

Posted: Thu Jul 21, 2016 5:36 am
by tarff
Hi, I've been playing around with raspberry pi's for some time so I decided to take on a slightly more advanced project (for me anyway.)

I'm trying to build a soundboard that plays samples on a button press. I have the sounds playing and stopping on the button press, however, I cant for the life of me figure out how to get the sounds to play on a continuous loop until the button is pressed again.

I've search google and the forums and figure it has something to do with the hold_repeat function on gpiozero but I don't have much coding experience and cant work out where to fit it in the code.

The code I'm using is:

Code: Select all

import pygame.mixer
from pygame.mixer import Sound
from gpiozero import Button
from signal import pause

pygame.mixer.init()

sound_pins = {
    2: Sound("samples/sound1.wav"),
    3: Sound("samples/sound2.wav"),
}

print "pedal ready"

buttons = [Button(pin) for pin in sound_pins]
for button in buttons:
    sound = sound_pins[button.pin.number]
    button.when_pressed = sound.play
    button.when_released = sound.stop
    
pause()
Taken from here https://gpiozero.readthedocs.io/en/v1.2 ... -music-box

Any help would be greatly appreciated.

Re: Sound Loop GPIO Music Box

Posted: Thu Jul 21, 2016 10:09 am
by YCN-
Well, I don't really know a lot of python, but I'm working currently in a similar drum machine project. I'm doing it in C, but here's how I do what you want to do, I use an array int pattern [N_STEP][N_PATTERN] , and I fill it when a button is pressed, mean while I have two principal threads, one playing the sound and the other one witch just increasing the current step each n second (n depending on the BPM aka tempo you wanna have).
This is my way and it's working fine, but I have no idea how you can do thread in python ahah.

(Just in case a thread is an independent program that is running in your program if I can say so. It's not exactly that but if you don't what it is it's a good introduction and for what you want to do I think it's enough for you. I can give you sample of code to show you how threads work in C, but it won't be any help for python)

Re: Sound Loop GPIO Music Box

Posted: Thu Jul 21, 2016 11:29 am
by elParaguayo
Well, according to the pygame docs you can pass a loops parameter and setting that to -1 loops indefinitely.

So, you could try changing this line:

Code: Select all

button.when_pressed = sound.play
to

Code: Select all

button.when_pressed = lambda snd=sound: snd.play(loops=-1)

Re: Sound Loop GPIO Music Box

Posted: Fri Jul 22, 2016 1:46 am
by tarff
Ah, thank you so much. That did it.

Re: Sound Loop GPIO Music Box

Posted: Fri Jul 22, 2016 6:08 am
by elParaguayo
My pleasure. Happy to help.

Re: Sound Loop GPIO Music Box

Posted: Mon Jan 28, 2019 10:18 pm
by brandonandrsn
im looking to do something similar.

play sound on GPIO button press and continue to play loop until the GPIO is pressed a second time.

so far my code is this.
it loops the sound while button is pressed but stops once released.
looking to build a crude loop sampler box

Code: Select all

import pygame.mixer
from pygame.mixer import Sound
from gpiozero import Button
from signal import pause

pygame .mixer.init()

button_sounds = {
	Button(21): Sound("samples/clap.wav"),
}

for button, sound in button_sounds.items():
	button.when_pressed = lambda snd=sound: snd.play(loops=-1)
	button.when_released = sound.stop

pause()

Re: Sound Loop GPIO Music Box

Posted: Tue Jan 29, 2019 9:39 am
by elParaguayo
One way to do this would be to make the sound play on a particular channel. You can then use the "get_busy" method of the channel to check if the sound is playing.

Your on_pressed method would then call a function that checks if a sound is playing. If it isn't, then it starts it. If it is, then it stops it.

If you're only going to be playing one sound then you can just use pygame.mixer.get_busy instead.

Re: Sound Loop GPIO Music Box

Posted: Tue Jan 29, 2019 11:07 am
by brandonandrsn
elParaguayo wrote:
Tue Jan 29, 2019 9:39 am
One way to do this would be to make the sound play on a particular channel. You can then use the "get_busy" method of the channel to check if the sound is playing.

Your on_pressed method would then call a function that checks if a sound is playing. If it isn't, then it starts it. If it is, then it stops it.

If you're only going to be playing one sound then you can just use pygame.mixer.get_busy instead.
mind showing me how one would do so? how do i set a sound to a particular channel and use the get busy?

Re: Sound Loop GPIO Music Box

Posted: Tue Jan 29, 2019 1:00 pm
by elParaguayo
OK. By default I think pygame has 8 channels but I think you can increase this.

As for the code, I was just thinking something along the lines of:

Code: Select all

import pygame.mixer
from pygame.mixer import Sound
from gpiozero import Button
from signal import pause

pygame.mixer.init()

button_sounds = {
	Button(21): {"channel": 0, "sound": Sound("samples/clap.wav")},
}

def start_stop_sound(snd):
    channel = pygame.mixer.Channel(snd["channel"])
    if channel.get_busy():
        # Sound is playing - stop it
        channel.stop()
    else:
        # No sound playing on this channel
        sound = snd["sound"]
        channel.play(sound, loops=-1)

for button, sound in button_sounds.items():
	button.when_pressed = lambda snd=sound: start_stop_sound(snd)

pause()
Code is untested but I hope this gives you and idea of what I was trying to do.

Re: Sound Loop GPIO Music Box

Posted: Thu Jan 31, 2019 12:58 am
by brandonandrsn
elParaguayo wrote:
Tue Jan 29, 2019 1:00 pm
OK. By default I think pygame has 8 channels but I think you can increase this.

As for the code, I was just thinking something along the lines of:

Code: Select all

import pygame.mixer
from pygame.mixer import Sound
from gpiozero import Button
from signal import pause

pygame.mixer.init()

button_sounds = {
	Button(21): {"channel": 0, "sound": Sound("samples/clap.wav")},
}

def start_stop_sound(snd):
    channel = pygame.mixer.Channel(snd["channel"])
    if channel.get_busy():
        # Sound is playing - stop it
        channel.stop()
    else:
        # No sound playing on this channel
        sound = snd["sound"]
        channel.play(sound, loops=-1)

for button, sound in button_sounds.items():
	button.when_pressed = lambda snd=sound: start_stop_sound(snd)

pause()
Code is untested but I hope this gives you and idea of what I was trying to do.
thank you so mucch