Drum hat hit kill


#1

Just wondering how I could make a hit on the drum hat kill the hit that is playing, it presently just plays over top, for example if I have a longer sample and I want to start it again? thanks for any insight


#2

It looks like Pygame’s Sound object supports stop to stop it playing: https://www.pygame.org/docs/ref/mixer.html#pygame.mixer.Sound

I can’t see any way to determine if it’s currently playing, though. It seems a sensible approach would be to:

  • Keep a value for each drum pad that you toggle on hit
  • If that value is true then .play() the corresponding sound
  • If that value is false then .stop() the corresponding sound
  • Additionally you could light an LED to show which state a pad is in

This doesn’t seem to bode well for re-trigger though, since if you can’t tell if a sound is playing or stopped then if you do let the sound finish the next drum pad hit will try to stop it.

Apparently, though, you could have a channel for each drum pad and play the sound into that, allowing you to use the get_busy() method:

https://www.pygame.org/docs/ref/mixer.html#pygame.mixer.Channel.get_busy

So I think your use-case is possible!

You can also combine this with loops=-1 for longer sounds, so they play in a continuous loop.

If you wanted to sync multiple sounds together (say percussion, rhythm and melody layers for a performance), you would have to play them all simultaneously and mute/unmute each channel on tap.

This is quite a useful setup, and would make for a good example!


#3

Here’s a quick demo showing my last thought in action: https://gist.github.com/Gadgetoid/a0b2dd2d62b6e64298387fc54bf1ff9d

import time
import math
import pygame

NUM_CHANNELS = 3

pygame.mixer.init(44100, -16, 1, 512)
pygame.mixer.set_num_channels(NUM_CHANNELS)

channels = [pygame.mixer.Channel(n) for n in range(NUM_CHANNELS)]

melody = pygame.mixer.Sound("./fn-melody.wav")
bass = pygame.mixer.Sound("./fn-bass.wav")
percussion = pygame.mixer.Sound("./fn-percussion.wav")

channels[0].play(melody, loops=-1)
channels[1].play(bass, loops=-1)
channels[2].play(percussion, loops=-1)

channels[1].set_volume(0.5)

while True:
    vol = (math.sin(time.time()) + 1) / 2
    channels[0].set_volume(vol)
    time.sleep(0.01)

This uses 3 loops played simultaneously and simply adjusts the volume of one with a sine wave to simulate how you might start/stop it.

A full example would need some differentiation between loops that play continuously from start-up and stay in sync, and single trigger sounds, but that’s not too tricky.


#4

wow that’s great, i’ll get on this, my students are having a blast with the drum pad so i will try some of your ideas out and see where we go, thx so much!