How to fork in this situation?

from scamp import *

s = Session()
s.tempo = 65

# user input instrument and its information format dict
instrument_and_infor_dict = {"guitar": [[45, 52, 59, 57, 60], [0.9, 0.6, 0.8, 0.5, 0.8], 0.5],
                             "piano": [[45, 52, 59, 57, 60], [0.9, 0.6, 0.8, 0.5, 0.8], 0.5]}

instrument_objects = []  # list to collect instrument_object that created by creat_instrument_object_from_dict for fork function
play = []  # collect soundtrack to fork


# the next step


def creat_instrument_object_from_dict(instrument_and_infor_dict):
    for instruments, instruments_info in instrument_and_infor_dict.items():
        instrument_name = []
        instrument_name.append(instruments)
        # get the name of the instrument and use it to create a instrument object
        for i in range(len(instrument_name)):
            instru = instrument_name[i]
            print(instru)
            instru = s.new_part(instru)
            instrument_objects.append(instru)


def play_instruments(instrument_and_infor_dict):
    # get the information of the instrument and use the play method to play it
    for instruments, instruments_info in instrument_and_infor_dict.items():
        pitchs = instruments_info[0]
        volumes = instruments_info[1]
        note_length = instruments_info[2]

    for i in range(len(instrument_objects)):
        for p, v in zip(pitchs, volumes):
            # I define a instrument play notes as a soundtrack and collect it into play for the next :fork
            soundtrack = instrument_objects[i].play_note(p, v, note_length)
            play.append(soundtrack)


creat_instrument_object_from_dict(instrument_and_infor_dict)
play_instruments(instrument_and_infor_dict)
# to here everything is fine, but if I intend to fork the soundtracks in play it goes wrong,what should I do to fork the
# soundtrack in the play to make them sound at the same time.
for i in range(len(play)):
    s.fork(play[i])

I stuck here for hours ,I got no clue, can you help me?

Hi @yison ,
I reworked your code a bit. I hope this is what you were after.
If I understand correctly, s.fork() is for forking functions so you need to build a function that will take scamp instruments and note information as arguments.

So, typically I make some type of play_notes function that takes an_instrument_list and note_data_list as arguments and then does the playing within the function.

So it would look like

s.fork(play_notes, (an_instrument_list, note_data_list))

When using forks, important to add s.wait_for_children_to_finish() at the end so that the script waits until all of the forks end before finishing.

Neil

from scamp import *

s = Session()
s.tempo = 65

# user input instrument and its information format dict
info = [[[45, 52, 59, 57, 60], [0.9, 0.6, 0.8, 0.5, 0.8], 0.5],
        [[45, 52, 59, 57, 60], [0.9, 0.6, 0.8, 0.5, 0.8], 0.5]]

instrument_names = ['guitar', 'piano']

instruments = []
for inst in instrument_names:
    x = s.new_part(inst)
    instruments.append(x)

print('instruments:', instruments)

def instrument_player(instrument, info):
    print('instrument:', instrument)
    pitches = info[0]
    volumes = info[1]
    note_length = info[2]
    iter_list = list(zip(pitches, volumes))
    print('iter_list:', iter_list)
    for p, v in iter_list:
        print('p, v', p, v)
        instrument.play_note(p, v, note_length)


for instrument, inf in zip(instruments, info):
    print(inf)
    print(instrument)
    s.fork(instrument_player, (instrument, inf))

s.wait_for_children_to_finish()
2 Likes

Thanks for chiming in, Neil! Nice explanation of how to approach fork in these kinds of situations

that’s really helpful, Thank you. you make things easier.

I got confused here, the result seemd to be [[45, 52, 59, 57, 60], [0.9, 0.6, 0.8, 0.5, 0.8], 0.5], but when you print the result is [45, 52, 59, 57, 60], why was that?

There’s a little confusion there, since the variable name info is being used in multiple places for different things, and sometimes the local name masks the global name. If you change a few variable names, it’s maybe a little clearer:

from scamp import *

s = Session()
s.tempo = 65

# user input instrument and its information format dict
all_parts_info = [
    [[45, 52, 59, 57, 60], [0.9, 0.6, 0.8, 0.5, 0.8], 0.5],
    [[49, 52, 59, 57, 62], [0.9, 0.6, 0.8, 0.5, 0.8], 0.5]
]

instrument_names = ['guitar', 'piano']

instruments = []
for inst in instrument_names:
    x = s.new_part(inst)
    instruments.append(x)

print('instruments:', instruments)

def instrument_player(instrument, part_info):
    print('instrument:', instrument)
    pitches = part_info[0]
    volumes = part_info[1]
    note_length = part_info[2]
    iter_list = list(zip(pitches, volumes))
    print('iter_list:', iter_list)
    for p, v in iter_list:
        print('p, v', p, v)
        instrument.play_note(p, v, note_length)


for instrument, this_part_info in zip(instruments, all_parts_info):
    print(this_part_info)
    print(instrument)
    s.fork(instrument_player, (instrument, this_part_info))

s.wait_for_children_to_finish()

Thank you for your explaination. That’s helpful.

good fix - a bad habit I still have to break :slight_smile:

Very easy habit to fall into! Coming up with names is hard.