def setup_patch(p): # Take a FM patch and output AMY commands to set up the patch. Send alles.send(vel=0,osc=6,note=50) after # Problem here, pitch values are such that 0 = -n octave, 99 = + n octave # pitch level = 50 means no change (or 1 for us) # can our breakpoints handle negative numbers? alles.reset() print(p["name"]) pitch_rates, pitch_times = p["bp_pitch_rates"], p["bp_pitch_times"] pitchbp = "%d,%f,%d,%f,%d,%f,%d,%f" % ( pitch_times[0], pitch_rates[0], pitch_times[1], pitch_rates[1], pitch_times[2], pitch_rates[2], pitch_times[3], pitch_rates[3] ) # Set up each operator for i,op in enumerate(p["ops"]): freq_ratio = -1 freq = -1 # Set the ratio or the fixed freq if(op.get("fixedhz",None) is not None): freq = op["fixedhz"] else: freq_ratio = op["ratio"] bp_rates, bp_times = op["bp_opamp_rates"], op["bp_opamp_times"] opbp = "%d,%f,%d,%f,%d,%f,%d,%f" % ( bp_times[0], bp_rates[0], bp_times[1], bp_rates[1], bp_times[2], bp_rates[2], bp_times[3], bp_rates[3] ) #print("osc %d (op %d) freq %f ratio %f beta-bp %s pitch-bp %s beta %f detune %d" % (i, (i-6)*-1, freq, freq_ratio, opbp, pitchbp, op["opamp"], op["detunehz"])) if(freq>=0): alles.send(osc=i, freq=freq, ratio=freq_ratio,bp0_target=alles.TARGET_AMP+alles.TARGET_LINEAR,bp0=opbp, bp1=pitchbp, bp1_target=alles.TARGET_FREQ+alles.TARGET_LINEAR, amp=op["opamp"], detune=op["detunehz"]) else: alles.send(osc=i, freq=freq, ratio=freq_ratio,bp0_target=alles.TARGET_AMP+alles.TARGET_LINEAR,bp0=opbp, amp=op["opamp"], detune=op["detunehz"]) # Set up the main carrier note lfo_target = 0 # Choose the bigger one if(p.get("lfoampmoddepth",0) + p.get("lfopitchmoddepth",0) > 0): if(p.get("lfoampmoddepth",0) >= p.get("lfopitchmoddepth",0)): lfo_target=alles.TARGET_AMP lfo_amp = output_level_to_amp(p.get("lfoampmoddepth",0)) else: lfo_target=alles.TARGET_FREQ lfo_amp = output_level_to_amp(p.get("lfopitchmoddepth",0)) if(lfo_target>0): alles.send(osc=7, wave=p["lfowaveform"],freq=p["lfospeed"], amp=lfo_amp) alles.send(osc=6,lfo_target=lfo_target, lfo_source=7) #print("osc 7 lfo wave %d freq %f amp %f target %d" % (p["lfowaveform"],p["lfospeed"], lfo_amp, lfo_target)) print("osc 6 (main) algo %d feedback %f pitchenv %s" % ( p["algo"], p["feedback"], pitchbp)) alles.send(osc=6, wave=alles.ALGO, algorithm=p["algo"], feedback=p["feedback"], algo_source="0,1,2,3,4,5", bp1=pitchbp, bp1_target=alles.TARGET_FREQ+alles.TARGET_LINEAR)
def play(sequence, osc_offset=0, sustain_ms = -1, sustain_len_ms = 0, time_ratio = 1, pitch_ratio = 1, amp_ratio = 1, bw_ratio = 1, round_robin=False): # i take a sequence and play it to AMY, just like native AMY will do from a .h file my_start_time = alles.millis() if(round_robin): next_client = 0 osc_to_client_map = {} print("Syncing mesh....") clients = len(alles.sync()) # After a sync, we don't want to immediately spam the mesh, so let's wait 2000ms time.sleep(2) print("Ready to play among %d speakers" % (clients)) sustain_offset = 0 if(sustain_ms > 0): if(sustain_ms > sequence[-1][0]): print("Moving sustain_ms from %d to %d" % (sustain_ms, sequence[-1][0]-100)) sustain_ms = sequence[-1][0] - 100 for i,s in enumerate(sequence): # Wait for the item in the sequence to be close, so I don't overflow the synthesizers' state while(my_start_time + (s[0] / time_ratio) > (alles.millis() - 500)): time.sleep(0.01) # Make envelope strings bp0 = "%d,%s,0,0" % (s[6] / time_ratio, alles.trunc(s[7])) bp1 = "%d,%s,0,0" % (s[6] / time_ratio, alles.trunc(s[8])) if(bw_ratio > 0): bp2 = "%d,%s,0,0" % (s[6] / time_ratio, alles.trunc(s[9])) else: bp2 = "" if(sustain_ms > 0 and sustain_offset == 0): if(s[0]/time_ratio > sustain_ms/time_ratio): sustain_offset = sustain_len_ms/time_ratio osc = s[1]+osc_offset partial_args = {} if(round_robin): if(osc_to_client_map.get(osc,None) is None): osc_to_client_map[osc] = (next_client % clients) next_client += 1 partial_args["client"] = osc_to_client_map[osc] partial_args.update({"timestamp":my_start_time + (s[0]/time_ratio + sustain_offset), "osc":s[1]+osc_offset, "wave":alles.PARTIAL, "amp":s[3]*amp_ratio, "freq":s[2]*pitch_ratio, "feedback":s[4]*bw_ratio, "bp0":bp0, "bp1":bp1, "bp2":bp2, "bp0_target":alles.TARGET_AMP+alles.TARGET_LINEAR, "bp1_target":alles.TARGET_FREQ+alles.TARGET_LINEAR, "bp2_target":alles.TARGET_FEEDBACK+alles.TARGET_LINEAR}) if(s[5]==-2): #end, add note off alles.send(**partial_args, vel=0) elif(s[5]==-1): # continue alles.send(**partial_args) else: #start, add phase and note on alles.send(**partial_args, vel=s[3]*amp_ratio, phase=s[5]) return sequence[-1][0]/time_ratio
def play_partial_sequence(sequence, amp_mult=1, max_oscs=alles.ALLES_OSCS, show_cpu=False, **kwargs): alles.reset() alles.buffer() (time_ms, partial_idx, bp_idx, freq, amp, bw, phase) = range(7) q = queue.Queue(max_oscs) for i in range(int(max_oscs / 2)): q.put(int(i)) q.put(int(i + alles.ALLES_OSCS / 2)) osc_map = {} start = alles.millis() offset = alles.millis() - sequence[0][time_ms] m = 0 alles.send(debug=2) for event in sequence: event_time_ms = (event[time_ms] + offset) while (event_time_ms - alles.millis() > 1): pass # If this is the start of a partial if (event[phase] > -1): if (not q.empty()): osc_map[event[partial_idx]] = q.get() m = m + 1 alles.note_on(osc=osc_map[event[partial_idx]], wave=alles.SINE, freq=event[freq], phase=event[phase], timestamp=event_time_ms, vel=event[amp] * amp_mult, **kwargs) else: # No oscs available for this partial, so skip it continue else: if (event[partial_idx] in osc_map): # If this is a normal breakpoint if (event[amp] > -1): m = m + 1 alles.send(osc=osc_map[event[partial_idx]], freq=event[freq], amp=event[amp] * amp_mult, timestamp=event_time_ms, **kwargs) else: # partial is over, free the oscillator m = m + 1 alles.send(osc=osc_map[event[partial_idx]], vel=0, timestamp=event_time_ms, **kwargs) q.put(osc_map[event[partial_idx]]) if (alles.millis() - start > 1000): if (show_cpu): alles.send(debug=1) start = alles.millis() print("Voice allocator was able to send %d messages out of %d (%2.2f%%)" % (m, len(sequence), float(m) / len(sequence) * 100.0)) # Wait for the last bits in the latency buffer time.sleep(1) alles.send(debug=1) alles.reset() alles.buffer(size=0)
import alles from time import sleep clients = list(alles.sync().keys()) try: for i in range(400): alles.send(wave=alles.ALGO, note=[[60, 58][(i // 32) % 2], [48, 52][(i // 48) % 2] ][(i // 64) % 2] + [0, 3, 5, 7, 10, 11][i % 6] * 2, vel=0.1 * (i % 9), patch=14 + i % 2, client=clients[i % len(clients)]) sleep([0.08, 0.05, 0.1][i % 3] * (i % 3)) except KeyboardInterrupt: pass alles.reset()
def dir_drums(bpm=120, loops=-1, **kwargs): alles.preset(13, osc=0, **kwargs) # sample bass drum alles.preset(8, osc=3, **kwargs) # sample hat alles.preset(9, osc=4, **kwargs) # sample cow alles.preset(10, osc=5, **kwargs) # sample hi cow alles.preset(11, osc=2, **kwargs) # sample snare alles.preset(1, osc=7, **kwargs) # filter bass [bass, snare, hat, cow, hicow, silent] = [1, 2, 4, 8, 16, 32] pattern = [ bass + hat, hat + hicow, bass + hat + snare, hat + cow, hat, hat + bass, snare + hat, hat ] basslines = [[50, 0, 0, 0, 50, 52, 51, 0], [56, 0, 0, 0, 56, 58, 57, 0], [57, 0, 0, 0, 57, 59, 58, 0], [50, 50, 50, 50, 50, 50, 0, 50], [58, 58, 58, 58, 58, 58, 0, 58]] next_sleepytime_in = 4 while (loops != 0): loops = loops - 1 random.shuffle(pattern) bassline = random.choice(basslines) sleepytime = 1.0 / (bpm * 2.0 / 60) for i, x in enumerate(pattern): if (x & bass): alles.send(osc=0, vel=4, **kwargs) if (x & snare): alles.send(osc=2, vel=1.5) if (x & hat): alles.send(osc=3, vel=1) if (x & cow): alles.send(osc=4, vel=1) if (x & hicow): alles.send(osc=5, vel=1) if (bassline[i] > 0): alles.send(osc=7, vel=0.5, note=bassline[i] - 12, **kwargs) else: alles.send(vel=0, osc=7, **kwargs) if (next_sleepytime_in == 0): sleepytime_multi = random.choice([[1.0, 8], [0.5, 4], [0.333, 3], [0.25, 4]]) sleepytime *= sleepytime_multi[0] next_sleepytime_in = sleepytime_multi[1] next_sleepytime_in -= 1 time.sleep(sleepytime)
def play(patch): alles.reset() setup_patch(decode_patch(get_patch(patch))) alles.send(osc=6,vel=1,note=40,bp0_target=alles.TARGET_AMP,bp0="0,1,500,0,500,0") time.sleep(0.5) alles.send(osc=6,vel=0) time.sleep(0.5) alles.send(osc=6,vel=1,note=50) time.sleep(0.5) alles.send(osc=6,vel=1,note=51) time.sleep(0.5) alles.send(osc=6,vel=1,note=52) time.sleep(0.5) alles.send(osc=6,vel=1,note=40,bp0_target=alles.TARGET_AMP,bp0="0,1,100,0,0,0") time.sleep(0.25) alles.send(osc=6,vel=0)