Skip to content

Commit

Permalink
Adding scale selection and octave selection to MIDI controller
Browse files Browse the repository at this point in the history
  • Loading branch information
skafreak committed Aug 22, 2023
1 parent 4645264 commit 8f5613d
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 19 deletions.
128 changes: 110 additions & 18 deletions Software/Production/MIDIState.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,39 @@
midi_serial,
midi_usb,
neopixels,
select_enc,
volume_enc,
)

c_1 = 24
d_1 = 26
e_1 = 28
f_1 = 29
g_1 = 31
a_1 = 33
b_1 = 35

# MIDI Functions
def send_note_on(note, octv):
note = (note) + (12 * octv)
# def send_note_on(note, octv):
# note = (note) + (12 * octv)
# midi_serial.send(NoteOn(note, 120))
# midi_usb.send(NoteOn(note, 120))


# def send_note_off(note, octv):
# note = (note) + (12 * octv)
# midi_serial.send(NoteOff(note, 0))
# midi_usb.send(NoteOff(note, 120))

# MIDI Functions
def send_note_on(note):
midi_serial.send(NoteOn(note, 120))
midi_usb.send(NoteOn(note, 120))


def send_note_off(note, octv):
note = (note) + (12 * octv)
def send_note_off(note):
midi_serial.send(NoteOff(note, 0))
midi_usb.send(NoteOff(note, 120))
midi_usb.send(NoteOff(note, 0))


def send_cc(number, val):
Expand All @@ -46,39 +65,112 @@ def enter(self, machine):
display.show(text_area)
neopixels.fill((100, 100, 100))
neopixels.show()
self.notes = []
# Reset encoder positions
select_enc.position = 0
volume_enc.position = 0
self.last_select_position = select_enc.position
self.last_volume_position = volume_enc.position
self.notes = [] # Current pressed notes
self.scale = [] # Current scale
self.base = c_1 # Current base note
self.current_scale = "major"
self.generate_major_scale(self.base)
keys.events.clear()
State.enter(self, machine)

def exit(self, machine):
for key in self.notes:
send_note_off(key, 4)
self.notes = []
self.midi_panic()
neopixels.fill((100, 100, 100))
neopixels.show()
State.exit(self, machine)

def generate_major_scale(self, base):
self.scale = []
pattern = [0, 2, 4, 5, 7, 9, 11, 12]
for value in pattern:
self.scale.append(base + value)

def generate_minor_scale(self, base):
self.scale = []
pattern = [0, 2, 3, 5, 7, 8, 10, 12]
for value in pattern:
self.scale.append(base + value)

def midi_panic(self):
send_cc(123, 0) # Turn off all MIDI signal
self.notes = []

def base_down(self):
if self.base > 24:
self.base = self.base - 1

def base_up(self):
if self.base < 108:
self.base = self.base + 1

def octave_down(self):
if self.scale[0] >= 36:
for index, note in enumerate(self.scale):
self.scale[index] = note - 12
self.midi_panic() # TODO improve tracking
self.base = self.scale[0]

def octave_up(self):
if self.scale[0] <= 108:
for index, note in enumerate(self.scale):
self.scale[index] = note + 12
self.midi_panic() # TODO improve tracking
self.base = self.scale[0]

def poll_encoders(self):
# Check select knob
if select_enc.position != self.last_select_position:
if select_enc.position < self.last_select_position:
self.octave_down()
if select_enc.position > self.last_select_position:
self.octave_up()
self.last_select_position = select_enc.position

# Check volume knob
if volume_enc.position != self.last_volume_position:
# Change to minor if already major
if self.current_scale == "major":
self.generate_minor_scale(self.base)
self.current_scale = "minor"
# Change to major if already minor
elif self.current_scale == "minor":
self.generate_major_scale(self.base)
self.current_scale = "major"
self.last_volume_position = volume_enc.position

def update(self, machine):
key_event = keys.events.get()
while key_event:
if key_event.key_number < 10:
if key_event:
if key_event.key_number < 8:
if key_event.pressed:
key = key_event.key_number
self.notes.append(key)
send_note_on(key, 4)
note_value = self.scale[key]
self.notes.append(note_value)
send_note_on(note_value)
mapped_neopixel = neoindex(key)
neopixels[mapped_neopixel] = (255, 0, 0)
if key_event.released:
key = key_event.key_number
if key in self.notes:
self.notes.remove(key)
send_note_off(key, 4)
note_value = self.scale[key]
if note_value in self.notes:
self.notes.remove(note_value)
send_note_off(note_value)
mapped_neopixel = neoindex(key)
neopixels[mapped_neopixel] = (100, 100, 100)
elif (key_event.key_number == 8) and key_event.pressed:
self.midi_panic() # Play button kills all active MIDI notes
elif (key_event.key_number == 9) and key_event.pressed:
pass # TODO Implement function key to shift function of encoder knobs
elif (key_event.key_number == 10) and key_event.pressed: # Select Button
machine.go_to_state("menu")
return
elif (key_event.key_number == 11) and key_event.pressed: # Volume Button
print("TODO: Decide what the volume button does")
key_event = keys.events.get()

neopixels.show()
neopixels.show()
self.poll_encoders()
1 change: 0 additions & 1 deletion Software/Production/SequencerState.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,6 @@ def edit_sequence(self, fsequences):
file_sequences.show_sequence(selected_sequence)
neopixels.show()


# Exit on click of select encoder
key_event = keys.events.get()
if key_event and key_event.pressed and key_event.key_number == 10:
Expand Down
2 changes: 2 additions & 0 deletions Software/Production/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
select_enc,
volume_enc,
)

# from audiocore import WaveFile
from StartupState import StartupState
from FlashyState import FlashyState
from MIDIState import MIDIState
Expand Down

0 comments on commit 8f5613d

Please sign in to comment.