def chord_quiz() -> None: note = choice(notes) chord_key, chord_name = choice(list(Chord.names.items())) inp = input(f"Enter space-separated notes for {note} {chord_name}: ") target_chord = Chord(Note(note), chord_key) # TODO: More-intelligent parsing to account for upper-case characters. submission = inp.split(' ') is_correct = are_chords_equal(target_chord, submission) print("You were right!") if is_correct else print("You were wrong.")
def scale_quiz() -> None: note = choice(notes) scale = sample(Scale.greek_modes_set, 1)[0] inp = input(f"Enter space-separateed notess for {note} {scale}: ") correct_scale = Scale(Note(note), scale) correct_notes = [str(correct_scale[i]) for i in range(len(correct_scale))] # TODO: Better answer-checking algorithm if inp.split(' ') == correct_notes: print("You got the correct scale!") else: print("You got it wrong!")
def are_chords_equal(c1: Chord, notes: List[str]) -> bool: """ Returns whether two chords have the same notes in the same order, not considering octave. """ chord_notes = c1.notes if not len(chord_notes) is len(notes): return False for i in range(len(chord_notes)): if not are_notes_equal(chord_notes[i], Note(notes[i])): return False return True
from musthe import Note, Chord from typing import List def are_notes_equal(n1: Note, n2: Note) -> bool: """ Returns whether `n1` and `n2` are the same note, disregarding octave or enharmonic equivalence. Checks note name and accidental value to determine this equality. """ letters_equal = n1.letter == n2.letter accidentals_equal = n1.accidental == n2.accidental return letters_equal and accidentals_equal assert (are_notes_equal(Note("A4"), Note("A4"))) assert (are_notes_equal(Note("E#3"), Note("E#5"))) assert (not are_notes_equal(Note("B#"), Note("C"))) def are_chords_equal(c1: Chord, notes: List[str]) -> bool: """ Returns whether two chords have the same notes in the same order, not considering octave. """ chord_notes = c1.notes if not len(chord_notes) is len(notes): return False for i in range(len(chord_notes)):
# player.play_note("A", 0.2) # To play a G flat on octave n°3 for 2.5 seconds # player.play_note("G3b", 2.5) # To play a F sharp on octave n°5 for the default duration of 0.5 seconds # player.play_note("F5#") # To pause the player for 3.5 seconds # player.play_note("pause", 3.5) play_with_musicalBeeps = False play_with_rtmidi = True note_len_s = 0.2 root_Note = Note("A4") s = Scale(root_Note, 'major') # Iterating Scales (Original Mode) original_mode_bool = False if original_mode_bool: for scale_ in s.scales.keys(): print('***') print(scale_) cs = Scale(root_Note, scale_) scale_short = [] scale_full = [] frecuency_ = [] for n in cs.notes: scale_short.append(str(n))
from musthe import Note, Interval, scale NOTES = ['C', 'D', 'E', 'F', 'G', 'A', 'B'] ALTERATIONS = ['', 'b', '#'] WTF_NOTES = ['B#', 'E#', 'Fb', 'Cb'] SCALES = ['melodic_minor', 'major', 'harmonic_minor', 'mixolydian', 'dorian', 'lydian', 'major_pentatonic', 'phrygian', 'natural_minor', 'minor_pentatonic', 'locrian'] for n in NOTES: for alt in ALTERATIONS: note = Note(n+alt) if str(note) in WTF_NOTES: continue for s in SCALES: scale_name = s.replace('_', ' ') front = 'The %s scale of %s is...' % (scale_name, str(note)) back = ' '.join(map(str, scale(note, s))) print '\t'.join([front, back])
from musthe import Interval from musthe import Note from musthe import Scale # Notes Define A4 = Note("A4") Eb = Note("Eb") C0 = Note("C0") # number = 0 B0 = Note("B0") # number = 11 C1 = Note('C1') # number = 12 # Intervals Define P1_int = Interval('P1') # 0 semitones P5_int = Interval('P5') # 7 semitones m2_int = Interval('m2') # 2 semitones # Tests 1. Add Interval to a Note test_1 = C0 + P1_int print(test_1) print(test_1.number) print(test_1.octave) # Test 2. Check Octave Value is incremented when a # number surpass current octave test_2 = B0 + P5_int print(test_2) print(test_2.number) print(test_2.octave) # Test 3. Print Scales Notes
if opp == '>': case1 = (a.letter.idx > b.letter.idx) and (a.octave == b.octave) case2 = a.octave > b.octave return case1 or case2 elif opp == '<': case1 = (a.letter.idx < b.letter.idx) and (a.octave == b.octave) case2 = a.octave < b.octave return case1 or case2 possible_keys = ['A', 'C', 'D', 'F', 'G', 'Bb', 'Eb'] possible_tonalities = [ 'major', 'natural_minor', 'harmonic_minor', 'major_pentatonic' ] key = Note(random.choice(possible_keys)) tonality = random.choice(possible_tonalities) tune_chars = list(itertools.product(possible_keys, possible_tonalities)) melodies = [] good_melodies = [] for k, t in tune_chars: k_note = Note(k + '3') possible_notes = [*Scale(k_note, t)][:14] for melody in list(itertools.permutations(possible_notes, 4)): melodies.append((melody, k, t)) lowest = Note('F4') highest = Note('A#5')
def transpose_chord_info(chord_info, pitch, number_of_bars=None): """ Transpose a chord_info string to lilypond chord info e.g.: chord_info: d2:m7 g:7 c1:maj7, with pitch: d => e2:m7 a:7 d1:maj7 chord_info: C7, pitch: d, number_of_bars: 2 => d1:7 d1:7 Note: when using C7 notation (from the riff.chord property) -> number of bars is mandatory return: new lilypond chord string """ # ***************************************************************************************************************** # Todo: expose via REST API -> so the client can use it to calculate the correct lilypond chord info values upon # changing the pitch of an exercise item # ***************************************************************************************************************** notes = { "c": "P1", "cis": "A1", "d": "M2", "ees": "m3", "e": "M3", "f": "P4", "fis": "A4", "g": "P5", "gis": "A5", "aes": "m6", "a": "M6", "bes": "m7", "b": "M7", } to_lilypond = { "c": "c", "cb": "b", "db": "des", "d": "d", "eb": "ees", "e": "e", "a": "a", "ab": "aes", "b": "b", "bb": "bes", "c#": "cis", "c##": "d", "d#": "dis", "e#": "f", "fb": "e", "f": "f", "f#": "fis", "f##": "g", "g": "g", "gb": "fis", "g#": "gis", "g##": "a", "a#": "ais", "b#": "c", } lilypond_mood = {"M": "maj", "m": "m"} if chord_info and len(chord_info) and chord_info[0].isupper(): if len(chord_info) > 1 and (chord_info[1] == "#" or chord_info[1] == "b"): root_key = str(Note(chord_info[0:2]) + Interval(notes[pitch])).lower() o = 1 else: root_key = str(Note(chord_info[0]) + Interval(notes[pitch])).lower() o = 0 if root_key in to_lilypond.keys(): root_key = to_lilypond[root_key] # Done with root key : continue with rest of chord digit = "" separator = ":" if len(chord_info) == 1: chord_mood = "" separator = "" elif chord_info[1 + o].isdigit(): # Handle C7, C#7, Bb7 chord_mood = "" digit = chord_info[1 + o] elif len(chord_info) == 2 + o: # Handle Cm, C#m, Bbm, CM, C#M chord_mood = (lilypond_mood[chord_info[1 + o]] if chord_info[1 + o] in lilypond_mood.keys() else chord_info[1 + o]) elif len(chord_info) == 3 + o: # Handle Cm7, C#m7, CM7, BbM9, Cm9, CM6 chord_mood = (lilypond_mood[chord_info[1 + o]] if chord_info[1 + o] in lilypond_mood.keys() else chord_info[1 + o]) digit = chord_info[2 + o] elif len(chord_info) == 4 + o: # Handle Cmaj chord_mood = chord_info[1 + o:4 + o] elif len(chord_info) == 5 + o: # Handle Cmaj7 chord_mood = chord_info[1 + o:4 + o] digit = chord_info[4 + o] else: logger.info("Couldn't parse chord info", chord_info=chord_info) raise ValueError logger.info("Using chord from riff", root_key=root_key, chord_mood=chord_mood, digit=digit) if not number_of_bars or number_of_bars == 1: return f"{root_key}1{separator}{chord_mood}{digit}" result = [] for i in range(0, number_of_bars): result.append(f"{root_key}1{separator}{chord_mood}{digit}") return " ".join(result) elif chord_info: chords = chord_info.split(" ") logger.info("Using chord-info in lilypond format", chords=chords, pitch=pitch) result = [] for chord in chords: if ":" in chord: root_key, chord_mood = chord.split(":") # 3 case: c1, cis2, c and cis duration = "" numbers = re.findall(r'\d+', root_key) if len(numbers): # print(numbers) duration = numbers[0] # print(f"Duration: {duration}") root_key = root_key.replace("1", "").replace("2", "").capitalize() if root_key.endswith("is"): root_key = root_key[0] + "#" if root_key.endswith("es"): root_key = root_key[0] + "b" new_root_key = str(Note(root_key) + Interval(notes[pitch])).lower() # print(new_root_key) if new_root_key in to_lilypond.keys(): new_root_key = to_lilypond[new_root_key] # simplify some chords if new_root_key == "dis": new_root_key = "ees" if new_root_key == "gis": new_root_key = "aes" if new_root_key == "ais": new_root_key = "bes" if new_root_key == "des": new_root_key = "cis" new_root_key = f"{new_root_key}{duration}" else: print(f"Error with {new_root_key}") 1 / 0 result.append(f"{new_root_key}:{chord_mood}") else: # handle lilypond chords without mode like "c1" root_key = chord duration = "" numbers = re.findall(r'\d+', root_key) if len(numbers): # print(numbers) duration = numbers[0] # print(f"Duration: {duration}") root_key = root_key.replace("1", "").replace("2", "").capitalize() if root_key.endswith("is"): root_key = root_key[0] + "#" if root_key.endswith("es"): root_key = root_key[0] + "b" new_root_key = str(Note(root_key) + Interval(notes[pitch])).lower() # print(new_root_key) if new_root_key in to_lilypond.keys(): new_root_key = to_lilypond[new_root_key] # simplify some chords if new_root_key == "dis": new_root_key = "ees" if new_root_key == "gis": new_root_key = "aes" if new_root_key == "ais": new_root_key = "bes" if new_root_key == "des": new_root_key = "cis" new_root_key = f"{new_root_key}{duration}" else: print(f"Error with {new_root_key}") 1 / 0 result.append(new_root_key) # else: # logger.error("Expected ':' in chord", chord=chord, complete_chord_info=chord_info) # result.append(f"Error in:{chord}") return " ".join(result)