Skip to main content
Glama
test_tracks_and_melody.py5.44 kB
#!/usr/bin/env python3 """ Test script for play_pattern_with_tracks_and_melody function Tests combining track triggers and melody notes in a single MIDI clock session """ import asyncio import mido import time # Find Digitakt output port output_port = None for port_name in mido.get_output_names(): if "Elektron Digitakt II" in port_name: output_port = mido.open_output(port_name) print(f"✓ Connected to MIDI output: {port_name}") break if not output_port: print("✗ Could not find Digitakt MIDI output port") exit(1) # Helper function for delayed note off async def _delayed_note_off(note: int, duration: float, channel: int = 0): """Send note off after a delay""" await asyncio.sleep(duration) if output_port: output_port.send(mido.Message('note_off', note=note, velocity=0, channel=channel)) async def test_tracks_and_melody(): """Test combining track triggers and melody notes""" print("\n" + "="*70) print("TEST: play_pattern_with_tracks_and_melody") print("="*70) print("Playing 5 bars at 120 BPM:") print(" - 1-bar count-in on track 15 (beats 0-3)") print(" - 4-bar melody (beats 4-19)") print() bars = 5 bpm = 120 # 1-bar count-in on track 15 (click track) track_triggers = [ [0, 15, 100], # beat 0, track 15, velocity 100 [1, 15, 100], # beat 1 [2, 15, 100], # beat 2 [3, 15, 100], # beat 3 ] # 4-bar melody (simple ascending scale) melody_notes = [ # Bar 2 (beats 4-7) [4, 60, 85, 0.4], # C [5, 62, 80, 0.4], # D [6, 64, 85, 0.4], # E [7, 65, 80, 0.4], # F # Bar 3 (beats 8-11) [8, 67, 85, 0.4], # G [9, 69, 80, 0.4], # A [10, 71, 85, 0.4], # B [11, 72, 90, 0.4], # C (octave) # Bar 4 (beats 12-15) [12, 71, 85, 0.4], # B [13, 69, 80, 0.4], # A [14, 67, 85, 0.4], # G [15, 65, 80, 0.4], # F # Bar 5 (beats 16-19) [16, 64, 85, 0.4], # E [17, 62, 80, 0.4], # D [18, 60, 85, 0.4], # C [19, 60, 90, 0.8], # C (longer) ] # Calculate timing clock_interval = 60.0 / (bpm * 24) total_pulses = int(bars * 96) channel = 0 # Use channel 0 for melody # Prepare combined event schedule event_schedule = [] # Add track triggers for trigger_data in track_triggers: beat = trigger_data[0] track = trigger_data[1] velocity = trigger_data[2] pulse_index = int(beat * 24) note = track - 1 # Track 15 = note 14 event_schedule.append(("track", pulse_index, note, velocity, 0.05, 0)) # Add melody notes for note_data in melody_notes: beat = note_data[0] note = note_data[1] velocity = note_data[2] duration = note_data[3] pulse_index = int(beat * 24) event_schedule.append(("melody", pulse_index, note, velocity, duration, channel)) # Sort all events by pulse index event_schedule.sort(key=lambda x: x[1]) print(f"Total events scheduled: {len(event_schedule)}") print(f" - Track triggers: {len(track_triggers)}") print(f" - Melody notes: {len(melody_notes)}") print() # Send Start message output_port.send(mido.Message('start')) start_time = time.time() event_idx = 0 trigger_count = 0 melody_count = 0 # Send clock pulses and all scheduled events for i in range(total_pulses): output_port.send(mido.Message('clock')) # Check if we need to send any events at this pulse while event_idx < len(event_schedule) and event_schedule[event_idx][1] == i: event_type, pulse, note, velocity, duration, ch = event_schedule[event_idx] output_port.send(mido.Message('note_on', note=note, velocity=velocity, channel=ch)) asyncio.create_task(_delayed_note_off(note, duration, ch)) if event_type == "track": trigger_count += 1 else: melody_count += 1 event_idx += 1 # Calculate when next pulse should occur next_pulse_time = start_time + (i + 1) * clock_interval sleep_duration = next_pulse_time - time.time() if sleep_duration > 0: await asyncio.sleep(sleep_duration) # Send Stop output_port.send(mido.Message('stop')) print(f"✓ Playback complete!") print(f" - Sent {trigger_count} track triggers") print(f" - Sent {melody_count} melody notes") print(f" - Total events: {trigger_count + melody_count}") print() async def main(): """Run the test""" print("Digitakt II play_pattern_with_tracks_and_melody Test") print("="*70) print("Make sure your Digitakt II has:") print(" - Sample loaded on track 15 (for count-in)") print(" - Active track set to a melodic sample") print(" - TRANSPORT RECEIVE enabled") print(" - CLOCK RECEIVE enabled") print() await test_tracks_and_melody() print("="*70) print("✓ Test complete!") print("="*70) print() print("Did you hear:") print(" 1. Four count-in clicks on track 15?") print(" 2. An ascending and descending scale melody?") print(" 3. Both overlapping correctly?") print() output_port.close() if __name__ == "__main__": asyncio.run(main())

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/feamster/digitakt-midi-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server