def run(self): global modulation, frequencies, control, channame, scale_amplitude, offset_amplitude, scale_frequency, offset_frequency pubsub = r.pubsub() # this message unblocks the Redis listen command pubsub.subscribe('MODULATETONE_UNBLOCK') # this message triggers the event pubsub.subscribe(self.redischannel) while self.running: for item in pubsub.listen(): if not self.running or not item['type'] == 'message': break if item['channel'] == self.redischannel: chanval = float(item['data']) with lock: if modulation == 'am': chanval = EEGsynth.rescale(chanval, slope=scale_amplitude, offset=offset_amplitude) chanval = EEGsynth.limit(chanval, lo=0, hi=1) elif modulation == 'fm': chanval = EEGsynth.rescale(chanval, slope=scale_frequency, offset=offset_frequency) control[self.tone, self.audiochannel] = chanval monitor.update( channame[self.audiochannel] + " tone" + str(self.tone + 1), chanval)
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, monitor, debug, ft_host, ft_port, ft_input global timeout, hdr_input, start, rectify, invert, prefix, window, scale_threshold, offset_threshold, scale_interval, offset_interval, channels, previous, begsample, endsample global dat_input, threshold, interval, channel, maxind, maxval, sample, key # determine when we start polling for available data start = time.time() while endsample > hdr_input.nSamples - 1: # wait until there is enough data time.sleep(patch.getfloat('general', 'delay')) hdr_input = ft_input.getHeader() if (hdr_input.nSamples - 1) < (endsample - window): raise RuntimeError("buffer reset detected") if (time.time() - start) > timeout: raise RuntimeError("timeout while waiting for data") # get the input data dat_input = ft_input.getData([begsample, endsample]).astype(np.double) monitor.debug("read from sample %d to %d" % (begsample, endsample)) # rectify the data if rectify: dat_input = np.absolute(dat_input) # invert the data if invert: dat_input = -dat_input threshold = patch.getfloat('processing', 'threshold') threshold = EEGsynth.rescale(threshold, slope=scale_threshold, offset=offset_threshold) interval = patch.getfloat('processing', 'interval', default=0) interval = EEGsynth.rescale(interval, slope=scale_interval, offset=offset_interval) for channel in channels: maxind = np.argmax(dat_input[:, channel]) maxval = dat_input[maxind, channel] sample = maxind + begsample if maxval >= threshold and (sample - previous[channel]) >= ( interval * hdr_input.fSample): key = "%s.channel%d" % (patch.getstring('output', 'prefix'), channel + 1) patch.setvalue(key, float(maxval)) previous[channel] = sample # increment the counters for the next loop begsample += window endsample += window # there should not be any local variables in this function, they should all be global if len(locals()): print('LOCALS: ' + ', '.join(locals().keys()))
def run(self): pubsub = r.pubsub() # this message unblocks the Redis listen command pubsub.subscribe('OUTPUTGPIO_UNBLOCK') # this message triggers the event pubsub.subscribe(self.redischannel) while self.running: for item in pubsub.listen(): if not self.running or not item['type'] == 'message': break if item['channel'] == self.redischannel: # the scale and offset options are channel specific and can be changed on the fly scale = patch.getfloat('scale', self.gpio, default=100) offset = patch.getfloat('offset', self.gpio, default=0) # switch to the PWM value specified in the event val = float(item['data']) val = EEGsynth.rescale(val, slope=scale, offset=offset) val = int(val) SetGPIO(self.gpio, val) if self.duration != None: # schedule a timer to switch it off after the specified duration duration = patch.getfloat('duration', self.gpio) duration = EEGsynth.rescale(duration, slope=scale_duration, offset=offset_duration) # some minimal time is needed for the delay duration = EEGsynth.limit(duration, 0.05, float('Inf')) t = threading.Timer(duration, SetGPIO, args=[self.gpio, 0]) t.start()
def forward_handler(addr, tags, data, source): global prefix global scake global offset if debug > 1: print("---") print("source %s" % OSC.getUrlStr(source)) print("addr %s" % addr) print("tags %s" % tags) print("data %s" % data) if addr[0] != '/': # ensure it starts with a slash addr = '/' + addr if tags == 'f' or tags == 'i': # it is a single value key = prefix + addr.replace('/', '.') val = EEGsynth.rescale(data[0], slope=scale, offset=offset) patch.setvalue(key, val) else: for i in range(len(data)): # it is a list, send it as multiple scalar control values # append the index to the key, this starts with 0 key = prefix + addr.replace('/', '.') + '.%i' % i val = EEGsynth.rescale(data[i], slope=scale, offset=offset) patch.setvalue(key, val)
def forward_handler(addr, tags, data, source): global prefix global scake global offset if debug > 1: print("---") print("source %s" % OSC.getUrlStr(source)) print("addr %s" % addr) print("tags %s" % tags) print("data %s" % data) if addr[0] != '/': # ensure it starts with a slash addr = '/' + addr if tags == 'f' or tags == 'i': # it is a single scalar value key = prefix + addr.replace('/', '.') val = EEGsynth.rescale(data[0], slope=scale, offset=offset) patch.setvalue(key, val) else: for i in range(len(data)): # it is a list, send it as multiple scalar control values # append the index to the key, this starts with 1 key = prefix + addr.replace('/', '.') + '.%i' % (i + 1) val = EEGsynth.rescale(data[i], slope=scale, offset=offset) patch.setvalue(key, val)
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, debug, scale_rate, scale_spread, offset_rate, offset_spread, rate, spread, lock, t global change with lock: rate = patch.getfloat('interval', 'rate', default=60) spread = patch.getfloat('interval', 'spread', default=10) rate = EEGsynth.rescale(rate, slope=scale_rate, offset=offset_rate) spread = EEGsynth.rescale(spread, slope=scale_spread, offset=offset_spread) change = monitor.update('rate', rate) change = monitor.update('spread', spread) or change if change: monitor.debug('canceling previously scheduled trigger') t.cancel() trigger(send=False) # there should not be any local variables in this function, they should all be global if len(locals()): print("LOCALS: " + ", ".join(locals().keys()))
def python2_message_handler(addr, tags, data, source): global monitor, patch, prefix, output_scale, output_offset monitor.debug("addr = %s, tags = %s, data = %s, source %s" % (addr, tags, data, OSC.getUrlStr(source))) if addr[0] != '/': # ensure it starts with a slash addr = '/' + addr if tags == 'f' or tags == 'i': # it is a single scalar value key = prefix + addr.replace('/', '.') val = EEGsynth.rescale(data[0], slope=output_scale, offset=output_offset) patch.setvalue(key, val) else: for i in range(len(data)): # it is a list, send it as multiple scalar control values # append the index to the key, this starts with 1 key = prefix + addr.replace('/', '.') + '.%i' % (i + 1) val = EEGsynth.rescale(data[i], slope=output_scale, offset=output_offset) patch.setvalue(key, val) monitor.update(key, val)
def forward_handler(addr, tags, data, source): global prefix global scake global offset if debug > 1: print "---" print "source %s" % OSC.getUrlStr(source) print "addr %s" % addr print "tags %s" % tags print "data %s" % data if addr[0] != '/': # ensure it starts with a slash addr = '/' + addr key = prefix + addr.replace('/', '.') if tags == 'f' or tags == 'i': # it is a single value val = EEGsynth.rescale(data[0], slope=scale, offset=offset) r.set(key, val) # send it as control value if addr in button_list: r.publish(key, val) # send it as trigger else: for i in range(len(data)): # it is a list, send it as multiple scalar control values val = EEGsynth.rescale(data[i], slope=scale, offset=offset) # append the index to the key, this starts with 0 r.set(key + '.%i' % i, val)
def forward_handler(addr, tags, data, source): if debug>1: print "---" print "source %s" % OSC.getUrlStr(source) print "addr %s" % addr print "tags %s" % tags print "data %s" % data if addr[0]!='/': # ensure it starts with a slash addr = '/' + addr # the scale and offset are used to map OSC values to Redis values scale = patch.getfloat('output', 'scale', default=1) offset = patch.getfloat('output', 'offset', default=0) # the results will be written to redis as "osc.1.faderA" etc. key = patch.getstring('output', 'prefix') + addr.replace('/', '.') if tags=='f' or tags=='i': # it is a single value val = EEGsynth.rescale(data[0], slope=scale, offset=offset) r.set(key, val) # send it as control value if addr in button_list: r.publish(key,val) # send it as trigger else: for i in range(len(data)): # it is a list, send it as multiple scalar control values val = EEGsynth.rescale(data[i], slope=scale, offset=offset) # append the index to the key, this starts with 0 r.set(key + '.%i' % i, val)
def paintEvent(self, e): qp = QtGui.QPainter() qp.begin(self) green = QtGui.QColor(10, 255, 10) red = QtGui.QColor(255, 10, 10) w = qp.window().width() h = qp.window().height() # determine the width (x) and height (y) of each bar barx = int(w / len(input_name)) bary = h # subtract some padding from each side padx = int(barx / 10) pady = int(h / 20) barx -= 2 * padx bary -= 2 * pady # this is the position for the first bar x = padx for name in input_name: scale = patch.getfloat('scale', name, default=1) offset = patch.getfloat('offset', name, default=0) val = patch.getfloat('input', name, default=np.nan) val = EEGsynth.rescale(val, slope=scale, offset=offset) monitor.update(name, val) threshold = patch.getfloat('threshold', name, default=1) threshold = EEGsynth.rescale(threshold, slope=scale, offset=offset) if val >= 0 and val <= threshold: qp.setBrush(green) qp.setPen(green) else: qp.setBrush(red) qp.setPen(red) if not np.isnan(val): val = EEGsynth.limit(val, 0, 1) r = QtCore.QRect(x, pady + (1 - val) * bary, barx, val * bary) qp.drawRect(r) r = QtCore.QRect(x, pady, barx, bary) qp.setPen(QtGui.QColor('white')) qp.drawText(r, QtCore.Qt.AlignCenter | QtCore.Qt.AlignBottom, name) # update the position for the next bar x += 2 * padx + barx # add horizontal lines every 10% for i in range(1, 10): qp.setPen(QtGui.QColor('black')) y = h - pady - float(i) / 10 * bary qp.drawLine(0, y, w, y) qp.end() self.show()
def UpdateParameters(): global patch, velocity_note, scale_velocity, offset_velocity, duration_note, scale_duration, offset_duration velocity_note = patch.getfloat('velocity', 'note', default=64) velocity_note = int(EEGsynth.rescale(velocity_note, slope=scale_velocity, offset=offset_velocity)) duration_note = patch.getfloat('duration', 'note', default=None) if duration_note != None: duration_note = EEGsynth.rescale(duration_note, slope=scale_duration, offset=offset_duration) # some minimal time is needed for the duration duration_note = EEGsynth.limit(duration_note, 0.05, float('Inf'))
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, duration_scale, duration_offset, serialdevice, s, lock, trigger, chanindx, chanstr, redischannel, thread monitor.loop() time.sleep(patch.getfloat('general', 'delay')) # loop over the control voltages for chanindx in range(1, 5): chanstr = "cv%d" % chanindx # this returns None when the channel is not present chanval = patch.getfloat('input', chanstr) if chanval == None: # the value is not present in Redis, skip it monitor.trace(chanstr, 'not available') continue # the scale and offset options are channel specific scale = patch.getfloat('scale', chanstr, default=4095) offset = patch.getfloat('offset', chanstr, default=0) # apply the scale and offset chanval = EEGsynth.rescale(chanval, slope=scale, offset=offset) # ensure that it is within limits chanval = EEGsynth.limit(chanval, lo=0, hi=4095) chanval = int(chanval) SetControl(chanindx, chanval) monitor.update(chanstr, chanval) # loop over the gates for chanindx in range(1, 5): chanstr = "gate%d" % chanindx chanval = patch.getfloat('input', chanstr) if chanval == None: # the value is not present in Redis, skip it monitor.trace(chanstr, 'not available') continue # the scale and offset options are channel specific scale = patch.getfloat('scale', chanstr, default=4095) offset = patch.getfloat('offset', chanstr, default=0) # apply the scale and offset chanval = EEGsynth.rescale(chanval, slope=scale, offset=offset) # the value for the gate should be 0 or 1 chanval = int(chanval > 0) SetGate(chanindx, chanval) monitor.update(chanstr, chanval)
def run(self): while self.running: if self.steps in [1, 2, 3, 4, 6, 8, 12, 24] and len(self.sequence): with lock: step = np.mod( np.arange(0, 24, 24 / self.steps) + self.adjust, 24).astype(int).tolist() if debug > 1: print "sequence step =", step for tick in [clock[i] for i in step]: # the note can be a value or a string pointing to a Redis channel with lock: if len(self.sequence): note = self.sequence[np.mod( self.current, len(self.sequence))] else: note = None note = r.get(note) or note try: note = float(note) except TypeError: # this happens if it is not a number or a string, e.g. None note = None except ValueError: # this happens if it is a string that cannot be converted note = None if note: # map the Redis values to the internally used values note = EEGsynth.rescale(note, slope=pattern_scale, offset=pattern_offset) note = note + self.transpose # map the internally used values to Redis values val = EEGsynth.rescale(note, slope=output_scale, offset=output_offset) if debug > 1: print 'sequence note =', note tick.wait( ) # wait for synchronization with the clock thread if note: r.set(key, val) # send it as control value r.publish(key, val) # send it as trigger self.current += 1 else: # if self.steps is not appropriate time.sleep(patch.getfloat('general', 'delay'))
def forward_handler(addr, tags, data, source): print "---" print "source %s" % OSC.getUrlStr(source) print "addr %s" % addr print "tags %s" % tags print "data %s" % data scale = EEGsynth.getfloat('processing', 'scale', config, r) if scale is None: scale = 1 offset = EEGsynth.getfloat('processing', 'offset', config, r) if offset is None: offset = 0 # apply the scale and offset for i in range(len(data)): data[i] = EEGsynth.rescale(data[i], scale, offset) # the results will be written to redis as "osc.1.faderA" etc. key = config.get('output', 'prefix') + addr.replace('/', '.') if tags == 'f' or tags == 'i': # it is a single value val = data[0] r.set(key, val) # send it as control value if addr in button_list: r.publish(key, val) # send it as trigger else: # it is a list, send it as a list of control values val = data r.set(key, val)
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, delay, timeout, lsl_name, lsl_type, lsl_format, output_prefix, start, selected, streams, stream, inlet, type, source_id, match, lsl_id global sample, timestamp sample, timestamp = inlet.pull_sample(timeout=delay) if not sample == None: if lsl_format == 'value': # interpret the LSL marker string as a numerical value try: val = float(sample[0]) except ValueError: val = float('nan') # the scale and offset options can be changed on the fly scale = patch.getfloat('lsl', 'scale', default=1. / 127) offset = patch.getfloat('lsl', 'offset', default=0.) val = EEGsynth.rescale(val, slope=scale, offset=offset) name = '%s.%s.%s' % (output_prefix, lsl_name, lsl_type) else: # use the marker string as the name, and use an arbitrary value name = '%s.%s.%s.%s' % (output_prefix, lsl_name, lsl_type, sample[0]) val = 1. # send the Redis message patch.setvalue(name, val) monitor.update(name, val) # 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, debug, mididevice, output_scale, output_offset, port, inputport for msg in inputport.iter_pending(): monitor.debug(msg) if hasattr(msg, "control"): # prefix.control000=value key = "{}.control{:0>3d}".format( patch.getstring('output', 'prefix'), msg.control) val = msg.value # map the MIDI values to Redis values between 0 and 1 val = EEGsynth.rescale(val, slope=output_scale, offset=output_offset) patch.setvalue(key, val) elif hasattr(msg, "note"): # prefix.noteXXX=value key = "{}.note{:0>3d}".format(patch.getstring('output', 'prefix'), msg.note) val = msg.velocity patch.setvalue(key, val) key = "{}.note".format(patch.getstring('output', 'prefix')) val = msg.note patch.setvalue(key, val) # there should not be any local variables in this function, they should all be global if len(locals()): print('LOCALS: ' + ', '.join(locals().keys()))
def changevalue(self): target = self.sender() send = True if target.type == 'slider' or target.type == 'dial': val = target.value() elif target.type == 'slap': target.value = (target.value + 1) % 2 val = target.value * 127 / 1 send = val > 0 # only send the press, not the release elif target.type == 'push': target.value = (target.value + 1) % 2 val = target.value * 127 / 1 elif target.type == 'toggle1': target.value = (target.value + 1) % 2 val = target.value * 127 / 1 elif target.type == 'toggle2': target.value = (target.value + 1) % 3 val = target.value * 127 / 2 elif target.type == 'toggle3': target.value = (target.value + 1) % 4 val = target.value * 127 / 3 elif target.type == 'toggle4': target.value = (target.value + 1) % 5 val = target.value * 127 / 4 self.setcolor(target) if send: key = '%s.%s' % (prefix, target.name) val = EEGsynth.rescale(val, slope=output_scale, offset=output_offset) patch.setvalue(key, val, debug=debug)
def UpdateVelocity(): global velocity_note velocity_note = patch.getfloat('velocity', 'note', default=64) velocity_note = int( EEGsynth.rescale(velocity_note, slope=scale_velocity, offset=offset_velocity))
def changevalue(self): target = self.sender() send = True if target.type == 'slider' or target.type == 'dial': val = target.value() elif target.type == 'text': val = int(target.text()) # convert the string into an integer target.setText( '%d' % val) # ensure that the displayed value is consistent elif target.type == 'slap': target.value = (target.value + 1) % 2 val = target.value * 127 / 1 send = val > 0 # only send the press, not the release elif target.type == 'push': target.value = (target.value + 1) % 2 val = target.value * 127 / 1 elif target.type == 'toggle1': target.value = (target.value + 1) % 2 val = target.value * 127 / 1 elif target.type == 'toggle2': target.value = (target.value + 1) % 3 val = target.value * 127 / 2 elif target.type == 'toggle3': target.value = (target.value + 1) % 4 val = target.value * 127 / 3 elif target.type == 'toggle4': target.value = (target.value + 1) % 5 val = target.value * 127 / 4 self.setcolor(target) if send: key = '%s.%s' % (prefix, target.name) val = EEGsynth.rescale(val, slope=output_scale, offset=output_offset) patch.setvalue(key, val, debug=debug)
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 debug, mididevice, port, previous_note, UpdateVelocity, UpdateDuration, TriggerThread, trigger_name, trigger_code, code, trigger, this, thread, control_name, control_code, previous_val, SetNoteOff, SetNoteOn, duration_note, lock, midichannel, monitor, monophonic, offset_duration, offset_velocity, outputport, scale_duration, scale_velocity, sendMidi, velocity_note monitor.loop() time.sleep(patch.getfloat('general', 'delay')) UpdateVelocity() UpdateDuration() for name, code in zip(control_name, control_code): # loop over the control values val = patch.getfloat('control', name) if val is None: continue # it should be skipped when not present in the ini or Redis if val == previous_val[name]: continue # it should be skipped when identical to the previous value previous_val[name] = val # the scale and offset options are channel specific and can be changed on the fly scale = patch.getfloat('scale', name, default=127) offset = patch.getfloat('offset', name, default=0) val = EEGsynth.rescale(val, slope=scale, offset=offset) with lock: sendMidi(name, code, val)
def run(self): pubsub = r.pubsub() # this message unblocks the Redis listen command pubsub.subscribe('OUTPUTCVGATE_UNBLOCK') # this message triggers the event pubsub.subscribe(self.redischannel) while self.running: for item in pubsub.listen(): if not self.running or not item['type'] == 'message': break if item['channel'] == self.redischannel: # switch to the value specified in the event, it can be 0 or 1 val = float(item['data']) > 0 SetGate(self.gate, val) if self.duration != None: # schedule a timer to switch it off after the specified duration duration = patch.getfloat('duration', self.duration) duration = EEGsynth.rescale(duration, slope=duration_scale, offset=duration_offset) # some minimal time is needed for the delay duration = EEGsynth.limit(duration, 0.05, float('Inf')) t = threading.Timer(duration, SetGate, args=[self.gate, False]) t.start()
def run(self): global monitor, scale, offset pubsub = r.pubsub() pubsub.subscribe('VOLCAKEYS_UNBLOCK' ) # this message unblocks the redis listen command pubsub.subscribe(self.redischannel) # this message contains the note while self.running: for item in pubsub.listen(): if not self.running or not item['type'] == 'message': break if item['channel'] == self.redischannel: monitor.trace(item) # map the Redis values to MIDI values val = EEGsynth.rescale(float(item['data']), slope=scale, offset=offset) val = EEGsynth.limit(val, 0, 127) val = int(val) monitor.update(item['channel'], val) msg = mido.Message('note_on', note=self.note, velocity=val, channel=midichannel) with lock: outputport.send(msg)
def run(self): pubsub = r.pubsub() pubsub.subscribe('OUTPUTLSL_UNBLOCK' ) # this message unblocks the redis listen command pubsub.subscribe( self.redischannel) # this message contains the trigger while self.running: for item in pubsub.listen(): if not self.running or not item['type'] == 'message': break if item['channel'] == self.redischannel: if lsl_format == 'value': # map the Redis values to LSL marker values val = float(item['data']) # the scale and offset options are channel specific and can be changed on the fly scale = patch.getfloat('scale', self.name, default=127) offset = patch.getfloat('offset', self.name, default=0) val = EEGsynth.rescale(val, slope=scale, offset=offset) # format the value as a string marker = '%g' % (val) else: marker = self.name with lock: monitor.debug(marker) outlet.push_sample([marker])
def run(self): pubsub = r.pubsub() pubsub.subscribe('OUTPUTOSC_UNBLOCK' ) # this message unblocks the redis listen command pubsub.subscribe( self.redischannel) # this message contains the value of interest while self.running: for item in pubsub.listen(): if not self.running or not item['type'] == 'message': break if item['channel'] == self.redischannel: # map the Redis values to OSC values val = float(item['data']) # the scale and offset options are channel specific scale = patch.getfloat('scale', self.name, default=1) offset = patch.getfloat('offset', self.name, default=0) # apply the scale and offset val = EEGsynth.rescale(val, slope=scale, offset=offset) monitor.update(self.osctopic, val) with lock: # send it as a string with a space as separator if use_old_version: msg = OSC.OSCMessage(self.osctopic) msg.append(val) s.send(msg) else: s.send_message(self.osctopic, val)
def run(self): pubsub = r.pubsub() pubsub.subscribe('OUTPUTMQTT_UNBLOCK' ) # this message unblocks the redis listen command pubsub.subscribe( self.redischannel) # this message contains the value of interest while self.running: for item in pubsub.listen(): if not self.running or not item['type'] == 'message': break if item['channel'] == self.redischannel: # map the Redis values to MQTT values val = float(item['data']) # the scale and offset options are channel specific scale = patch.getfloat('scale', self.name, default=1) offset = patch.getfloat('offset', self.name, default=0) # apply the scale and offset val = EEGsynth.rescale(val, slope=scale, offset=offset) monitor.update(self.mqtttopic, val) with lock: client.publish(self.mqtttopic, payload=val, qos=0, retain=False)
def run(self): pubsub = r.pubsub() pubsub.subscribe('RECORDTRIGGER_UNBLOCK' ) # this message unblocks the Redis listen command pubsub.subscribe(self.redischannel) # this message triggers the event while self.running: for item in pubsub.listen(): timestamp = datetime.datetime.now().isoformat() if not self.running or not item['type'] == 'message': break if item['channel'] == self.redischannel: # the trigger value should be saved if input_scale != None or input_offset != None: try: # convert it to a number and apply the scaling and the offset val = float(item['data']) val = EEGsynth.rescale(val, slope=input_scale, offset=input_offset) except ValueError: # keep it as a string val = item['data'] if debug > 0: print(( "cannot apply scaling, writing %s as string" % (self.redischannel))) if not f.closed: lock.acquire() # write the value, it can be either a number or a string f.write("%s\t%s\t%s\n" % (self.redischannel, val, timestamp)) lock.release() if debug > 0: print(("%s\t%s\t%s" % (self.redischannel, val, timestamp)))
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, control_name, control_code, note_name, note_code, debug, port, midichannel, mididevice, outputport, scale, offset, lock, trigger, code, this, thread, previous_val global cmd, val, msg for name, cmd in zip(control_name, control_code): # loop over the control values val = patch.getfloat('control', name) if val == None: continue # it should be skipped when not present if val == previous_val[name]: continue # it should be skipped when identical to the previous value previous_val[name] = val # map the Redis values to MIDI values val = EEGsynth.rescale(val, slope=scale, offset=offset) val = EEGsynth.limit(val, 0, 127) val = int(val) msg = mido.Message('control_change', control=cmd, value=val, channel=midichannel) monitor.debug(cmd, val, name) with lock: outputport.send(msg) # there should not be any local variables in this function, they should all be global if len(locals()): print('LOCALS: ' + ', '.join(locals().keys()))
def run(self): pubsub = r.pubsub() pubsub.subscribe('VOLCABASS_UNBLOCK' ) # this message unblocks the redis listen command pubsub.subscribe(self.redischannel) # this message contains the note while self.running: for item in pubsub.listen(): if not self.running or not item['type'] == 'message': break if item['channel'] == self.redischannel: # map the Redis values to MIDI values val = EEGsynth.rescale(item['data'], slope=scale, offset=offset) val = EEGsynth.limit(val, 0, 127) val = int(val) if debug > 1: print item['channel'], "=", val msg = mido.Message('note_on', note=self.note, velocity=val, channel=midichannel) lock.acquire() outputport.send(msg) lock.release()
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, prefix, input_name, input_variable, previous_val monitor.loop() time.sleep(patch.getfloat('general', 'delay')) lrate = patch.getfloat('processing', 'learning_rate', default=1) for name, variable in zip(input_name, input_variable): key = '%s.%s' % (prefix, variable) val = patch.getfloat('input', name) if val is None: continue # it should be skipped when not present in the ini or Redis scale = patch.getfloat('scale', name, default=1) offset = patch.getfloat('offset', name, default=0) val = EEGsynth.rescale(val, slope=scale, offset=offset) if previous_val[name] is None: # initialize for the first time previous_val[name] = val val = (1 - lrate) * previous_val[name] + lrate * val monitor.update(key, val) patch.setvalue(key, val) previous_val[name] = val
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 for gpio, channel in config.items('control'): val = patch.getfloat('control', gpio) if val == None: continue # it should be skipped when not present if val == previous_val[gpio]: continue # it should be skipped when identical to the previous value previous_val[gpio] = val # the scale and offset options are channel specific and can be changed on the fly scale = patch.getfloat('scale', gpio, default=100) offset = patch.getfloat('offset', gpio, default=0) val = EEGsynth.rescale(val, slope=scale, offset=offset) val = EEGsynth.limit(val, 0, 100) val = int(val) with lock: wiringpi.softPwmWrite(pin[gpio], val) # there should not be any local variables in this function, they should all be global if len(locals()): print('LOCALS: ' + ', '.join(locals().keys()))
def UpdateDuration(): global duration_note duration_note = patch.getfloat('duration', 'note', default=None) if duration_note != None: duration_note = EEGsynth.rescale(duration_note, slope=scale_duration, offset=offset_duration) # some minimal time is needed for the duration duration_note = EEGsynth.limit(duration_note, 0.05, float('Inf'))
def run(self): pubsub = r.pubsub() # this message unblocks the Redis listen command pubsub.subscribe('OUTPUTGPIO_UNBLOCK') # this message triggers the event pubsub.subscribe(self.redischannel) while self.running: for item in pubsub.listen(): if not self.running or not item['type'] == 'message': break if item['channel'] == self.redischannel: # switch to the PWM value specified in the event val = item['data'] val = EEGsynth.rescale(val, slope=input_scale, offset=input_offset) val = int(val) SetGPIO(self.gpio, val) if self.duration != None: # schedule a timer to switch it off after the specified duration duration = patch.getfloat('duration', self.gpio) duration = EEGsynth.rescale(duration, slope=duration_scale, offset=duration_offset) # some minimal time is needed for the delay duration = EEGsynth.limit(duration, 0.05, float('Inf')) t = threading.Timer(duration, SetGPIO, args=[self.gpio, 0]) t.start()
def run(self): pubsub = r.pubsub() pubsub.subscribe('OUTPUTMIDI_UNBLOCK') # this message unblocks the redis listen command pubsub.subscribe(self.redischannel) # this message contains the note while self.running: for item in pubsub.listen(): if not self.running or not item['type'] == 'message': break if item['channel']==self.redischannel: if debug>1: print(item['channel'], '=', item['data']) # map the Redis values to MIDI values val = item['data'] val = EEGsynth.rescale(val, slope=input_scale, offset=input_offset) val = EEGsynth.limit(val, 0, 127) val = int(val) sendMidi(self.name, self.code, val)
def run(self): pubsub = r.pubsub() pubsub.subscribe('VOLCAKEYS_UNBLOCK') # this message unblocks the redis listen command pubsub.subscribe(self.redischannel) # this message contains the note while self.running: for item in pubsub.listen(): if not self.running or not item['type'] == 'message': break if item['channel']==self.redischannel: # map the Redis values to MIDI values val = EEGsynth.rescale(item['data'], slope=scale, offset=offset) val = EEGsynth.limit(val, 0, 127) val = int(val) if debug>1: print item['channel'], "=", val msg = mido.Message('note_on', note=self.note, velocity=val, channel=midichannel) lock.acquire() outputport.send(msg) lock.release()
def run(self): pubsub = r.pubsub() pubsub.subscribe('RECORDTRIGGER_UNBLOCK') # this message unblocks the Redis listen command pubsub.subscribe(self.redischannel) # this message triggers the event while self.running: for item in pubsub.listen(): timestamp = datetime.datetime.now().isoformat() if not self.running or not item['type'] == 'message': break if item['channel']==self.redischannel: # the trigger value should also be saved val = item['data'] val = EEGsynth.rescale(val, slope=input_scale, offset=input_offset) if not f.closed: lock.acquire() f.write("%s\t%g\t%s\n" % (self.redischannel, val, timestamp)) lock.release() if debug>0: print("%s\t%g\t%s" % (self.redischannel, val, timestamp))
def run(self): pubsub = r.pubsub() pubsub.subscribe('SEQUENCER_UNBLOCK') # this message unblocks the redis listen command pubsub.subscribe(self.redischannel) # this message contains the note while self.running: for item in pubsub.listen(): if not self.running or not item['type'] == 'message': break if item['channel'] == self.redischannel: now = time.time() if self.prevtime != None: self.steptime = now - self.prevtime self.prevtime = now if len(self.sequence) > 0: # the sequence can consist of a list of values or a list of Redis channels val = self.sequence[self.step % len(self.sequence)] try: # convert the string from the ini to floating point val = float(val) except: # get the value from Redis val = r.get(val) if val == None: val = 0. else: # convert the string from Redis to floating point val = float(val) # apply the scaling, offset and transpose the note val = EEGsynth.rescale(val, slope=scale_note, offset=offset_note) val += self.transpose # send it as sequencer.note with the note as value patch.setvalue(self.key, val, duration=self.duration*self.steptime) if val>=1.: # send it also as sequencer.noteXXX with value 1.0 key = '%s%03d' % (self.key, val) patch.setvalue(key, 1., duration=self.duration*self.steptime) if debug>0: print "step %2d :" % (self.step + 1), self.key, "=", val # increment to the next step self.step = (self.step + 1) % len(self.sequence)
thresh = np.logical_and(thresh[1:], np.logical_not(thresh[0:-1])) sample = np.where(thresh)[0]+1 if len(sample)<1: # no beat was detected continue # determine the last beat in the window last = sample[-1] last = (last + begsample) / hdr_input.fSample if np.isnan(prev): # the first beat has not been detected yet prev = last continue if last-prev>debounce: # require a minimum time between beats bpm = 60./(last-prev) prev = last if not np.isnan(bpm): # this is to schedule a timer that switches the gate off duration = patch.getfloat('general', 'duration', default=0.1) duration_scale = patch.getfloat('scale', 'duration', default=1) duration_offset = patch.getfloat('offset', 'duration', default=0) duration = EEGsynth.rescale(duration, slope=duration_scale, offset=duration_offset) patch.setvalue(key_rate, bpm, debug=debug) patch.setvalue(key_beat, bpm, debug=debug, duration=duration)
time.sleep(0.1); continue # measure the time that it takes start = time.time(); if debug>1: print "Generating block", block, 'from', begsample, 'to', endsample frequency = patch.getfloat('signal', 'frequency', default=10) amplitude = patch.getfloat('signal', 'amplitude', default=0.8) offset = patch.getfloat('signal', 'offset', default=0) # the DC component of the output signal noise = patch.getfloat('signal', 'noise', default=0.1) dutycycle = patch.getfloat('signal', 'dutycycle', default=0.5) # for the square wave # map the Redis values to signal parameters frequency = EEGsynth.rescale(frequency, slope=scale_frequency, offset=offset_frequency) amplitude = EEGsynth.rescale(amplitude, slope=scale_amplitude, offset=offset_amplitude) offset = EEGsynth.rescale(offset, slope=scale_offset, offset=offset_offset) noise = EEGsynth.rescale(noise, slope=scale_noise, offset=offset_noise) dutycycle = EEGsynth.rescale(dutycycle, slope=scale_dutycycle, offset=offset_dutycycle) if frequency!=prev_frequency or debug>2: print "frequency =", frequency prev_frequency = frequency if amplitude!=prev_amplitude or debug>2: print "amplitude =", amplitude prev_amplitude = amplitude if offset!=prev_offset or debug>2: print "offset =", offset prev_offset = offset if noise!=prev_noise or debug>2:
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) if debug>0: # show the parameters whose value has changed show_change("redis_play", redis_play) show_change("midi_play", midi_play) show_change("midi_start", midi_start)
return not(val % 2) def clip01(val): return min(max(val,0),1) dwelltime = 0. edge = 0 previous = 'no' while True: # measure the time that it takes start = time.time() # these can change on the fly switch_time = patch.getfloat('switch', 'time', default=1.0) switch_time = EEGsynth.rescale(switch_time, slope=scale_time, offset=offset_time) switch_precision = patch.getfloat('switch', 'precision', default=0.1) switch_precision = EEGsynth.rescale(switch_precision, slope=scale_precision, offset=offset_precision) show_change('time', switch_time) show_change('precision', switch_precision) # get the input value and scale between 0 and 1 input = patch.getfloat('input', 'channel', default=np.NaN) input = EEGsynth.rescale(input, slope=scale_input, offset=offset_input) if switch_precision > 0: # the input value is scaled relative to the vertices # so that the switching happens exactly at the vertices and is not visible input = input * (1 + 2 * switch_precision) - switch_precision lower_treshold = 0 upper_treshold = 1
for chanindx in range(1, 512): chanstr = "channel%03d" % chanindx # this returns None when the channel is not present chanval = patch.getfloat('input', chanstr) if chanval==None: # the value is not present in Redis, skip it if debug>2: print chanstr, 'not available' continue # the scale and offset options are channel specific scale = patch.getfloat('scale', chanstr, default=255) offset = patch.getfloat('offset', chanstr, default=0) # apply the scale and offset chanval = EEGsynth.rescale(chanval, slope=scale, offset=offset) # ensure that it is within limits chanval = EEGsynth.limit(chanval, lo=0, hi=255) chanval = int(chanval) if dmxdata[chanindx]!=chr(chanval): if debug>0: print "DMX channel%03d" % chanindx, '=', chanval # update the DMX value for this channel dmxdata = senddmx(dmxdata,chanindx,chanval) elif (time.time()-prevtime)>1: # send a maintenance packet now and then dmxdata = senddmx(dmxdata,chanindx,chanval) prevtime = time.time() except KeyboardInterrupt:
show_change('offset_active', offset_active) show_change('offset_transpose', offset_transpose) show_change('offset_note', offset_note) show_change('offset_duration', offset_duration) try: while True: # measure the time to correct for the slip now = time.time() if debug > 1: print 'loop' # the active sequence is specified as an integer between 0 and 127 active = patch.getfloat('sequence', 'active', default=0) active = EEGsynth.rescale(active, slope=scale_active, offset=offset_active) active = int(active) # get the corresponding sequence as a single string try: sequence = patch.getstring('sequence', "sequence%03d" % active, multiple=True) except: sequence = [] transpose = patch.getfloat('sequence', 'transpose', default=0.) transpose = EEGsynth.rescale(transpose, slope=scale_transpose, offset=offset_transpose) # the duration is relative to the time between clock ticks duration = patch.getfloat('sequence', 'duration', default=0.) duration = EEGsynth.rescale(duration, slope=scale_duration, offset=offset_duration) duration = EEGsynth.limit(duration, 0.1, 0.9)
for thread in trigger: thread.start() try: while True: time.sleep(patch.getfloat('general', 'delay')) for gpio, channel in config.items('control'): val = patch.getfloat('control', gpio) if val == None: continue # it should be skipped when not present if val == previous_val[gpio]: continue # it should be skipped when identical to the previous value previous_val[gpio] = val val = EEGsynth.rescale(val, slope=input_scale, offset=input_offset) val = EEGsynth.limit(val, 0, 100) val = int(val) lock.acquire() wiringpi.softPwmWrite(pin[gpio], val) lock.release() except KeyboardInterrupt: print("Closing threads") for thread in trigger: thread.stop() r.publish('OUTPUTGPIO_UNBLOCK', 1) for thread in trigger: thread.join() sys.exit()
raise SystemExit # determine the start of the actual processing start = time.time() dat_input = ft_input.getData([begsample, endsample]) dat_output = dat_input.astype(np.float32) if debug>2: print("------------------------------------------------------------") print("read ", window, "samples in", (time.time()-start)*1000, "ms") # Online filtering highpassfilter = patch.getfloat('processing', 'highpassfilter', default=None) if highpassfilter != None: highpassfilter = EEGsynth.rescale(highpassfilter, slope=scale_highpass, offset=offset_highpass) lowpassfilter = patch.getfloat('processing', 'lowpassfilter', default=None) if lowpassfilter != None: lowpassfilter = EEGsynth.rescale(lowpassfilter, slope=scale_lowpass, offset=offset_lowpass) change = False change = show_change('highpassfilter', highpassfilter) or change change = show_change('lowpassfilter', lowpassfilter) or change if change: # update the filter parameters b, a, zi = EEGsynth.initialize_online_filter(hdr_input.fSample, highpassfilter, lowpassfilter, filterorder, dat_output, axis=0) if not(highpassfilter is None) or not(lowpassfilter is None): # apply the filter to the data dat_output, zi = EEGsynth.online_filter(b, a, dat_output, axis=0, zi=zi) if debug>1:
def run(self): while self.running: ################################################################################ # these are to map the Redis values to MIDI values ################################################################################ scale_vco_pitch = patch.getfloat('scale', 'vco_pitch') offset_vco_pitch = patch.getfloat('offset', 'vco_pitch') ################################################################################ # VCO ################################################################################ vco_pitch = patch.getfloat('control', 'vco_pitch', default=60) vco_sin = patch.getfloat('control', 'vco_sin', default=0.75) vco_tri = patch.getfloat('control', 'vco_tri', default=0.00) vco_saw = patch.getfloat('control', 'vco_saw', default=0.25) vco_sqr = patch.getfloat('control', 'vco_sqr', default=0.00) # map the Redis values to MIDI values vco_pitch = EEGsynth.rescale(vco_pitch, scale_vco_pitch, offset_vco_pitch) vco_total = vco_sin + vco_tri + vco_saw + vco_sqr if vco_total > 0: # these are all scaled relatively to each other vco_sin = vco_sin / vco_total vco_tri = vco_tri / vco_total vco_saw = vco_saw / vco_total vco_sqr = vco_sqr / vco_total ################################################################################ # LFO ################################################################################ lfo_frequency = patch.getfloat('control', 'lfo_frequency', default=2) lfo_depth = patch.getfloat('control', 'lfo_depth', default=0.5) ################################################################################ # ADSR ################################################################################ adsr_attack = patch.getfloat('control', 'adsr_attack', default=0.25) adsr_decay = patch.getfloat('control', 'adsr_decay', default=0.25) adsr_sustain = patch.getfloat('control', 'adsr_sustain', default=0.5) adsr_release = patch.getfloat('control', 'adsr_release', default=0.25) # convert from value between 0 and 1 into time in samples adsr_attack *= float(rate) adsr_decay *= float(rate) adsr_sustain *= float(rate) adsr_release *= float(rate) ################################################################################ # VCA ################################################################################ vca_envelope = patch.getfloat('control', 'vca_envelope', default=0.5) ################################################################################ # store the control values in the local object ################################################################################ lock.acquire() self.vco_pitch = vco_pitch self.vco_sin = vco_sin self.vco_tri = vco_tri self.vco_saw = vco_saw self.vco_sqr = vco_sqr self.lfo_depth = lfo_depth self.lfo_frequency = lfo_frequency self.adsr_attack = adsr_attack self.adsr_decay = adsr_decay self.adsr_sustain = adsr_sustain self.adsr_release = adsr_release self.vca_envelope = vca_envelope lock.release() if debug > 2: print('----------------------------------') print('vco_pitch =', vco_pitch) print('vco_sin =', vco_sin) print('vco_tri =', vco_tri) print('vco_saw =', vco_saw) print('vco_sqr =', vco_sqr) print('lfo_depth =', lfo_depth) print('lfo_frequency =', lfo_frequency) print('adsr_attack =', adsr_attack) print('adsr_decay =', adsr_decay) print('adsr_sustain =', adsr_sustain) print('adsr_release =', adsr_release) print('vca_envelope =', vca_envelope)
def run(self): pubsub = r.pubsub() pubsub.subscribe('KEYBOARD_UNBLOCK') # this message unblocks the Redis listen command pubsub.subscribe(self.onset) # this message triggers the note while self.running: for item in pubsub.listen(): if not self.running or not item['type'] == 'message': break if item['channel']==self.onset: # the trigger may contain a value that should be mapped to MIDI val = item['data'] val = EEGsynth.rescale(val, slope=input_scale, offset=input_offset) val = EEGsynth.limit(val, 0, 127) val = int(val) if self.velocity == None: # use the value of the onset trigger velocity = val elif type(self.velocity) == str: velocity = float(r.get(self.velocity)) velocity = EEGsynth.rescale(velocity, slope=scale_velocity, offset=offset_velocity) velocity = EEGsynth.limit(velocity, 0, 127) velocity = int(velocity) else: velocity = self.velocity if type(self.pitch) == str: pitch = float(r.get(self.pitch)) pitch = EEGsynth.rescale(pitch, slope=scale_pitch, offset=offset_pitch) pitch = EEGsynth.limit(pitch, 0, 127) pitch = int(pitch) else: pitch = self.pitch if type(self.duration) == str: duration = float(r.get(self.duration)) duration = EEGsynth.rescale(duration, slope=scale_duration, offset=offset_duration) duration = EEGsynth.limit(duration, 0.05, float('Inf')) # some minimal time is needed for the delay else: duration = self.duration if debug>1: print '----------------------------------------------' print "onset ", self.onset, "=", val print "velocity", self.velocity, "=", velocity print "pitch ", self.pitch, "=", pitch print "duration", self.duration, "=", duration if midichannel is None: msg = mido.Message('note_on', note=pitch, velocity=velocity) else: msg = mido.Message('note_on', note=pitch, velocity=velocity, channel=midichannel) SendMessage(msg) if duration != None: # schedule a delayed MIDI message to be sent to switch the note off if midichannel is None: msg = mido.Message('note_on', note=pitch, velocity=0) else: msg = mido.Message('note_on', note=pitch, velocity=0, channel=midichannel) t = threading.Timer(duration, SendMessage, args=[msg]) t.start()
if debug > 2: print name, 'not available' continue if port_val is None: # the value is not present in Redis, skip it if debug > 2: print name, 'not available' continue # the scale and offset options are channel specific scale = patch.getfloat('scale', name, default=1) offset = patch.getfloat('offset', name, default=0) # map the Redis values to MIDI pitch values val = EEGsynth.rescale(val, slope=scale, offset=offset) # portamento range is hardcoded 0-127, so no need for user-config port_val = EEGsynth.rescale(port_val, slope=127, offset=0) # ensure that values are within limits if patch.getstring('general', 'mode') == 'note': val = EEGsynth.limit(val, lo=0, hi=127) val = int(val) port_val = EEGsynth.limit(port_val, lo=0, hi=127) port_val = int(port_val) elif patch.getstring('general', 'mode') == 'pitchbend': val = EEGsynth.limit(val, lo=-8192, hi=8191) val = int(val) else: print 'No output mode (note or pitchbend) specified!'
def update(): global specmax_curr, specmin_curr, specmax_hist, specmin_hist, fft_prev, fft_hist, redfreq, redwidth, bluefreq, bluewidth, counter, history # get last data last_index = ft_input.getHeader().nSamples begsample = (last_index - window) endsample = (last_index - 1) data = ft_input.getData([begsample, endsample]) if debug>0: print("reading from sample %d to %d" % (begsample, endsample)) # demean and detrend data before filtering to reduce edge artefacts and center timecourse data = detrend(data, axis=0) # taper data taper = np.hanning(len(data)) data = data * taper[:, np.newaxis] # shift data to next sample history = np.roll(history, 1, axis=2) for ichan in range(numchannel): channr = int(chanarray[ichan]) # estimate FFT at current moment, apply some temporal smoothing fft_temp = abs(fft(data[:, channr])) fft_curr[ichan] = fft_temp * lrate + fft_prev[ichan] * (1 - lrate) fft_prev[ichan] = fft_curr[ichan] # update FFT history with current estimate history[ichan, :, numhistory - 1] = fft_temp fft_hist = np.nanmean(history, axis=2) # user-selected frequency band arguments_freqrange = patch.getfloat('arguments', 'freqrange', multiple=True) freqrange = np.greater(freqaxis, arguments_freqrange[0]) & np.less_equal(freqaxis, arguments_freqrange[1]) # update panels spect_curr[ichan].setData(freqaxis[freqrange], fft_curr[ichan][freqrange]) spect_hist[ichan].setData(freqaxis[freqrange], fft_hist[ichan][freqrange]) # adapt the vertical scale to the running mean of min/max specmax_curr[ichan] = float(specmax_curr[ichan]) * (1 - lrate) + lrate * max(fft_curr[ichan][freqrange]) specmin_curr[ichan] = float(specmin_curr[ichan]) * (1 - lrate) + lrate * min(fft_curr[ichan][freqrange]) specmax_hist[ichan] = float(specmax_hist[ichan]) * (1 - lrate) + lrate * max(fft_hist[ichan][freqrange]) specmin_hist[ichan] = float(specmin_hist[ichan]) * (1 - lrate) + lrate * min(fft_hist[ichan][freqrange]) freqplot_curr[ichan].setXRange(arguments_freqrange[0], arguments_freqrange[1]) freqplot_hist[ichan].setXRange(arguments_freqrange[0], arguments_freqrange[1]) freqplot_curr[ichan].setYRange(specmin_curr[ichan], specmax_curr[ichan]) freqplot_hist[ichan].setYRange(specmin_hist[ichan], specmax_hist[ichan]) # update plotted lines redfreq = patch.getfloat('input', 'redfreq', default=10. / arguments_freqrange[1]) redfreq = EEGsynth.rescale(redfreq, slope=scale_red, offset=offset_red) * arguments_freqrange[1] redwidth = patch.getfloat('input', 'redwidth', default=1. / arguments_freqrange[1]) redwidth = EEGsynth.rescale(redwidth, slope=scale_red, offset=offset_red) * arguments_freqrange[1] bluefreq = patch.getfloat('input', 'bluefreq', default=20. / arguments_freqrange[1]) bluefreq = EEGsynth.rescale(bluefreq, slope=scale_blue, offset=offset_blue) * arguments_freqrange[1] bluewidth = patch.getfloat('input', 'bluewidth', default=4. / arguments_freqrange[1]) bluewidth = EEGsynth.rescale(bluewidth, slope=scale_blue, offset=offset_blue) * arguments_freqrange[1] if showred: redleft_curr[ichan].setData(x=[redfreq - redwidth, redfreq - redwidth], y=[specmin_curr[ichan], specmax_curr[ichan]]) redright_curr[ichan].setData(x=[redfreq + redwidth, redfreq + redwidth], y=[specmin_curr[ichan], specmax_curr[ichan]]) if showblue: blueleft_curr[ichan].setData(x=[bluefreq - bluewidth, bluefreq - bluewidth], y=[specmin_curr[ichan], specmax_curr[ichan]]) blueright_curr[ichan].setData(x=[bluefreq + bluewidth, bluefreq + bluewidth], y=[specmin_curr[ichan], specmax_curr[ichan]]) if showred: redleft_hist[ichan].setData(x=[redfreq - redwidth, redfreq - redwidth], y=[specmin_hist[ichan], specmax_hist[ichan]]) redright_hist[ichan].setData(x=[redfreq + redwidth, redfreq + redwidth], y=[specmin_hist[ichan], specmax_hist[ichan]]) if showblue: blueleft_hist[ichan].setData(x=[bluefreq - bluewidth, bluefreq - bluewidth], y=[specmin_hist[ichan], specmax_hist[ichan]]) blueright_hist[ichan].setData(x=[bluefreq + bluewidth, bluefreq + bluewidth], y=[specmin_hist[ichan], specmax_hist[ichan]]) # update labels at plotted lines if showred: text_redleft.setText('%0.1f' % (redfreq - redwidth)) text_redleft.setPos(redfreq - redwidth, specmax_curr[0]) text_redright.setText('%0.1f' % (redfreq + redwidth)) text_redright.setPos(redfreq + redwidth, specmax_curr[0]) else: text_redleft.setText("") text_redright.setText("") if showblue: text_blueleft.setText('%0.1f' % (bluefreq - bluewidth)) text_blueleft.setPos(bluefreq - bluewidth, specmax_curr[0]) text_blueright.setText('%0.1f' % (bluefreq + bluewidth)) text_blueright.setPos(bluefreq + bluewidth, specmax_curr[0]) else: text_blueleft.setText("") text_blueright.setText("") if showred: text_redleft_hist.setText('%0.1f' % (redfreq - redwidth)) text_redleft_hist.setPos(redfreq - redwidth, specmax_hist[0]) text_redright_hist.setText('%0.1f' % (redfreq + redwidth)) text_redright_hist.setPos(redfreq + redwidth, specmax_hist[0]) else: text_redleft_hist.setText("") text_redright_hist.setText("") if showblue: text_blueleft_hist.setText('%0.1f' % (bluefreq - bluewidth)) text_blueleft_hist.setPos(bluefreq - bluewidth, specmax_hist[0]) text_blueright_hist.setText('%0.1f' % (bluefreq + bluewidth)) text_blueright_hist.setPos(bluefreq + bluewidth, specmax_hist[0]) else: text_blueleft_hist.setText("") text_blueright_hist.setText("") key = "%s.%s.%s" % (prefix, 'redband', 'low') patch.setvalue(key, redfreq - redwidth) key = "%s.%s.%s" % (prefix, 'redband', 'high') patch.setvalue(key, redfreq + redwidth) key = "%s.%s.%s" % (prefix, 'blueband', 'low') patch.setvalue(key, bluefreq - bluewidth) key = "%s.%s.%s" % (prefix, 'blueband', 'high') patch.setvalue(key, bluefreq + bluewidth)
for chan, i in zip(right, range(len(right))): # interpolate each channel onto the output sampling rate vec_output = np.interp(tim_output, tim_input, dat_input[:, chan-1]) # multiply with the modulating signal vec_output *= np.cos(tim_output * right_f[i] * 2 * np.pi) # apply the filter to remove one sideband vec_output, right_zi[i] = EEGsynth.online_filter(right_b[i], right_a[i], vec_output, zi=right_zi[i]) # add it to the output dat_output[:,1] += vec_output # normalize for the number of channels dat_output /= hdr_input.nChannels scaling = patch.getfloat('signal', 'scaling', default=1) scaling = EEGsynth.rescale(scaling, slope=scale_scaling, offset =offset_scaling) if scaling_method == 'multiply': dat_output *= scaling elif scaling_method == 'divide': dat_output /= scaling # write the data to the output buffer ft_output.putData(dat_output.astype(np.float32)) # compute the duration and desired number of output samples duration = time.time() - start desired = duration * sample_rate # update the number of output samples for the next iteration # if nOutput > desired: # nOutput /= 1.002
for msg in inputport.iter_pending(): if midichannel is None: try: # specify the MIDI channel on the basis of the first incoming message midichannel = int(msg.channel) except: pass if debug>1 and msg.type!='clock': print(msg) if hasattr(msg, "control"): # e.g. prefix.control000=value key = "{}.control{:0>3d}".format(patch.getstring('output', 'prefix'), msg.control) val = EEGsynth.rescale(msg.value, slope=scale_control, offset=offset_control) patch.setvalue(key, val, debug=debug) elif hasattr(msg, "note"): # the default is not to send a message val = None # use an local variable as abbreviation in the subsequent code if msg.note not in note_list: # this note/button was not specified in the ini file, add it note_list = note_list+[msg.note] status_list = status_list+[0] # get the remembered status for this note/button status = status_list[note_list.index(msg.note)] # change to the next state if msg.note in toggle1:
pass if debug>0 and msg.type!='clock': print msg if hasattr(msg,'note'): print(msg) if patch.getstring('processing','detect')=='release' and msg.velocity>0: pass elif patch.getstring('processing','detect')=='press' and msg.velocity==0: pass else: # prefix.noteXXX=velocity key = '{}.note{:0>3d}'.format(patch.getstring('output','prefix'), msg.note) val = msg.velocity val = EEGsynth.rescale(val, slope=output_scale, offset=output_offset) patch.setvalue(key, val) # prefix.note=note key = '{}.note'.format(patch.getstring('output','prefix')) val = msg.note patch.setvalue(key, val) elif hasattr(msg,'control'): # ignore these pass elif hasattr(msg,'time'): # ignore these pass except KeyboardInterrupt: print 'Closing threads' for thread in trigger: