def _start(): '''Start the module This uses the global variables from setup and adds a set of global variables ''' global parser, args, config, r, response, patch, name global monitor, debug, mididevice, output_scale, output_offset, port, inputport # this can be used to show parameters that have changed monitor = EEGsynth.monitor(name=name, debug=patch.getint('general', 'debug')) # get the options from the configuration file debug = patch.getint('general', 'debug') mididevice = patch.getstring('midi', 'device') mididevice = EEGsynth.trimquotes(mididevice) # the scale and offset are used to map MIDI values to Redis values output_scale = patch.getfloat('output', 'scale', default=1. / 127) # MIDI values are from 0 to 127 output_offset = patch.getfloat('output', 'offset', default=0.) # MIDI values are from 0 to 127 # this is only for debugging, check which MIDI devices are accessible monitor.info('------ INPUT ------') for port in mido.get_input_names(): monitor.info(port) monitor.info('-------------------------') try: inputport = mido.open_input(mididevice) monitor.success('Connected to MIDI input') except: raise RuntimeError("Cannot connect to MIDI input") # there should not be any local variables in this function, they should all be global if len(locals()): print('LOCALS: ' + ', '.join(locals().keys()))
def _start(): """Start the module This uses the global variables from setup and adds a set of global variables """ global parser, args, config, r, response, patch, name global monitor, debug, mididevice, outputport, lock, trigger, port, channel, previous_val, previous_port_val # this can be used to show parameters that have changed monitor = EEGsynth.monitor(name=name, debug=patch.getint('general', 'debug')) # get the options from the configuration file debug = patch.getint('general', 'debug') mididevice = patch.getstring('midi', 'device') mididevice = EEGsynth.trimquotes(mididevice) mididevice = process.extractOne(mididevice, mido.get_output_names())[0] # select the closest match # this is only for debugging, check which MIDI devices are accessible monitor.info('------ OUTPUT ------') for port in mido.get_output_names(): monitor.info(port) monitor.info('-------------------------') try: outputport = mido.open_output(mididevice) monitor.success('Connected to MIDI output') except: raise RuntimeError("cannot connect to MIDI output") # this is to prevent two messages from being sent at the same time lock = threading.Lock() # each of the gates that can be triggered is mapped onto a different message trigger = [] for channel in range(0, 16): # channels are one-offset in the ini file, zero-offset in the code name = 'channel{}'.format(channel + 1) if config.has_option('gate', name): # start the background thread that deals with this channel this = TriggerThread(patch.getstring('gate', name), channel) trigger.append(this) monitor.debug(name + ' trigger configured') # start the thread for each of the notes for thread in trigger: thread.start() # control values are only relevant when different from the previous value previous_val = {} previous_port_val = {} for channel in range(0, 16): name = 'channel{}'.format(channel + 1) previous_val[name] = None previous_port_val[name] = None # there should not be any local variables in this function, they should all be global if len(locals()): print("LOCALS: " + ", ".join(locals().keys()))
def _start(): '''Start the module This uses the global variables from setup and adds a set of global variables ''' global parser, args, config, r, response, patch global monitor, duration_scale, duration_offset, serialdevice, s, lock, trigger, chanindx, chanstr, redischannel, thread # this can be used to show parameters that have changed monitor = EEGsynth.monitor(name=name, debug=patch.getint('general', 'debug')) # values between 0 and 1 work well for the duration duration_scale = patch.getfloat('duration', 'scale', default=1) duration_offset = patch.getfloat('duration', 'offset', default=0) # get the specified serial device, or the one that is the closest match serialdevice = patch.getstring('serial', 'device') serialdevice = EEGsynth.trimquotes(serialdevice) serialdevice = process.extractOne( serialdevice, [comport.device for comport in serial.tools.list_ports.comports() ])[0] # select the closest match try: s = serial.Serial(serialdevice, patch.getint('serial', 'baudrate'), timeout=3.0) monitor.success("Connected to serial port") except: raise RuntimeError("cannot connect to serial port") # this is to prevent two triggers from being activated at the same time lock = threading.Lock() trigger = [] # configure the trigger threads for the control voltages for chanindx in range(1, 5): chanstr = "cv%d" % chanindx if patch.hasitem('trigger', chanstr): redischannel = patch.getstring('trigger', chanstr) trigger.append(TriggerThread(redischannel, chanindx, chanstr)) monitor.info("configured", redischannel, "on", chanindx) # configure the trigger threads for the gates for chanindx in range(1, 5): chanstr = "gate%d" % chanindx if patch.hasitem('trigger', chanstr): redischannel = patch.getstring('trigger', chanstr) trigger.append(TriggerThread(redischannel, chanindx, chanstr)) monitor.info("configured", redischannel, "on", chanindx) # start the thread for each of the triggers for thread in trigger: thread.start() # there should not be any local variables in this function, they should all be global if len(locals()): print('LOCALS: ' + ', '.join(locals().keys()))
def _start(): '''Start the module This uses the global variables from setup and adds a set of global variables ''' global parser, args, config, r, response, patch, name global monitor, debug, serialdevice, s, dmxsize, chanlist, chanvals, chanindx, chanstr, dmxframe, prevtime, START_VAL, END_VAL, TX_DMX_PACKET, FRAME_PAD # this can be used to show parameters that have changed monitor = EEGsynth.monitor(name=name, debug=patch.getint('general', 'debug')) # get the options from the configuration file debug = patch.getint('general', 'debug') # get the specified serial device, or the one that is the closest match serialdevice = patch.getstring('serial', 'device') serialdevice = EEGsynth.trimquotes(serialdevice) serialdevice = process.extractOne( serialdevice, [comport.device for comport in serial.tools.list_ports.comports() ])[0] # select the closest match try: s = serial.Serial(serialdevice, patch.getint('serial', 'baudrate'), timeout=3.0) monitor.info("Connected to serial port") except: raise RuntimeError("cannot connect to serial port") # determine the size of the universe dmxsize = 0 chanlist, chanvals = list(map(list, list(zip(*config.items('input'))))) for chanindx in range(0, 512): chanstr = "channel%03d" % (chanindx + 1) if chanstr in chanlist: # the last channel determines the size dmxsize = chanindx + 1 # my fixture won't work if the frame size is too small dmxsize = max(dmxsize, 16) monitor.info("universe size = %d" % dmxsize) # make an empty frame dmxframe = [0] * dmxsize # blank out sendframe(s, dmxframe) # keep a timer to send a packet every now and then prevtime = time.time() # there should not be any local variables in this function, they should all be global if len(locals()): print('LOCALS: ' + ', '.join(locals().keys()))
def _start(): '''Start the module This uses the global variables from setup and adds a set of global variables ''' global parser, args, config, r, response, patch, name global monitor, control_name, control_code, note_name, note_code, debug, port, midichannel, mididevice, outputport, scale, offset, lock, trigger, code, this, thread, previous_val # this can be used to show parameters that have changed monitor = EEGsynth.monitor(name=name, debug=patch.getint('general', 'debug')) # the list of MIDI commands is the only aspect that is specific to the Volca Keys # see http://media.aadl.org/files/catalog_guides/1444140_chart.pdf control_name = [ 'portamento', 'expression', 'voice', 'octave', 'detune', 'vco_eg_int', 'vcf_cutoff', 'vcf_eg_int', 'lfo_rate', 'lfo_pitch_int', 'lfo_cutoff_int', 'eg_attack', 'eg_decay_release', 'eg_sustain', 'delay_time', 'delay_feedback' ] control_code = [ 5, 11, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 ] note_name = [ 'C0', 'Db0', 'D0', 'Eb0', 'E0', 'F0', 'Gb0', 'G0', 'Ab0', 'A0', 'Bb0', 'B0', 'C1', 'Db1', 'D1', 'Eb1', 'E1', 'F1', 'Gb1', 'G1', 'Ab1', 'A1', 'Bb1', 'B1', 'C2', 'Db2', 'D2', 'Eb2', 'E2', 'F2', 'Gb2', 'G2', 'Ab2', 'A2', 'Bb2', 'B2', 'C3', 'Db3', 'D3', 'Eb3', 'E3', 'F3', 'Gb3', 'G3', 'Ab3', 'A3', 'Bb3', 'B3', 'C4', 'Db4', 'D4', 'Eb4', 'E4', 'F4', 'Gb4', 'G4', 'Ab4', 'A4', 'Bb4', 'B4', 'C5', 'Db5', 'D5', 'Eb5', 'E5', 'F5', 'Gb5', 'G5', 'Ab5', 'A5', 'Bb5', 'B5', 'C6', 'Db6', 'D6', 'Eb6', 'E6', 'F6', 'Gb6', 'G6', 'Ab6', 'A6', 'Bb6', 'B6', 'C7', 'Db7', 'D7', 'Eb7', 'E7', 'F7', 'Gb7', 'G7', 'Ab7', 'A7', 'Bb7', 'B7', 'C8', 'Db8', 'D8', 'Eb8', 'E8', 'F8', 'Gb8', 'G8', 'Ab8', 'A8', 'Bb8', 'B8', 'C9', 'Db9', 'D9', 'Eb9', 'E9', 'F9', 'Gb9', 'G9', 'Ab9', 'A9', 'Bb9', 'B9', 'C10', 'Db10', 'D10', 'Eb10', 'E10', 'F10', 'Gb10', 'G10', 'Ab10', 'A10', 'Bb10', 'B10' ] note_code = [ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143 ] # get the options from the configuration file debug = patch.getint('general', 'debug') # this is only for debugging, check which MIDI devices are accessible monitor.info('------ OUTPUT ------') for port in mido.get_output_names(): monitor.info(port) monitor.info('-------------------------') midichannel = patch.getint( 'midi', 'channel') - 1 # channel 1-16 get mapped to 0-15 mididevice = patch.getstring('midi', 'device') mididevice = EEGsynth.trimquotes(mididevice) mididevice = process.extractOne( mididevice, mido.get_output_names())[0] # select the closest match try: outputport = mido.open_output(mididevice) monitor.success('Connected to MIDI output') except: raise RuntimeError("cannot connect to MIDI output") # the scale and offset are used to map Redis values to MIDI values scale = patch.getfloat('input', 'scale', default=127) offset = patch.getfloat('input', 'offset', default=0) # this is to prevent two messages from being sent at the same time lock = threading.Lock() # each of the notes that can be played is mapped onto a different trigger trigger = [] for name, code in zip(note_name, note_code): if config.has_option('note', name): # start the background thread that deals with this note this = TriggerThread(patch.getstring('note', name), code) trigger.append(this) monitor.debug(name + ' trigger configured') # start the thread for each of the notes for thread in trigger: thread.start() # control values are only relevant when different from the previous value previous_val = {} for name in control_name: previous_val[name] = None # there should not be any local variables in this function, they should all be global if len(locals()): print('LOCALS: ' + ', '.join(locals().keys()))
# combine the patching from the configuration file and Redis patch = EEGsynth.patch(config, r) del config # this determines how much debugging information gets printed debug = patch.getint('general', 'debug') # this is only for debugging print('------ INPUT ------') for port in mido.get_input_names(): print(port) print('-------------------------') mididevice = patch.getstring('midi', 'device') mididevice = EEGsynth.trimquotes(mididevice) try: inputport = mido.open_input(mididevice) if debug > 0: print("Connected to MIDI input") except: print("Error: cannot connect to MIDI input") exit() # the scale and offset are used to map MIDI values to Redis values scale = patch.getfloat('output', 'scale', default=127) offset = patch.getfloat('output', 'offset', default=0) while True: time.sleep(patch.getfloat('general', 'delay'))
def _start(): '''Start the module This uses the global variables from setup and adds a set of global variables ''' global parser, args, config, r, response, patch, name global monitor, push, toggle1, toggle2, toggle3, toggle4, slap, scale_note, scale_control, offset_note, offset_control, mididevice_input, mididevice_output, port, inputport, Off, Red_Low, Red_Full, Amber_Low, Amber_Full, Yellow_Full, Green_Low, Green_Full, ledcolor, note_list, status_list, note, state0change, state0color, state0value, state1change, state1color, state1value, state2change, state2color, state2value, state3change, state3color, state3value, state4change, state4color, state4value, state5change, state5color, state5value, midichannel, outputport # this can be used to show parameters that have changed monitor = EEGsynth.monitor(name=name, debug=patch.getint('general', 'debug')) # get the options from the configuration file push = patch.getint('button', 'push', multiple=True) # push-release button toggle1 = patch.getint('button', 'toggle1', multiple=True) # on-off button toggle2 = patch.getint('button', 'toggle2', multiple=True) # on1-on2-off button toggle3 = patch.getint('button', 'toggle3', multiple=True) # on1-on2-on3-off button toggle4 = patch.getint('button', 'toggle4', multiple=True) # on1-on2-on3-on4-off button slap = patch.getint('button', 'slap', multiple=True) # slap button midichannel = patch.getint('midi', 'channel', default=None) # the scale and offset are used to map MIDI values to Redis values scale_note = patch.getfloat('scale', 'note', default=1. / 127) scale_control = patch.getfloat('scale', 'control', default=1. / 127) offset_note = patch.getfloat('offset', 'note', default=0) offset_control = patch.getfloat('offset', 'control', default=0) # on windows the input and output are different, on unix they are the same # use "input/output" when specified, otherwise use "device" for both try: mididevice_input = patch.getstring('midi', 'input') mididevice_input = EEGsynth.trimquotes(mididevice_input) except: mididevice_input = patch.getstring('midi', 'device') # fallback mididevice_input = EEGsynth.trimquotes(mididevice_input) try: mididevice_output = patch.getstring('midi', 'output') mididevice_output = EEGsynth.trimquotes(mididevice_output) except: mididevice_output = patch.getstring('midi', 'device') # fallback mididevice_output = EEGsynth.trimquotes(mididevice_output) mididevice_input = process.extractOne( mididevice_input, mido.get_input_names())[0] # select the closest match mididevice_output = process.extractOne( mididevice_output, mido.get_output_names())[0] # select the closest match # this is only for debugging, check which MIDI devices are accessible monitor.info('------ INPUT ------') for port in mido.get_input_names(): monitor.info(port) monitor.info('------ OUTPUT ------') for port in mido.get_output_names(): monitor.info(port) monitor.info('-------------------------') try: inputport = mido.open_input(mididevice_input) monitor.info("Connected to MIDI input") except: raise RuntimeError("cannot connect to MIDI input") try: outputport = mido.open_output(mididevice_output) monitor.info("Connected to MIDI output") except: raise RuntimeError("cannot connect to MIDI output") # channel 1-16 in the ini file should be mapped to 0-15 if not midichannel is None: midichannel -= 1 monitor.update('midichannel', midichannel) # these are the MIDI values for the LED color Off = 12 Red_Low = 13 Red_Full = 15 Amber_Low = 29 Amber_Full = 63 Yellow_Full = 62 Green_Low = 28 Green_Full = 60 # concatenate all buttons note_list = push + toggle1 + toggle2 + toggle3 + toggle4 + slap status_list = [0] * len(note_list) # ensure that all buttons and published messages start in the Off state for note in note_list: ledcolor(note, Off) # the button handling is implemented using an internal representation and state changes # whenever the actual button is pressed or released # push button sequence P-R results in state change 0-1-0 # toggle1 button sequence P-R-P-R results in state change 0-11-12-13-0 # toggle2 button sequence P-R-P-R-P-R results in state change 0-21-22-23-24-25-0 # toggle3 button sequence P-R-P-R-P-R-P-R results in state change 0-31-32-33-34-35-36-37-0 # toggle4 button sequence P-R-P-R-P-R-P-R-P-R results in state change 0-41-42-43-44-45-46-47-48-49-0 # slap button sequence P-R results in state change 0-51-0 state0change = {0: 1, 1: 0} state0color = {0: Off, 1: Red_Full} state0value = {0: 0, 1: 127} state1change = {0: 11, 11: 12, 12: 13, 13: 0} state1color = {0: Off, 11: Red_Full} # don't change color on 12,13 state1value = {0: 0, 11: 127} # don't send message on 12,13 state2change = {0: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 0} state2color = { 0: Off, 21: Red_Full, 23: Yellow_Full } # don't change color on 22,24,25 state2value = { 0: 0, 21: int(127 * 1 / 2), 23: int(127 * 2 / 2) } # don't send message on 22,24,25 state3change = { 0: 31, 31: 32, 32: 33, 33: 34, 34: 35, 35: 36, 36: 37, 37: 0 } state3color = {0: Off, 31: Red_Full, 33: Yellow_Full, 35: Green_Full} state3value = { 0: 0, 31: int(127 * 1 / 3), 33: int(127 * 2 / 3), 35: int(127 * 3 / 3) } state4change = { 0: 41, 41: 42, 42: 43, 43: 44, 44: 45, 45: 46, 46: 47, 47: 48, 48: 49, 49: 0 } state4color = { 0: Off, 41: Red_Full, 43: Yellow_Full, 45: Green_Full, 47: Amber_Full } state4value = { 0: 0, 41: int(127 * 1 / 4), 43: int(127 * 2 / 4), 45: int(127 * 3 / 4), 47: int(127 * 4 / 4) } state5change = {0: 1, 1: 0} state5color = {0: Off, 1: Amber_Full} state5value = {0: None, 1: 127} # don't send message on button release # there should not be any local variables in this function, they should all be global if len(locals()): print('LOCALS: ' + ', '.join(locals().keys()))
response = r.client_list() except redis.ConnectionError: raise RuntimeError("cannot connect to Redis server") # combine the patching from the configuration file and Redis patch = EEGsynth.patch(config, r) # this can be used to show parameters that have changed monitor = EEGsynth.monitor(name=name, debug=patch.getint('general','debug')) # get the options from the configuration file debug = patch.getint('general', 'debug') # get the specified serial device, or the one that is the closest match serialdevice = patch.getstring('serial', 'device') serialdevice = EEGsynth.trimquotes(serialdevice) serialdevice = process.extractOne(serialdevice, [comport.device for comport in serial.tools.list_ports.comports()])[0] # select the closest match try: s = serial.Serial(serialdevice, patch.getint('serial', 'baudrate'), timeout=3.0) monitor.info("Connected to serial port") except: raise RuntimeError("cannot connect to serial port") # determine the size of the universe dmxsize = 0 chanlist, chanvals = list(map(list, list(zip(*config.items('input'))))) for chanindx in range(0, 512): chanstr = "channel%03d" % (chanindx + 1) if chanstr in chanlist: # the last channel determines the size
def _start(): '''Start the module This uses the global variables from setup and adds a set of global variables ''' global parser, args, config, r, response, patch, name global monitor, note_name, note_code, debug, midichannel, mididevice, input_scale, input_offset, scale_velocity, scale_pitch, scale_duration, offset_velocity, offset_pitch, offset_duration, output_scale, output_offset, port, inputport, outputport, lock, trigger, code, onset, velocity, pitch, duration, thread # this can be used to show parameters that have changed monitor = EEGsynth.monitor(name=name, debug=patch.getint('general', 'debug')) # the list of MIDI commands is specific to the implementation for a full-scale keyboard # see https://newt.phys.unsw.edu.au/jw/notes.html note_name = ['C0', 'Db0', 'D0', 'Eb0', 'E0', 'F0', 'Gb0', 'G0', 'Ab0', 'A0', 'Bb0', 'B0', 'C1', 'Db1', 'D1', 'Eb1', 'E1', 'F1', 'Gb1', 'G1', 'Ab1', 'A1', 'Bb1', 'B1', 'C2', 'Db2', 'D2', 'Eb2', 'E2', 'F2', 'Gb2', 'G2', 'Ab2', 'A2', 'Bb2', 'B2', 'C3', 'Db3', 'D3', 'Eb3', 'E3', 'F3', 'Gb3', 'G3', 'Ab3', 'A3', 'Bb3', 'B3', 'C4', 'Db4', 'D4', 'Eb4', 'E4', 'F4', 'Gb4', 'G4', 'Ab4', 'A4', 'Bb4', 'B4', 'C5', 'Db5', 'D5', 'Eb5', 'E5', 'F5', 'Gb5', 'G5', 'Ab5', 'A5', 'Bb5', 'B5', 'C6', 'Db6', 'D6', 'Eb6', 'E6', 'F6', 'Gb6', 'G6', 'Ab6', 'A6', 'Bb6', 'B6', 'C7', 'Db7', 'D7', 'Eb7', 'E7', 'F7', 'Gb7', 'G7', 'Ab7', 'A7', 'Bb7', 'B7', 'C8', 'Db8', 'D8', 'Eb8', 'E8', 'F8', 'Gb8', 'G8', 'Ab8', 'A8', 'Bb8', 'B8', 'C9', 'Db9', 'D9', 'Eb9', 'E9', 'F9', 'Gb9', 'G9', 'Ab9', 'A9', 'Bb9', 'B9', 'C10', 'Db10', 'D10', 'Eb10', 'E10', 'F10', 'Gb10', 'G10', 'Ab10', 'A10', 'Bb10', 'B10'] note_code = [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143] # get the options from the configuration file debug = patch.getint('general', 'debug') midichannel = patch.getint('midi', 'channel', default=None) mididevice = patch.getstring('midi', 'device') mididevice = EEGsynth.trimquotes(mididevice) mididevice = process.extractOne(mididevice, mido.get_input_names())[0] # select the closest match # the input scale and offset are used to map Redis values to MIDI values input_scale = patch.getfloat('input', 'scale', default=127) input_offset = patch.getfloat('input', 'offset', default=0) scale_velocity = patch.getfloat('scale', 'velocity', default=127) scale_pitch = patch.getfloat('scale', 'pitch', default=127) scale_duration = patch.getfloat('scale', 'duration', default=2.0) offset_velocity = patch.getfloat('offset', 'velocity', default=0) offset_pitch = patch.getfloat('offset', 'pitch', default=0) offset_duration = patch.getfloat('offset', 'duration', default=0) # the output scale and offset are used to map MIDI values to Redis values output_scale = patch.getfloat('output', 'scale', default=1. / 127) output_offset = patch.getfloat('output', 'offset', default=0) # this is only for debugging, check which MIDI devices are accessible monitor.info('------ INPUT ------') for port in mido.get_input_names(): monitor.info(port) monitor.info('------ OUTPUT ------') for port in mido.get_output_names(): monitor.info(port) monitor.info('-------------------------') try: inputport = mido.open_input(mididevice) monitor.success('Connected to MIDI input') except: raise RuntimeError("cannot connect to MIDI input") try: outputport = mido.open_output(mididevice) monitor.success('Connected to MIDI output') except: raise RuntimeError("cannot connect to MIDI output") # channel 1-16 in the ini file should be mapped to 0-15 if not midichannel is None: midichannel -= 1 monitor.update('midichannel', midichannel) # this is to prevent two messages from being sent at the same time lock = threading.Lock() # the keyboard notes can be linked to separate triggers, where the trigger value corresponds to the velocity trigger = [] for name, code in zip(note_name, note_code): if config.has_option('input', name): # start the background thread that deals with this note onset = patch.getstring('input', name) velocity = None # use the value of the onset trigger pitch = code duration = None trigger.append(TriggerThread(onset, velocity, pitch, duration)) monitor.debug(name + ' = OK') try: # the keyboard notes can also be controlled using a single trigger onset = patch.getstring('input', 'onset') velocity = patch.getstring('input', 'velocity') pitch = patch.getstring('input', 'pitch') duration = patch.getstring('input', 'duration') trigger.append(TriggerThread(onset, velocity, pitch, duration)) monitor.debug('onset, velocity, pitch and duration OK') except: pass # start the thread for each of the notes for thread in trigger: thread.start() # there should not be any local variables in this function, they should all be global if len(locals()): print('LOCALS: ' + ', '.join(locals().keys()))
def _loop_once(): """Run the main loop once This uses the global variables from setup and start, and adds a set of global variables """ global parser, args, config, r, response, patch global monitor, stepsize, scale_rate, offset_rate, scale_shift, offset_shift, scale_ppqn, offset_ppqn, lock, clock, i, clockthread, midithread, redisthread, midiport, previous_midi_play, previous_midi_start, previous_redis_play global start, redis_play, midi_play, midi_start, rate, shift, ppqn, elapsed, naptime redis_play = patch.getint('redis', 'play') midi_play = patch.getint('midi', 'play') midi_start = patch.getint('midi', 'start') if previous_redis_play is None and redis_play is not None: previous_redis_play = not (redis_play) if previous_midi_play is None and midi_play is not None: previous_midi_play = not (midi_play) if previous_midi_start is None and midi_start is not None: previous_midi_start = not (midi_start) # the MIDI port should only be opened once, and only if needed if midi_play and midiport == None: mididevice = patch.getstring('midi', 'device') mididevice = EEGsynth.trimquotes(mididevice) mididevice = process.extractOne( mididevice, mido.get_output_names())[0] # select the closest match try: outputport = mido.open_output(mididevice) monitor.success('Connected to MIDI output') except: raise RuntimeError("cannot connect to MIDI output") # do something whenever the value changes if redis_play and not previous_redis_play: redisthread.setEnabled(True) previous_redis_play = True elif not redis_play and previous_redis_play: redisthread.setEnabled(False) previous_redis_play = False # do something whenever the value changes if midi_play and not previous_midi_play: midithread.setEnabled(True) previous_midi_play = True elif not midi_play and previous_midi_play: midithread.setEnabled(False) previous_midi_play = False # do something whenever the value changes if midi_start and not previous_midi_start: if midiport != None: midiport.send(mido.Message('start')) previous_midi_start = True elif not midi_start and previous_midi_start: if midiport != None: midiport.send(mido.Message('stop')) previous_midi_start = False rate = patch.getfloat('input', 'rate', default=0) rate = EEGsynth.rescale(rate, slope=scale_rate, offset=offset_rate) rate = EEGsynth.limit(rate, 30., 240.) shift = patch.getfloat('input', 'shift', default=0) shift = EEGsynth.rescale(shift, slope=scale_shift, offset=offset_shift) shift = int(shift) ppqn = patch.getfloat('input', 'ppqn', default=0) ppqn = EEGsynth.rescale(ppqn, slope=scale_ppqn, offset=offset_ppqn) ppqn = find_nearest_value([1, 2, 3, 4, 6, 8, 12, 24], ppqn) # show the parameters whose value has changed monitor.update("redis_play", redis_play) monitor.update("midi_play", midi_play) monitor.update("midi_start", midi_start) monitor.update("rate", rate) monitor.update("shift", shift) monitor.update("ppqn", ppqn) # update the clock and redis clockthread.setRate(rate) redisthread.setShift(shift) redisthread.setPpqn(ppqn) # there should not be any local variables in this function, they should all be global if len(locals()): print("LOCALS: " + ", ".join(locals().keys()))
offset_control = patch.getfloat('offset', 'control', default=0) # this is only for debugging, check which MIDI devices are accessible print('------ INPUT ------') for port in mido.get_input_names(): print(port) print('------ OUTPUT ------') for port in mido.get_output_names(): print(port) print('-------------------------') # on windows the input and output are different, on unix they are the same # use "input/output" when specified, or otherwise use "device" for both try: mididevice_input = patch.getstring('midi', 'input') mididevice_input = EEGsynth.trimquotes(mididevice_input) except: mididevice_input = patch.getstring('midi', 'device') # fallback mididevice_input = EEGsynth.trimquotes(mididevice_input) try: mididevice_output = patch.getstring('midi', 'output') mididevice_output = EEGsynth.trimquotes(mididevice_output) except: mididevice_output = patch.getstring('midi', 'device') # fallback mididevice_output = EEGsynth.trimquotes(mididevice_output) mididevice_input = process.extractOne( mididevice_input, mido.get_input_names())[0] # select the closest match mididevice_output = process.extractOne( mididevice_output, mido.get_output_names())[0] # select the closest match
def _start(): '''Start the module This uses the global variables from setup and adds a set of global variables ''' global parser, args, config, r, response, patch, name global debug, mididevice, port, previous_note, trigger_name, trigger_code, code, trigger, this, thread, control_name, control_code, previous_val, duration_note, lock, midichannel, monitor, monophonic, offset_duration, offset_velocity, outputport, scale_duration, scale_velocity, velocity_note # this can be used to show parameters that have changed monitor = EEGsynth.monitor(name=name, debug=patch.getint('general', 'debug')) # get the options from the configuration file debug = patch.getint('general', 'debug') monophonic = patch.getint('general', 'monophonic', default=1) midichannel = patch.getint( 'midi', 'channel') - 1 # channel 1-16 get mapped to 0-15 mididevice = patch.getstring('midi', 'device') mididevice = EEGsynth.trimquotes(mididevice) mididevice = process.extractOne( mididevice, mido.get_output_names())[0] # select the closest match # values between 0 and 1 work well for the note duration scale_duration = patch.getfloat('scale', 'duration', default=1) offset_duration = patch.getfloat('offset', 'duration', default=0) # values around 64 work well for the note velocity scale_velocity = patch.getfloat('scale', 'velocity', default=1) offset_velocity = patch.getfloat('offset', 'velocity', default=0) # this is only for debugging, and to check which MIDI devices are accessible monitor.info('------ INPUT ------') for port in mido.get_input_names(): monitor.info(port) monitor.info('------ OUTPUT ------') for port in mido.get_output_names(): monitor.info(port) monitor.info('-------------------------') try: outputport = mido.open_output(mididevice) monitor.success('Connected to MIDI output') except: raise RuntimeError("cannot connect to MIDI output") # this is to prevent two messages from being sent at the same time lock = threading.Lock() previous_note = None velocity_note = None duration_note = None # call them once at the start UpdateParameters() trigger_name = [] trigger_code = [] for code in range(1, 128): trigger_name.append("note%03d" % code) trigger_code.append(code) trigger_name.append("control%03d" % code) trigger_code.append(code) trigger_name.append("polytouch%03d" % code) trigger_code.append(code) for name in [ 'note', 'aftertouch', 'pitchwheel', 'start', 'continue', 'stop', 'reset' ]: trigger_name.append(name) trigger_code.append(None) # each of the Redis messages is mapped onto a different MIDI message trigger = [] for name, code in zip(trigger_name, trigger_code): if config.has_option('trigger', name): # start the background thread that deals with this note this = TriggerThread(patch.getstring('trigger', name), name, code) trigger.append(this) monitor.debug(name + ' trigger configured') # start the thread for each of the triggers for thread in trigger: thread.start() control_name = [] control_code = [] for code in range(1, 128): control_name.append("note%03d" % code) control_code.append(code) control_name.append("control%03d" % code) control_code.append(code) control_name.append("polytouch%03d" % code) control_code.append(code) for name in [ 'note', 'aftertouch', 'pitchwheel', 'start', 'continue', 'stop', 'reset' ]: control_name.append(name) control_code.append(None) # control values are only interesting when different from the previous value previous_val = {} for name in control_name: previous_val[name] = None # there should not be any local variables in this function, they should all be global if len(locals()): print('LOCALS: ' + ', '.join(locals().keys()))
def _start(): '''Start the module This uses the global variables from setup and adds a set of global variables ''' global parser, args, config, r, response, patch, name global monitor, control_name, control_code, note_name, note_code, debug, port, midichannel, mididevice, outputport, scale, offset, lock, trigger, code, this, thread, previous_val # this can be used to show parameters that have changed monitor = EEGsynth.monitor(name=name, debug=patch.getint('general', 'debug')) # the list of MIDI commands is the only aspect that is specific to the Volca Beats # see http://media.aadl.org/files/catalog_guides/1445131_chart.pdf control_name = [ 'kick_level', 'snare_level', 'lo_tom_level', 'hi_tom_level', 'closed_hat_level', 'open_hat_level', 'clap_level', 'claves_level', 'agogo_level', 'crash_level', 'clap_speed', 'claves_speed', 'agogo_speed', 'crash_speed', 'stutter_time', 'stutter_depth', 'tom_decay', 'closed_hat_decay', 'open_hat_decay', 'hat_gra in' ] control_code = [ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 ] note_name = [ 'kick', 'snare', 'lo_tom', 'hi_tom', 'closed_hat', 'open_hat', 'clap' ] note_code = [36, 38, 43, 50, 42, 46, 39] # get the options from the configuration file debug = patch.getint('general', 'debug') # this is only for debugging, check which MIDI devices are accessible monitor.info('------ OUTPUT ------') for port in mido.get_output_names(): monitor.info(port) monitor.info('-------------------------') midichannel = patch.getint( 'midi', 'channel') - 1 # channel 1-16 get mapped to 0-15 mididevice = patch.getstring('midi', 'device') mididevice = EEGsynth.trimquotes(mididevice) mididevice = process.extractOne( mididevice, mido.get_output_names())[0] # select the closest match try: outputport = mido.open_output(mididevice) monitor.success('Connected to MIDI output') except: raise RuntimeError("cannot connect to MIDI output") # the scale and offset are used to map Redis values to MIDI values scale = patch.getfloat('input', 'scale', default=127) offset = patch.getfloat('input', 'offset', default=0) # this is to prevent two messages from being sent at the same time lock = threading.Lock() # each of the notes that can be played is mapped onto a different trigger trigger = [] for name, code in zip(note_name, note_code): if config.has_option('note', name): # start the background thread that deals with this note this = TriggerThread(patch.getstring('note', name), code) trigger.append(this) monitor.debug(name + ' trigger configured') # start the thread for each of the notes for thread in trigger: thread.start() # control values are only relevant when different from the previous value previous_val = {} for name in control_name: previous_val[name] = None # there should not be any local variables in this function, they should all be global if len(locals()): print('LOCALS: ' + ', '.join(locals().keys()))