Using strings as attributes of class - how?

Hi, everyone.

Currently, I have:

inst1 = s2.new_part("Slow Strings")
...
inst1.play_note(root_note, bass_vol, chord_len, blocking=False)

However, what I want to do is this:

inst = ["slow_strings", "french_horns", "strings", "warm_pad", "fantasia", "cello", "synthbass2"]
instruments = sample(inst, k=3)
inst1 = instruments[0]
inst2 = instruments[1]
inst3 = instruments[2]

then make the same call:

inst1.play_note(root_note, bass_vol, chord_len, blocking=False)
inst2.play_note(root_note, bass_vol, chord_len, blocking=False)
inst3.play_note(root_note, bass_vol, chord_len, blocking=False)

But attaching inst1 to .play_note(…) gives an error.

I read something about using setattr (???) but I have no idea.

Can someone please help? Thanks!

David Collett
Seattle

Maybe you want something like this?

instruments = [s2.new_part(name) for name in ["piano", "clarinet", "Slow Strings"]]
inst1 = instruments[0]
inst2 = instruments[1]
inst3 = instruments[2]
inst1.play_note(root_note, bass_vol, chord_len, blocking=False)
inst2.play_note(root_note, bass_vol, chord_len, blocking=False)
inst3.play_note(root_note, bass_vol, chord_len, blocking=False)
1 Like

‘inst1’ is of type string, because it’s drawn from the ‘inst’ list that only contains strings.
Therefore it doesn’t have the method ‘play_note’. You forgot to create a new_part.

Also, you can use a loop to iterate over the sample, instead of using inst1, inst2, inst3.
Make k a parameter of a method and you will have a complete snippet.

1 Like

Thanks for your help, javiruiz and shiihs.

Based on your suggestions, I did it like this, and it works.

Is there a better (easier, more efficient) way for the loop assignment? (I copied that code from a Python article, but I don’t understand how it’s doing its magic.)

from scamp import *
from random import sample

s = Session()

inst = ["slow_strings", "french_horns", "strings", "warm_pad", "space_voice", "fantasia", "voice_oohs", "cello", "synthbass2"]
instruments = sample(inst, k=3)

for i in range(4):
    globals()[f'inst{i}'] = s.new_part(instruments[i-1])
    
inst1.play_note(48, 1, 1, blocking=False)
inst2.play_note(60, 1, 1, blocking=False)
inst3.play_note(72, 1, 1)

Also, how could I print inst1, inst2, and inst3 values using a loop?

Thanks. :grinning:

David

Whoa! Messing with globals()!
Maybe it’s better if you just use a list of instruments. See the example below:

from scamp import Session, wait
from random import sample

session = Session()

instrument_names = ["slow_strings", 
					"french_horns", 
					"strings", 
					"warm_pad", 
					"space_voice", 
					"fantasia", 
					"voice_oohs", 
					"cello", 
					"synthbass2"]

number_of_instruments = 3

sample_instruments = sample(instrument_names, 
							k=number_of_instruments)

instruments =  [] # this list will store the actual Scamp instruments, used for playback

for instrument_name in sample_instruments:
    instruments.append(session.new_part(instrument_name))
 
notes = (48, 60, 72) # number of notes should be equal to number of instruments
volume = [1, 0.5] # simple decrease in volume
duration = 4 # a whole note

assert len(notes) == len(instruments) # sanity check.


for instrument, note in zip(instruments, notes): # zip will take pairs of values from intruments and notes
	instrument.play_note(note, volume, duration, blocking=False)

wait(duration)

You may notice that I don’t import all Scamp namespace and only what I need. This is just a matter of style.