Ableton Control Surface for Roland TD-27KV2 Drum Kit This script provides a basic mapping for the Roland TD-27KV2 drum kit. TD27.py Save TD27.py in \Resources\MIDI Remote Scripts\TD27\ from __future__ import absolute_import, print_function, unicode_literals from _Framework.ControlSurface import ControlSurface from _Framework.InputControlElement import MIDI_NOTE_TYPE, MIDI_CC_TYPE from _Framework.ButtonElement import ButtonElement from _Framework.EncoderElement import EncoderElement from _Framework.TransportComponent import TransportComponent from _Framework.DeviceComponent import DeviceComponent from _Framework.MidiMap import MidiMap from _Framework.Layer import Layer class TD27(ControlSurface): def __init__(self, c_instance): ControlSurface.__init__(self, c_instance) self.log_message("Roland TD-27 Control Surface Initialized") with self.component_guard(): self._setup_midi_map() self._setup_transport_control() self._setup_device_control() def _setup_midi_map(self): self._drum_pads = { "Kick_Drum": ButtonElement(True, MIDI_NOTE_TYPE, 9, 36), "Snare_Drum": ButtonElement(True, MIDI_NOTE_TYPE, 9, 38), "Snare_Rim": ButtonElement(True, MIDI_NOTE_TYPE, 9, 40), "Snare_Brush": ButtonElement(True, MIDI_NOTE_TYPE, 9, 37), "Snare_CrossStick": ButtonElement(True, MIDI_NOTE_TYPE, 9, 39), "Tom1_Drum": ButtonElement(True, MIDI_NOTE_TYPE, 9, 48), "Tom1_Rim": ButtonElement(True, MIDI_NOTE_TYPE, 9, 50), "Tom2_Drum": ButtonElement(True, MIDI_NOTE_TYPE, 9, 45), "Tom2_Rim": ButtonElement(True, MIDI_NOTE_TYPE, 9, 47), "Tom3_Drum": ButtonElement(True, MIDI_NOTE_TYPE, 9, 43), "Tom3_Rim": ButtonElement(True, MIDI_NOTE_TYPE, 9, 58), "HiHat_Bow": ButtonElement(True, MIDI_NOTE_TYPE, 9, 46), "HiHat_Edge": ButtonElement(True, MIDI_NOTE_TYPE, 9, 26), "HiHat_ClosedEdge": ButtonElement(True, MIDI_NOTE_TYPE, 9, 42), "HiHat_Pedal": ButtonElement(True, MIDI_NOTE_TYPE, 9, 44), "Ride_Bow": ButtonElement(True, MIDI_NOTE_TYPE, 9, 51), "Ride_Edge": ButtonElement(True, MIDI_NOTE_TYPE, 9, 59), "Ride_Bell": ButtonElement(True, MIDI_NOTE_TYPE, 9, 53), "Crash1_Bow": ButtonElement(True, MIDI_NOTE_TYPE, 9, 49), "Crash1_Edge": ButtonElement(True, MIDI_NOTE_TYPE, 9, 57), "Crash2_Bow": ButtonElement(True, MIDI_NOTE_TYPE, 9, 81), "Crash2_Edge": ButtonElement(True, MIDI_NOTE_TYPE, 9, 82), "Ride_Choke": ButtonElement(True, MIDI_NOTE_TYPE, 9, 51), "Crash1_Choke": ButtonElement(True, MIDI_NOTE_TYPE, 9, 49), "Crash2_Choke": ButtonElement(True, MIDI_NOTE_TYPE, 9, 57), } self._positional_controls = { "Snare_Position": EncoderElement(MIDI_CC_TYPE, 9, 1, MidiMap.MapMode.absolute), "Tom1_Position": EncoderElement(MIDI_CC_TYPE, 9, 18, MidiMap.MapMode.absolute), "Tom2_Position": EncoderElement(MIDI_CC_TYPE, 9, 19, MidiMap.MapMode.absolute), "Tom3_Position": EncoderElement(MIDI_CC_TYPE, 9, 11, MidiMap.MapMode.absolute), "HiHat_Pedal": EncoderElement(MIDI_CC_TYPE, 9, 4, MidiMap.MapMode.absolute), "HiHat_LR_Position": EncoderElement(MIDI_CC_TYPE, 9, 16, MidiMap.MapMode.absolute), "Ride_Position": EncoderElement(MIDI_CC_TYPE, 9, 11, MidiMap.MapMode.absolute), } self._other_controls = { "Modulation": ButtonElement(True, MIDI_CC_TYPE, 9, 1), "Breath_Controller": ButtonElement(True, MIDI_CC_TYPE, 9, 2), "Foot_Controller": ButtonElement(True, MIDI_CC_TYPE, 9, 4), "Expression": ButtonElement(True, MIDI_CC_TYPE, 9, 11), "General_Purpose_Controller_1": ButtonElement(True, MIDI_CC_TYPE, 9, 16), "General_Purpose_Controller_2": ButtonElement(True, MIDI_CC_TYPE, 9, 17), "General_Purpose_Controller_3": ButtonElement(True, MIDI_CC_TYPE, 9, 18), "General_Purpose_Controller_4": ButtonElement(True, MIDI_CC_TYPE, 9, 19), "General_Purpose_Controller_5": ButtonElement(True, MIDI_CC_TYPE, 9, 80), "General_Purpose_Controller_6": ButtonElement(True, MIDI_CC_TYPE, 9, 81), "General_Purpose_Controller_7": ButtonElement(True, MIDI_CC_TYPE, 9, 82), "General_Purpose_Controller_8": ButtonElement(True, MIDI_CC_TYPE, 9, 83), "High_Resolution_Velocity": ButtonElement(True, MIDI_CC_TYPE, 9, 88), } def _setup_transport_control(self): self._transport = TransportComponent() self._transport.layer = Layer( play_button=self._drum_pads["Kick_Drum"], stop_button=self._drum_pads["Snare_Drum"], ) def _setup_device_control(self): self._device = DeviceComponent() self._device.layer = Layer( parameter_controls=[ self._positional_controls["Snare_Position"], self._positional_controls["HiHat_Pedal"], self._positional_controls["Ride_Position"], self._other_controls["Modulation"], self._other_controls["Breath_Controller"], self._other_controls["Foot_Controller"], self._other_controls["Expression"], self._other_controls["General_Purpose_Controller_1"], self._other_controls["General_Purpose_Controller_2"], self._other_controls["General_Purpose_Controller_3"], self._other_controls["General_Purpose_Controller_4"], self._other_controls["General_Purpose_Controller_5"], self._other_controls["General_Purpose_Controller_6"], self._other_controls["General_Purpose_Controller_7"], self._other_controls["General_Purpose_Controller_8"], ] ) def disconnect(self): self.log_message("Roland TD-27 Control Surface Disconnected") ControlSurface.disconnect(self) _ init.py Save _init.py_ to \Resources\MIDI Remote Scripts\TD27\ from __future__ import absolute_import, print_function, unicode_literals from .TD27 import TD27 def create_instance(c_instance): return TD27(c_instance) We can extend the above with a Kontakt script to enhance the expressiveness of the Roland TD-27KV2 control surface. on init message("Roland TD-27KV2 Kontakt Script Initialized") declare const $KICK_NOTE := 36 declare const $SNARE_NOTE := 38 declare const $SNARE_RIM_NOTE := 40 declare const $HH_CLOSED_NOTE := 42 declare const $HH_PEDAL_NOTE := 44 declare const $HH_OPEN_NOTE := 46 declare const $TOM1_NOTE := 48 declare const $TOM2_NOTE := 45 declare const $TOM3_NOTE := 43 declare const $CRASH1_NOTE := 49 declare const $CRASH2_NOTE := 57 declare const $RIDE_BOW_NOTE := 51 declare const $RIDE_BELL_NOTE := 53 declare $velocity declare $position declare $hh_openness declare ui_knob $snare_pos_sens (0, 100, 1) set_knob_unit($snare_pos_sens, $KNOB_UNIT_PERCENT) set_knob_defval($snare_pos_sens, 50) declare ui_knob $cymbal_choke_time (0, 1000, 1) set_knob_unit($cymbal_choke_time, $KNOB_UNIT_MS) set_knob_defval($cymbal_choke_time, 50) declare ui_switch $use_cc_hihat set_text($use_cc_hihat, "Use CC for Hi-Hat") end on on note $velocity := $EVENT_VELOCITY select ($EVENT_NOTE) case $SNARE_NOTE $position := get_controller(16) // Assuming CC 16 for snare position $velocity := $velocity + (($position - 64) * $snare_pos_sens / 100) $velocity := max(1, min(127, $velocity)) case $HH_CLOSED_NOTE, $HH_OPEN_NOTE if ($use_cc_hihat = 1) $hh_openness := get_controller(4) // Assuming CC 4 for hi-hat pedal $velocity := $velocity * (128 - $hh_openness) / 128 end if case $CRASH1_NOTE, $CRASH2_NOTE, $RIDE_BOW_NOTE, $RIDE_BELL_NOTE start_timer($cymbal_choke_time) // Start choke timer for cymbals end select set_event_par($EVENT_ID, $EVENT_PAR_VOLUME, $velocity * 1000 / 127) end on on controller if ($CC_NUM = 4 and $use_cc_hihat = 1) // Hi-hat pedal CC $hh_openness := $CC_VALUE set_engine_par($ENGINE_PAR_CUTOFF, $hh_openness * 1000 / 127, 0, 0, -1) end if end on on timer // Implement cymbal choking fade_out(0, 10000, 1) // Fade out all groups over 10ms end on on ui_control($use_cc_hihat) if ($use_cc_hihat = 1) message("Hi-Hat control set to CC mode") else message("Hi-Hat control set to velocity mode") end if end on Buy me a coffee Don’t be shy; if you found this useful, say Hi!