Skip to content

Instantly share code, notes, and snippets.

@darrylsloan
Last active October 14, 2020 00:56
Show Gist options
  • Save darrylsloan/76fc4410e85215b15133e85190ee0238 to your computer and use it in GitHub Desktop.
Save darrylsloan/76fc4410e85215b15133e85190ee0238 to your computer and use it in GitHub Desktop.
Music sequencer for the BBC micro:bit
# MUSIC SEQUENCER by Darryl Sloan (30/11/2017)
# Step 1: press A to toggle the first note of the desired scale, then B to select.
# Step 2: press A to toggle the time signature (3/4, 4/4 or 5/4), then B to select.
# Step 3: press A to toggle the desired number of patterns (1 to 4), then B to select.
# Press A to move the range of notes selected. Press B to randomise the selected notes.
# The direction of tilt determines which scale the random notes conform to:
# Left = minor; right = major; forward = minor pentatonic; backward = major pentatonic.
# While holding A during the first note of the sequence, tilting up/down increases/decreases the tempo,
# tilting left/right selects a lower/higher octave.
# While holding A, tap B to show the notes in English for transcription purposes.
from microbit import *
import music
import random
octave = 3
tempo_adjust = 90
music.set_tempo(bpm = tempo_adjust)
selection = 0
pattern = 0
all_notes = ("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B")
major = (0, 2, 4, 5, 7, 9, 11)
minor = (0, 2, 3, 5, 7, 8, 10)
major_pent = (0, 2, 4, 7, 9)
minor_pent = (0, 3, 5, 7, 10)
scale_major = ["", "", "", "", "", "", ""]
scale_minor = ["", "", "", "", "", "", ""]
scale_major_pent = ["", "", "", "", ""]
scale_minor_pent = ["", "", "", "", ""]
# User selects scale
scale = 0
display.scroll("Scale")
while True:
display.show(all_notes[scale])
if button_a.was_pressed():
scale += 1
if scale == 12:
scale = 0
if button_b.was_pressed():
break
for i in range(7):
scale_major[i] = all_notes[major[i]]
scale_minor[i] = all_notes[minor[i]]
for i in range(5):
scale_major_pent[i] = all_notes[major_pent[i]]
scale_minor_pent[i] = all_notes[minor_pent[i]]
notes = scale_major
# User selects time signature
beat = 4
display.scroll("Beat")
while True:
display.show(str(beat))
if button_a.was_pressed():
beat += 1
if beat == 6:
beat = 3
riff_length = beat*4
if button_b.was_pressed():
break
# User selects quantity of patterns
patterns = 1
display.scroll("Patterns")
while True:
display.show(str(patterns))
if button_a.was_pressed():
patterns += 1
if patterns == 5:
patterns = 1
if button_b.was_pressed():
break
# Load example riff
sequence = []
default = [all_notes[scale]+"4"]
for i in range(beat-1):
default += [all_notes[scale]+"3"]
for i in range(patterns*4):
sequence += default
while True:
x, y = 0, 0
for i in range(riff_length):
# Refresh display
display.clear()
display.set_pixel(pattern, 4, 9)
for highlight in range(beat):
display.set_pixel(highlight, selection, 5)
display.set_pixel(x, y, 9)
# User reveals notes in English
if button_a.is_pressed() and button_b.was_pressed():
for p in range(patterns):
text = ""
for q in range(8):
display.show(str(p+1))
sleep(200)
display.clear()
sleep(200)
for j in range(riff_length):
text += sequence[j+(pattern*riff_length)]+" "
display.scroll(text)
# User adjusts octave or tempo
if i == 0 and button_a.is_pressed():
if accelerometer.get_x() < 0 and abs(accelerometer.get_y()) < abs(accelerometer.get_x()) and octave > 1:
octave -= 1
if accelerometer.get_x() > 0 and abs(accelerometer.get_y()) < abs(accelerometer.get_x()) and octave < 6:
octave += 1
if accelerometer.get_y() < 0 and abs(accelerometer.get_x()) < abs(accelerometer.get_y()) and tempo_adjust < 200:
tempo_adjust += 10
if accelerometer.get_y() > 0 and abs(accelerometer.get_x()) < abs(accelerometer.get_y()) and tempo_adjust > 60:
tempo_adjust -= 10
music.set_tempo(bpm = tempo_adjust)
# User changes current selection
if button_a.was_pressed():
selection += 1
if selection == 4:
selection = 0
# User randomises selected notes
if button_b.was_pressed():
if accelerometer.get_x() < 0 and abs(accelerometer.get_y()) < abs(accelerometer.get_x()):
notes = scale_minor
if accelerometer.get_x() > 0 and abs(accelerometer.get_y()) < abs(accelerometer.get_x()):
notes = scale_major
if accelerometer.get_y() < 0 and abs(accelerometer.get_x()) < abs(accelerometer.get_y()):
notes = scale_minor_pent
if accelerometer.get_y() > 0 and abs(accelerometer.get_x()) < abs(accelerometer.get_y()):
notes = scale_major_pent
for r in range(selection*beat, selection*beat+beat):
sequence[r+(pattern*riff_length)] = random.choice(notes)+str(random.randint(octave, octave+1))
# Play current note
music.play(sequence[i+(pattern*riff_length)]+":1")
# Move playhead forward by 1
x += 1
if x == beat:
x = 0
y += 1
if y == 4:
y = 0
# Move pattern forward by 1
if x == 0 and y == 0:
pattern += 1
if pattern == patterns:
pattern = 0
@QuantumStar
Copy link

This is so awesome, I can't believe how complete this program is for something that fits on a Micro:Bit! I'm going to have so much fun playing with this, thank you :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment