Пример #1
0
 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)
Пример #2
0
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()))
Пример #3
0
 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()
Пример #4
0
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)
Пример #5
0
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)
Пример #6
0
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()))
Пример #7
0
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)
Пример #8
0
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)
Пример #9
0
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)
Пример #10
0
    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()
Пример #11
0
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'))
Пример #12
0
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)
Пример #13
0
    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'))
Пример #14
0
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)
Пример #15
0
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()))
Пример #16
0
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()))
Пример #17
0
 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)
Пример #18
0
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))
Пример #19
0
 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)
Пример #20
0
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)
Пример #21
0
 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()
Пример #22
0
 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)
Пример #23
0
 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])
Пример #24
0
    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)
Пример #25
0
    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)
Пример #26
0
 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)))
Пример #27
0
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()))
Пример #28
0
 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()
Пример #29
0
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
Пример #30
0
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()))
Пример #31
0
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'))
Пример #32
0
 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()
Пример #33
0
 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)
Пример #34
0
 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()
Пример #35
0
 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))
Пример #36
0
    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)
Пример #37
0
    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)
Пример #38
0
        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:
Пример #39
0
        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)
Пример #40
0
    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
Пример #41
0
        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:
Пример #42
0
    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)
Пример #43
0
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()
Пример #44
0
            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:
Пример #45
0
    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)
Пример #46
0
    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()
Пример #47
0
                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!'
Пример #48
0
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)
Пример #49
0
    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
Пример #50
0
    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:
Пример #51
0
                    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: