Last active
November 25, 2024 16:50
-
-
Save willwade/fb772a9e39f218af0e4035552a29a557 to your computer and use it in GitHub Desktop.
Midi-Switch controller
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
class ViewController: UIViewController { | |
var midiController: MIDIController? | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
// Initialize the MIDI controller | |
midiController = MIDIController() | |
// Example: Send a MIDI Note On and Note Off | |
sendMIDINotes() | |
} | |
func sendMIDINotes() { | |
// Send Note On for MIDI note 60 (Middle C), velocity 127, channel 1 | |
midiController?.sendNoteOn(note: 60, velocity: 127, channel: 0) | |
// Hold the note for 1 second, then send Note Off | |
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { | |
self.midiController?.sendNoteOff(note: 60, velocity: 127, channel: 0) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
import CoreMIDI | |
class MIDIController { | |
private var midiClient: MIDIClientRef = 0 | |
private var midiOutPort: MIDIPortRef = 0 | |
private var destination: MIDIEndpointRef? | |
init() { | |
setupMIDI() | |
} | |
private func setupMIDI() { | |
// Create a MIDI client | |
MIDIClientCreate("MIDIClient" as CFString, nil, nil, &midiClient) | |
// Create an output port | |
MIDIOutputPortCreate(midiClient, "MIDIOutPort" as CFString, &midiOutPort) | |
// Find the first available MIDI destination | |
let destinationCount = MIDIGetNumberOfDestinations() | |
if destinationCount > 0 { | |
destination = MIDIGetDestination(0) | |
} else { | |
print("No MIDI destinations found") | |
} | |
} | |
func sendNoteOn(note: UInt8, velocity: UInt8, channel: UInt8) { | |
guard let destination = destination else { return } | |
// Create a MIDI Note On message | |
var packet = MIDIPacket() | |
packet.timeStamp = 0 | |
packet.length = 3 | |
packet.data.0 = 0x90 | (channel & 0x0F) // Note On message, channel 1 | |
packet.data.1 = note // MIDI note number | |
packet.data.2 = velocity // Velocity | |
var packetList = MIDIPacketList(numPackets: 1, packet: packet) | |
// Send the packet list to the destination | |
MIDIReceived(destination, &packetList) | |
} | |
func sendNoteOff(note: UInt8, velocity: UInt8, channel: UInt8) { | |
guard let destination = destination else { return } | |
// Create a MIDI Note Off message | |
var packet = MIDIPacket() | |
packet.timeStamp = 0 | |
packet.length = 3 | |
packet.data.0 = 0x80 | (channel & 0x0F) // Note Off message, channel 1 | |
packet.data.1 = note // MIDI note number | |
packet.data.2 = velocity // Velocity | |
var packetList = MIDIPacketList(numPackets: 1, packet: packet) | |
// Send the packet list to the destination | |
MIDIReceived(destination, &packetList) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import time | |
import board | |
import digitalio | |
import usb_midi | |
import adafruit_midi | |
from adafruit_midi.note_on import NoteOn | |
from adafruit_midi.note_off import NoteOff | |
# Initialize USB MIDI | |
midi = adafruit_midi.MIDI(midi_in=usb_midi.ports[0], in_channel=0) | |
# Configure GPIO pins for the 3.5mm switch jacks | |
switch_jacks = { | |
"switch_1": digitalio.DigitalInOut(board.D2), | |
"switch_2": digitalio.DigitalInOut(board.D3), | |
"switch_3": digitalio.DigitalInOut(board.D4), | |
"switch_4": digitalio.DigitalInOut(board.D5), | |
} | |
# Set all switch jacks as outputs and default to LOW | |
for switch in switch_jacks.values(): | |
switch.direction = digitalio.Direction.OUTPUT | |
switch.value = False | |
# Define a mapping between MIDI notes and switch jacks | |
midi_to_switch = { | |
60: "switch_1", # MIDI Note 60 -> Switch 1 | |
61: "switch_2", # MIDI Note 61 -> Switch 2 | |
62: "switch_3", # MIDI Note 62 -> Switch 3 | |
63: "switch_4", # MIDI Note 63 -> Switch 4 | |
} | |
# Dictionary to track the current state of each switch (for holding) | |
active_switches = {} | |
def activate_switch(switch_name): | |
"""Activate the specified switch.""" | |
if switch_name in switch_jacks: | |
switch_jacks[switch_name].value = True | |
def deactivate_switch(switch_name): | |
"""Deactivate the specified switch.""" | |
if switch_name in switch_jacks: | |
switch_jacks[switch_name].value = False | |
# Main loop to listen for MIDI signals and control switches | |
while True: | |
# Check for incoming MIDI messages | |
midi_msg = midi.receive() | |
if isinstance(midi_msg, NoteOn): | |
# NoteOn message: activate the corresponding switch | |
note = midi_msg.note | |
if note in midi_to_switch: | |
switch_name = midi_to_switch[note] | |
activate_switch(switch_name) | |
# Record the start time for holding the switch | |
active_switches[switch_name] = time.monotonic() | |
elif isinstance(midi_msg, NoteOff): | |
# NoteOff message: deactivate the corresponding switch | |
note = midi_msg.note | |
if note in midi_to_switch: | |
switch_name = midi_to_switch[note] | |
deactivate_switch(switch_name) | |
# Remove the switch from the active list | |
if switch_name in active_switches: | |
del active_switches[switch_name] | |
# Manage holding logic for active switches | |
for switch_name, start_time in list(active_switches.items()): | |
# Check how long the switch has been held (in seconds) | |
duration = time.monotonic() - start_time | |
if duration > 0: # Optional: Limit max hold duration if needed | |
# For now, we're simply holding the switch as long as NoteOn is held | |
pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment