def test_NoteOn_constructor_int(self): # pylint: disable=invalid-name # pylint: enable=invalid-name object1 = NoteOn(60, 0x7F) self.assertEqual(object1.note, 60) self.assertEqual(object1.velocity, 0x7F) self.assertIsNone(object1.channel) object2 = NoteOn(60, 0x00) # equivalent of NoteOff self.assertEqual(object2.note, 60) self.assertEqual(object2.velocity, 0x00) self.assertIsNone(object2.channel) object3 = NoteOn(60, 0x50, channel=7) self.assertEqual(object3.note, 60) self.assertEqual(object3.velocity, 0x50) self.assertEqual(object3.channel, 7) object4 = NoteOn(60) # velocity defaults to 127 self.assertEqual(object4.note, 60) self.assertEqual(object4.velocity, 127) self.assertIsNone(object4.channel)
def test_send_basic_sequences(self): # def printit(buffer, len): # print(buffer[0:len]) mockedPortOut = Mock() # mockedPortOut.write = printit m = adafruit_midi.MIDI(midi_out=mockedPortOut, out_channel=2) # Test sending some NoteOn and NoteOff to various channels nextcall = 0 # Test sequences with list syntax and pass a tuple too note_list = [ NoteOn(0x6C, 0x51), NoteOn(0x70, 0x52), NoteOn(0x73, 0x53) ] note_tuple = tuple(note_list) m.send(note_list, channel=10) self.assertEqual( mockedPortOut.write.mock_calls[nextcall], call(b"\x9a\x6c\x51\x9a\x70\x52\x9a\x73\x53", 9), "The implementation writes in one go, single 9 byte write expected", ) nextcall += 1 m.send(note_tuple, channel=11) self.assertEqual( mockedPortOut.write.mock_calls[nextcall], call(b"\x9b\x6c\x51\x9b\x70\x52\x9b\x73\x53", 9), "The implementation writes in one go, single 9 byte write expected", ) nextcall += 1
def test_running_status_when_implemented(self): c = 8 raw_data = (bytes(NoteOn("C5", 0x7F, channel=c)) + bytes([0xE8, 0x72, 0x40] + [0x6D, 0x40] + [0x05, 0x41]) + bytes(NoteOn("D5", 0x7F, channel=c))) m = MIDI_mocked_receive(c, raw_data, [3 + 3 + 2 + 3 + 3]) self.assertIsInstance(m, adafruit_midi.MIDI) # silence pylint!
def test_running_status_when_implemented(self): # pylint: disable=invalid-name # pylint: enable=invalid-name channel = 8 raw_data = (bytes(NoteOn("C5", 0x7F, channel=channel)) + bytes([0xE8, 0x72, 0x40] + [0x6D, 0x40] + [0x05, 0x41]) + bytes(NoteOn("D5", 0x7F, channel=channel))) midi = MIDI_mocked_receive(channel, raw_data, [3 + 3 + 2 + 3 + 3]) self.assertIsInstance(midi, adafruit_midi.MIDI) # silence pylint!
def test_NoteOn_constructor_string(self): object1 = NoteOn("C4", 0x64) self.assertEqual(object1.note, 60) self.assertEqual(object1.velocity, 0x64) object2 = NoteOn("C3", 0x7F) self.assertEqual(object2.note, 48) self.assertEqual(object2.velocity, 0x7F) object3 = NoteOn("C#4", 0x00) self.assertEqual(object3.note, 61) self.assertEqual(object3.velocity, 0)
def test_NoteOn_constructor_string(self): # pylint: disable=invalid-name # pylint: enable=invalid-name object1 = NoteOn("C4", 0x64) self.assertEqual(object1.note, 60) self.assertEqual(object1.velocity, 0x64) object2 = NoteOn("C3", 0x7F) self.assertEqual(object2.note, 48) self.assertEqual(object2.velocity, 0x7F) object3 = NoteOn("C#4", 0x00) self.assertEqual(object3.note, 61) self.assertEqual(object3.velocity, 0)
def sequencer(seq, beat, gridbeat, x): # I have a feeling that each step needs to be iterated indiviually in the running loop beatstep = x #gridbeat = Rect( (52), (5), 24, 24, outline=0xF00000, stroke=3) beatstep = selection_update('right', beatstep, gridbeat) if seq[x][0] == 0: customwait(beat) else: midi.send(NoteOn(seq[x][0], 127, channel=seq[x][1])) # setting channel as x is just to prove we can switch channels or instruments for each step # fully supporting this means passing seq[] to sequencer fn includes # note number, midi channel, and any CC for that step as well customwait(beat) midi.send(NoteOn(seq[x][0], 0))
def test_larger_than_buffer_sysex(self): c = 0 monster_data_len = 500 raw_data = (bytes(NoteOn("C5", 0x7F, channel=c)) + bytes( SystemExclusive([0x02], [d & 0x7F for d in range(monster_data_len)])) + bytes(NoteOn("D5", 0x7F, channel=c))) m = MIDI_mocked_receive(c, raw_data, [len(raw_data)]) buffer_len = m._in_buf_size # pylint: disable=protected-access self.assertTrue( monster_data_len > buffer_len, "checking our SysEx truly is larger than buffer", ) msg1 = m.receive() self.assertIsInstance(msg1, NoteOn) self.assertEqual(msg1.note, 72) self.assertEqual(msg1.velocity, 0x7F) self.assertEqual(msg1.channel, c) # (Ab)using python's rounding down for negative division # pylint: disable=unused-variable for unused in range(-(-(1 + 1 + monster_data_len + 1) // buffer_len) - 1): msg2 = m.receive() self.assertIsNone(msg2) # The current implementation will read SysEx end status byte # and report it as an unknown msg3 = m.receive() self.assertIsInstance(msg3, adafruit_midi.midi_message.MIDIUnknownEvent) self.assertEqual(msg3.status, 0xF7) self.assertIsNone(msg3.channel) # (msg4, channel4) = m.receive() # self.assertIsInstance(msg4, PitchBend) # self.assertEqual(msg4.pitch_bend, 72) # self.assertEqual(channel4, c) msg5 = m.receive() self.assertIsInstance(msg5, NoteOn) self.assertEqual(msg5.note, 74) self.assertEqual(msg5.velocity, 0x7F) self.assertEqual(msg5.channel, c) msg6 = m.receive() self.assertIsNone(msg6)
def test_smallsysex_between_notes(self): m = MIDI_mocked_both_loopback(3, 3) m.send([ NoteOn("C4", 0x7F), SystemExclusive([0x1F], [1, 2, 3, 4, 5, 6, 7, 8]), NoteOff(60, 0x28), ]) msg1 = m.receive() self.assertIsInstance(msg1, NoteOn) self.assertEqual(msg1.note, 60) self.assertEqual(msg1.velocity, 0x7F) self.assertEqual(msg1.channel, 3) msg2 = m.receive() self.assertIsInstance(msg2, SystemExclusive) self.assertEqual(msg2.manufacturer_id, bytes([0x1F])) self.assertEqual(msg2.data, bytes([1, 2, 3, 4, 5, 6, 7, 8])) self.assertEqual(msg2.channel, None) # SysEx does not have a channel msg3 = m.receive() self.assertIsInstance(msg3, NoteOff) self.assertEqual(msg3.note, 60) self.assertEqual(msg3.velocity, 0x28) self.assertEqual(msg3.channel, 3) msg4 = m.receive() self.assertIsNone(msg4)
def update_notes(lastStep, step): for _channel in range(16): for _note in range(16): if pattern[_channel][_note][step] == Note.ON: midi[_channel].send(NoteOn(36 + _note, 120)) elif pattern[_channel][_note][step] == Note.OFF: if pattern[_channel][_note][lastStep] != Note.OFF: midi[_channel].send(NoteOff(36 + _note, 120))
def test_send_basic_single(self): # def printit(buffer, len): # print(buffer[0:len]) mockedPortOut = Mock() # mockedPortOut.write = printit m = adafruit_midi.MIDI(midi_out=mockedPortOut, out_channel=2) # Test sending some NoteOn and NoteOff to various channels nextcall = 0 m.send(NoteOn(0x60, 0x7F)) self.assertEqual(mockedPortOut.write.mock_calls[nextcall], call(b"\x92\x60\x7f", 3)) nextcall += 1 m.send(NoteOn(0x64, 0x3F)) self.assertEqual(mockedPortOut.write.mock_calls[nextcall], call(b"\x92\x64\x3f", 3)) nextcall += 1 m.send(NoteOn(0x67, 0x1F)) self.assertEqual(mockedPortOut.write.mock_calls[nextcall], call(b"\x92\x67\x1f", 3)) nextcall += 1 m.send(NoteOn(0x60, 0x00)) # Alternative to NoteOff self.assertEqual(mockedPortOut.write.mock_calls[nextcall], call(b"\x92\x60\x00", 3)) nextcall += 1 m.send(NoteOff(0x64, 0x01)) self.assertEqual(mockedPortOut.write.mock_calls[nextcall], call(b"\x82\x64\x01", 3)) nextcall += 1 m.send(NoteOff(0x67, 0x02)) self.assertEqual(mockedPortOut.write.mock_calls[nextcall], call(b"\x82\x67\x02", 3)) nextcall += 1 # Setting channel to non default m.send(NoteOn(0x6C, 0x7F), channel=9) self.assertEqual(mockedPortOut.write.mock_calls[nextcall], call(b"\x99\x6c\x7f", 3)) nextcall += 1 m.send(NoteOff(0x6C, 0x7F), channel=9) self.assertEqual(mockedPortOut.write.mock_calls[nextcall], call(b"\x89\x6c\x7f", 3)) nextcall += 1
def blink(event): # turn the LED on when a rising edge is detected if event.edge == NeoTrellis.EDGE_RISING: outport.write(NoteOn(midi_notes[i], 120)) trellis.pixels[event.number] = CYAN # turn the LED off when a rising edge is detected elif event.edge == NeoTrellis.EDGE_FALLING: trellis.pixels[event.number] = OFF
def test_somegood_somemissing_databytes(self): # pylint: disable=invalid-name # pylint: enable=invalid-name channel = 8 raw_data = ( bytes(NoteOn("C5", 0x7F, channel=channel)) + bytes([0xE8, 0x72, 0x40] + [0xE8, 0x6D] # Missing last data byte + [0xE8, 0x5, 0x41]) + bytes(NoteOn("D5", 0x7F, channel=channel))) midi = MIDI_mocked_receive(channel, raw_data, [3 + 3 + 2 + 3 + 3]) msg1 = midi.receive() self.assertIsInstance(msg1, NoteOn) self.assertEqual(msg1.note, 72) self.assertEqual(msg1.velocity, 0x7F) self.assertEqual(msg1.channel, channel) msg2 = midi.receive() self.assertIsInstance(msg2, PitchBend) self.assertEqual(msg2.pitch_bend, 8306) self.assertEqual(msg2.channel, channel) # The current implementation will read status bytes for data # In most cases it would be a faster recovery with fewer messages # lost if the next status byte wasn't consumed # and parsing restarted from that byte msg3 = midi.receive() self.assertIsInstance(msg3, adafruit_midi.midi_message.MIDIBadEvent) self.assertIsInstance(msg3.data, bytes) self.assertEqual(msg3.data, bytes([0xE8, 0x6D, 0xE8])) self.assertIsNone(msg3.channel) # (msg4, channel4) = m.receive() # self.assertIsInstance(msg4, PitchBend) # self.assertEqual(msg4.pitch_bend, 72) # self.assertEqual(channel4, c) msg5 = midi.receive() self.assertIsInstance(msg5, NoteOn) self.assertEqual(msg5.note, 74) self.assertEqual(msg5.velocity, 0x7F) self.assertEqual(msg5.channel, channel) msg6 = midi.receive() self.assertIsNone(msg6)
def trigger(event): if config_mode is 1: config_check(event) elif config_mode is 0: # sampler mode actions if button_mode is 0: # trigger on when a rising edge is detected if event.edge == NeoTrellis.EDGE_RISING: trellis.pixels[event.number] = COLOR_A button = button_map[event.number] # use the reindexed button numbering note = note_map[button] # print("Pixel "+str(event.number)+" pressed.") # debug only of physical buttons print("Button "+str(button)+" pressed.") midi.send(NoteOn(note, 127)) print("Note On: "+str(note)) # trigger off when a rising edge is detected for pad mode elif event.edge == NeoTrellis.EDGE_FALLING: trellis.pixels[event.number] = COLOR_B button = button_map[event.number] note = note_map[button] # print("Button "+str(event.number)+" released") print("Button "+str(button)+" released.") midi.send(NoteOff(note, 0)) print("Note Off: "+str(note)) # sequencer mode actions elif button_mode is 1: # trigger on when a rising edge is detected if event.edge == NeoTrellis.EDGE_RISING: if button_state[event.number] is 0: trellis.pixels[event.number] = COLOR_A button_state[event.number] = 1 else: trellis.pixels[event.number] = COLOR_B button_state[event.number] = 0 button = button_map[event.number] # use the reindexed button numbering note = note_map[button] # print("Pixel "+str(event.number)+" pressed.") # debug only of physical buttons print("Button "+str(button)+" pressed.") midi.send(NoteOn(note, 127)) print("Note On: "+str(note))
def sequencer(seq, beat, gridbeat, x): beatstep = x #gridbeat = Rect( (52), (5), 24, 24, outline=0xF00000, stroke=3) beatstep = selection_update('right', beatstep, gridbeat) #send MIDI for each track for trk in range(0, MAX_TRACKS - 1): if seq[current_track][x][0] != 0: midi.send(NoteOn(seq[trk][x][0], 127, channel=seq[0][x][1])) # setting channel as x is just to prove we can switch channels or instruments for each step # fully supporting this means passing seq[] to sequencer fn includes # note number, midi channel, and any CC for that step as well customwait(beat) # MIDI Note off for each track for trk in range(0, MAX_TRACKS - 1): if seq[current_track][x][0] != 0: midi.send(NoteOn(seq[trk][x][0], 0))
def blink(xcoord, ycoord, edge): padNum = XY(xcoord, ycoord, 0) if edge == NeoTrellis.EDGE_RISING: print('key press! ', padNum) trellis.pressed_keys.add((xcoord,ycoord)) if keys[padNum][1]['type'] is 'momentary': #print('momentary ', padNum, ' on') #midi.send(NoteOn(keys[padNum][2], 120)) midi.send(NoteOn(padNum)) color = keys[padNum][1]['on'] trellis.color(xcoord, ycoord, color) elif keys[padNum][1]['type'] is 'latching': #midi.send(NoteOn(keys[padNum][2], 120)) midi.send(NoteOn(padNum)) if not keys[padNum][1]['state']: color = keys[padNum][1]['on'] #print('latching ', padNum, ' on ', keys[padNum]) elif keys[padNum][1]['state']: color = keys[padNum][1]['off'] #print('latching ', padNum, ' off ', keys[padNum]) trellis.color(xcoord, ycoord, color) keys[padNum][1]['state'] = not keys[padNum][1]['state'] elif edge == NeoTrellis.EDGE_FALLING: print('key release! ', padNum) if (xcoord,ycoord) in current_press: trellis.pressed_keys.remove((xcoord,ycoord)) if keys[padNum][1]['type'] is 'momentary': #print('momentary ', padNum, ' off') midi.send(NoteOff(padNum)) color = keys[padNum][1]['off'] trellis.color(xcoord, ycoord, color)
def test_send_badnotes(self): mockedPortOut = Mock() m = adafruit_midi.MIDI(midi_out=mockedPortOut, out_channel=2) # Test sending some NoteOn and NoteOff to various channels nextcall = 0 m.send(NoteOn(60, 0x7F)) self.assertEqual(mockedPortOut.write.mock_calls[nextcall], call(b"\x92\x3c\x7f", 3)) nextcall += 1 with self.assertRaises(ValueError): m.send(NoteOn(64, 0x80)) # Velocity > 127 - illegal value with self.assertRaises(ValueError): m.send(NoteOn(67, -1)) # test after exceptions to ensure sending is still ok m.send(NoteOn(72, 0x7F)) self.assertEqual(mockedPortOut.write.mock_calls[nextcall], call(b"\x92\x48\x7f", 3)) nextcall += 1
def test_unknown_before_NoteOn(self): c = 0 # From an M-Audio AXIOM controller raw_data = bytes( [0b11110011, 0x10] # Song Select (not yet implemented) + [0b11110011, 0x20] + [0b11110100] + [0b11110101]) + bytes( NoteOn("C5", 0x7F, channel=c)) m = MIDI_mocked_receive(c, raw_data, [2, 2, 1, 1, 3]) for unused in range(4): # pylint: disable=unused-variable msg = m.receive() self.assertIsInstance(msg, adafruit_midi.midi_message.MIDIUnknownEvent) self.assertIsNone(msg.channel) msg = m.receive() self.assertIsInstance(msg, NoteOn) self.assertEqual(msg.note, 0x48) # 0x48 is C5 self.assertEqual(msg.velocity, 0x7F) self.assertEqual(msg.channel, c)
from adafruit_midi.timing_clock import TimingClock from adafruit_midi.channel_pressure import ChannelPressure from adafruit_midi.control_change import ControlChange from adafruit_midi.note_off import NoteOff from adafruit_midi.note_on import NoteOn from adafruit_midi.pitch_bend import PitchBend from adafruit_midi.polyphonic_key_pressure import PolyphonicKeyPressure from adafruit_midi.program_change import ProgramChange from adafruit_midi.start import Start from adafruit_midi.stop import Stop from adafruit_midi.system_exclusive import SystemExclusive from adafruit_midi.midi_message import MIDIUnknownEvent import usb_midi midi = adafruit_midi.MIDI(midi_in=usb_midi.ports[0], midi_out=usb_midi.ports[1], in_channel=0, out_channel=0, debug=True) # UART = busio.UART(board.TX, board.RX, baudrate=31250, timeout=0.001) # midi = adafruit_midi.MIDI(midi_in=UART, midi_out=UART, in_channel=0, out_channel=0, debug=True) while True: print("-----") midi.send(Stop()) midi.send(NoteOn(60, 100)) midi.send(ControlChange(25, 127)) midi.send(ProgramChange(33)) time.sleep(1)
while True: while True: msg_in = midi.receive() # non-blocking read # For a Note On or Note Off play a major chord # For any other known event just forward it if isinstance(msg_in, NoteOn) and msg_in.velocity != 0: print( "Playing major chord with root", msg_in.note, "from channel", msg_in.channel + 1, ) for offset in major_chord: new_note = msg_in.note + offset if 0 <= new_note <= 127: midi.send(NoteOn(new_note, msg_in.velocity)) elif (isinstance(msg_in, NoteOff) or isinstance(msg_in, NoteOn) and msg_in.velocity == 0): for offset in major_chord: new_note = msg_in.note + offset if 0 <= new_note <= 127: midi.send(NoteOff(new_note, 0x00)) elif isinstance(msg_in, MIDIUnknownEvent): # Message are only known if they are imported print("Unknown MIDI event status ", msg_in.status) elif msg_in is not None: midi.send(msg_in)
def sendKey(key): midi.send(NoteOn(key, 60)) time.sleep(0.25) midi.send([NoteOff(key, 127)]) time.sleep(0.2)
midi.send(NoteOff(note, 0)) keys[k].set_led(0, 0, 0) # Calculate MIDI note numbers notes = [start_note + k for k in pressed] last_pressed = pressed # If going forward (up or starting up-down), start at 0, # otherwise start at the end of the list of notes. if arp_style == 0 or arp_style == 2: this_note = 0 elif arp_style == 1: this_note = len(notes) - 1 # Send MIDI note on message for current note and turn LED on midi.send(NoteOn(notes[this_note], velocity)) keys[pressed[this_note]].set_led(*rgb) # Update last_played time, set elapsed to 0, and update current and # last note indices. last_played = time.monotonic() elapsed = 0 last_note = this_note this_note += direction # If the currently pressed notes are the same as the last loop, then... else: if notes != []: # Check time elapsed since last note played elapsed = time.monotonic() - last_played
while ble.connected: # iterate through the touch inputs for i in range(3): inputs = pads[i] # if a touch input is detected... if inputs.value and triad_states[i] is False: # debounce state activated triad_states[i] = True # update triad active_triad = triads[i] print(active_triad) # after touch input... if not inputs.value and triad_states[i] is True: # reset debounce state triad_states[i] = False # send triad arpeggios out with half second delay midi.send(NoteOn(active_triad[z])) time.sleep(0.5) midi.send(NoteOff(active_triad[z])) time.sleep(0.5) # increase index by 1 z += 1 # reset index at end of triad if z > 2: z = 0 # BLE connection print("Disconnected") print() ble.start_advertising(advertisement)
def play_notes(step): for i in range(16): if pattern[i][step]: midi.send(NoteOn(36 + i, 120))
from adafruit_midi.note_off import NoteOff from adafruit_midi.note_on import NoteOn from adafruit_midi.pitch_bend import PitchBend midi = adafruit_midi.MIDI(midi_out=usb_midi.ports[1], out_channel=0) print("Midi test") # Convert channel numbers at the presentation layer to the ones musicians use print("Default output channel:", midi.out_channel + 1) print("Listening on input channel:", midi.in_channel + 1 if midi.in_channel is not None else None) while True: # method per message interface midi.note_on(44, 120) time.sleep(0.25) midi.pitch_bend(random.randint(0, 16383)) time.sleep(0.25) midi.note_off(44, 120) midi.control_change(3, 44) time.sleep(0.5) # send message(s) interface midi.send(NoteOn(44, 120)) time.sleep(0.25) midi.send(PitchBend(random.randint(0, 16383))) time.sleep(0.25) midi.send([NoteOff("G#2", 120), ControlChange(3, 44)]) time.sleep(0.5)
def press_handler(key): note = start_note + key.number key.set_led(*rgb) midi.send(NoteOn(note, velocity))
def update(self): # Update the superclass (Keybow2040). super(Sequencer, self).update() if self.running: # Keep track of current time. current_time = time.monotonic() # If a step has elapsed... if current_time - self.last_step_time > self.step_time: for track in self.tracks: if track.active: # Turn last step off. last_step = track.steps[self.last_step_num] last_step.playing = False last_step.update() last_note = last_step.note # Helps prevent stuck notes. if last_step.note_changed: for note in last_step.last_notes: self.midi_channels[track.channel].send( NoteOff(note, 0)) last_step.note_changed = False last_step.last_notes = [] # If last step is active, send MIDI note off message. if last_step.active: self.midi_channels[track.channel].send( NoteOff(last_note, 0)) # Turn this step on. this_step = track.steps[self.this_step_num] this_step.playing = True this_step.update() this_note = this_step.note this_vel = this_step.velocity # Helps prevent stuck notes if this_step.note_changed: for note in this_step.last_notes: self.midi_channels[track.channel].send( NoteOff(note, 0)) this_step.note_changed = False this_step.last_notes = [] # If this step is active, send MIDI note on message. if this_step.active: self.midi_channels[track.channel].send( NoteOn(this_note, this_vel)) # If track is not active, send note off for last note and this note. else: last_note = track.steps[self.last_step_num].note this_note = track.steps[self.this_step_num].note self.midi_channels[track.channel].send( NoteOff(last_note, 0)) self.midi_channels[track.channel].send( NoteOff(this_note, 0)) # This step is now the last step! last_step = this_step self.last_step_num = self.this_step_num self.this_step_num += 1 # If we get to the end of the sequence, go back to the start. if self.this_step_num == self.num_steps: self.this_step_num = 0 # Keep track of last step time. self.last_step_time = current_time # Update the tracks. for track in self.tracks: track.update() # Update the step_time, in case the BPM has been changed. self.step_time = 60.0 / self.bpm / (self.num_steps / 2)
def press_handler(key): note = start_note + keymap[key.number] midi.send(NoteOn(note, velocity)) key.set_led(255, 255, 255)
# simple_test import time import random import usb_midi import adafruit_midi from adafruit_midi.control_change import ControlChange from adafruit_midi.note_off import NoteOff from adafruit_midi.note_on import NoteOn from adafruit_midi.pitch_bend import PitchBend midi = adafruit_midi.MIDI(midi_out=usb_midi.ports[1], out_channel=0) print("Midi test") # Convert channel numbers at the presentation layer to the ones musicians use print("Default output channel:", midi.out_channel + 1) print("Listening on input channel:", midi.in_channel + 1 if midi.in_channel is not None else None) while True: midi.send(NoteOn(44, 120)) # G sharp 2nd octave time.sleep(0.25) a_pitch_bend = PitchBend(random.randint(0, 16383)) midi.send(a_pitch_bend) time.sleep(0.25) # note how a list of messages can be used midi.send([NoteOff("G#2", 120), ControlChange(3, 44)]) time.sleep(0.5)
board.GP22, ) touch_ins = [] touchs = [] for pin in touch_pins: touchin = touchio.TouchIn(pin) touchin.threshold += touch_threshold_adjust touch_ins.append(touchin) touchs.append(Debouncer(touchin)) print("\n----------") print("picotouch hello") while True: if debug: for i in range(len(touch_ins)): touchin = touch_ins[i] print(touchin.raw_value, ', ', end='') print() time.sleep(0.01) for i in range(len(touchs)): touch = touchs[i] touch.update() if touch.rose: print("press", i) midi.send(NoteOn(midi_base_note + i, midi_velocity)) if touch.fell: print("release", i) midi.send(NoteOff(midi_base_note + i, midi_velocity))