pythonpyo

Running Multiple If-Loops on Python for Music Production?


I'm creating a simple music production program for a final class project in Python and using pyo for the audio integration. My goal is for users to be able to create simple drum patterns that play back at a BPM they choose.

I have created a function called drumMachine() that asks user to input which set of drum sounds they would like to add and on what beats they would like to add it, which then selects the corresponding if-loop for the drum sound and saves the beat placements into a dictionary. Added a piece of the code for reference below.

if drumMachine_userInput == 1: #KICK DRUMS
        #ask for drum beats
    kick_input = input("Which beat(s) do you want to place your kick drums?")
        #split str into list
    kick_list = kick_input.split()
        #convert str list into int list, replacing old list
    kick_list = [int(i) for i in kick_list]
        #add result to dictionary
    instrument_dict['kicks'].append(kick_list)

The program then goes into a While-loop that plays that drum sound at the chosen beat at a chosen BPM by seeing if there are beat placements for drums in the dictionary. Right now to test my program I only implemented the ability to do it on either beat 1, 2, 3, or 4, btw.

   while True:
    counter += 1

    if counter > 4:
        counter = 1
        measureCounter += 1

    if 'kicks' in instrument_dict:
        if counter == 1 in kick_list:
            sf = SfPlayer('kick.wav', speed=1, loop=False).out()
        elif counter == 2 in kick_list:
            sf = SfPlayer('kick.wav', speed=1, loop=False).out()
        elif counter == 3 in kick_list:
            sf = SfPlayer('kick.wav', speed=1, loop=False).out()
        elif counter == 4 in kick_list:
            sf = SfPlayer('kick.wav', speed=1, loop=False).out()

Now, the issue I am having is that I'm not sure what I can do to give the user the ability to add another layer of drums on top of that loop. For example, if the user wants to add snares to beats 2 and 4 on top of the kick drums. I experimented with populating my dictionary entries with different beats, but when I play the sounds, none of the drum sounds play at the same time.

For example, if I said I want kick drums on 1, 2, 3, 4; snares on 2, 4; and claps on only 4, instead of everything playing together, I get: kick, snare, kick, clap instead of kick, kick+ snare, kick, kick+snare+claps.

Is there any way to be able to have multiple if-loops running at the same time? Or is there any other way to be able to code the ability of running multiple drum loops at once that I'm just not seeing? Hope this made sense.

Thanks for everyone's help in advance!


Solution

  • I dug up some wav files and modified my previous answer to create a running sample program:

    from pyo.lib.players import SfPlayer
    from pyo import Server
    from time import sleep
    s = Server().boot()
    s.start()
    instrument_beats =  {
        "kicks": [1,2,3,4],
        "snares": [2,4],
        "claps": [4],
    }
    wave_file = {
        "kicks": "kick.wav",
        "snares": "snare.wav",
        "claps": "clap.wav",
    }
    counter = 0
    measureCounter = 0
    while measureCounter < 5:
        counter += 1
        if counter > 4:
            counter = 1
            measureCounter += 1
        players = []
        for instrument,beats in instrument_beats.items():
            if counter in beats:
                players.append(SfPlayer(wave_file[instrument], speed=1, loop=False).out())
        sleep(0.5) # beat delay