Created
October 28, 2024 11:24
-
-
Save artfwo/01bb77bfc94c99c849c246e20d1ba747 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
#! /usr/bin/env python3 | |
def get_scale_note(scale, step, offset=0): | |
octave, scale_index = divmod(step, len(scale)) | |
result = scale[scale_index] | |
offset_step = -1 if offset < 0 else 1 | |
while offset != 0: | |
while True: | |
octave, result = divmod(result + offset_step + (octave * 12), 12) | |
if result not in scale: | |
break | |
offset = offset - offset_step | |
result += octave * 12 | |
return result | |
import unittest | |
class TestScaleNote(unittest.TestCase): | |
def test_get_scale_note(self): | |
scale = [0, 2, 4, 5, 7, 9, 11] | |
self.assertEqual(get_scale_note(scale, 0), 0) | |
self.assertEqual(get_scale_note(scale, 3), 5) | |
self.assertEqual(get_scale_note(scale, 6), 11) | |
self.assertEqual(get_scale_note(scale, 7), 12) | |
self.assertEqual(get_scale_note(scale, 13), 23) | |
self.assertEqual(get_scale_note(scale, 14), 24) | |
self.assertEqual(get_scale_note(scale, -1), -1) | |
self.assertEqual(get_scale_note(scale, -4), -7) | |
self.assertEqual(get_scale_note(scale, -7), -12) | |
self.assertEqual(get_scale_note(scale, -8), -13) | |
def test_get_scale_note_offset(self): | |
scale = [0, 2, 4, 5, 7, 9, 11] | |
self.assertEqual(get_scale_note(scale, 3, -1), 3) | |
self.assertEqual(get_scale_note(scale, 3, -2), 1) | |
self.assertEqual(get_scale_note(scale, 3, -3), -2) | |
self.assertEqual(get_scale_note(scale, 10, 1), 18) | |
self.assertEqual(get_scale_note(scale, 10, 2), 20) | |
self.assertEqual(get_scale_note(scale, 10, 3), 22) | |
if __name__ == '__main__': | |
unittest.main() |
@TriplEight thanks! It depends on how familiar you are with music software in general and what's your target platform :)
For the most basic setup you could probably get a MIDI synth, such as SurgeXT.
Then maybe install python-rtmidi. It should show the synthesiser port if you run the following snippet:
import rtmidi
midiout = rtmidi.MidiOut()
print(midiout.get_ports())
You can then send notes to the port as described in this example:
https://github.com/SpotlightKid/python-rtmidi?tab=readme-ov-file#usage-example
If you'd like to snap them to a scale you can use this function as follows:
root = 36
scale = [0, 2, 4, 5, 7, 9, 11]
import time
for step in range(7):
note = root + get_scale_note(scale, step)
midiout.send_message([0x90, note, 127])
time.sleep(0.5)
midiout.send_message([0x80, note, 0])
time.sleep(0.5)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I found your pres on BHNT #100 awesome! And this snippet is linked there.
Could you please describe how to play with it?