Microbit Choir
Early experiment in creating a choir for three or more microbits.
Code
from microbit import *
import radio
import music
def separate_note(note):
return note.split(':')
def note_to_midi(note):
note_map = {
'C': 0, 'C#': 1, 'D': 2, 'D#': 3, 'E': 4, 'F': 5, 'F#': 6,
'G': 7, 'G#': 8, 'A': 9, 'A#': 10, 'B': 11
}
# Extract the note and octave from the input
if len(note) == 2:
note_name = note[0]
octave = int(note[1])
elif len(note) == 3:
note_name = note[:2]
octave = int(note[2])
else:
raise ValueError("Invalid note format")
# Calculate the MIDI value
midi_value = note_map[note_name] + (octave + 1) * 12
return midi_value
def midi_to_note_name(midi_value):
note_names = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
note_name = note_names[midi_value % 12]
octave = (midi_value // 12) - 1
return f"{note_name}{octave}"
def is_rest(note):
return note == 'R' or note == 'r'
def harmonize(note, interval):
parts = separate_note(note)
if is_rest(parts[0]):
return note
root = note_to_midi(parts[0])
harmony = root + interval
harmony_note = midi_to_note_name(harmony)
if len(parts) == 2:
return f"{harmony_note}:{parts[1]}"
return harmony_note
def harmonize_all(notes, interval):
if interval == 0:
return notes
harmonized = []
for note in notes:
harmony = harmonize(note, interval)
harmonized.append(harmony)
return notes
def encode_notes_message(notes):
commalist = ','.join(score)
return "NOTES={}".format(commalist)
def decode_notes_message(message):
_, notes = message.split("=")
return notes.split(',')
# notes are
score = ['C4:4', 'D4:4', 'E4:4', 'F4:4', 'G4:4', 'A4:4', 'B4:4']
# choir leader
leader = False
# position = 0
# harmonizer
semi_tones = 0
wallpaper = Image.MUSIC_CROTCHET
display.scroll('Harmony')
display.show(wallpaper)
radio.on()
while True:
if accelerometer.was_gesture('shake'):
leader = not leader
wallpaper = Image.ALL_ARROWS if leader else Image.MUSIC_CROTCHET
display.show(wallpaper)
if leader:
# send out notes
# send out go signal
if button_a.was_pressed():
message = encode_notes_message(score)
radio.send(message)
if button_b.was_pressed():
message = "PLAY"
radio.send(message)
else:
# harmonizer
if button_a.was_pressed():
semi_tones = max(0, semi_tones - 1)
if button_b.was_pressed():
semi_tones = max(semi_tones + 1, 12)
# is this a set of notes?
# is this a control signal
message = radio.receive()
if message:
if message.startswith("NOTES"):
score = decode_notes_message(message)
elif message.startswith("PLAY"):
harmony = harmonize_all(score, semi_tones)
music.play(harmony)
# print(harmonize('C5', 12))