#!/usr/bin/env python # mzk music theory helper - developed by acidvegas in python (https://acid.vegas/mzk) # functions.py import constants def generate_notes(key): notes = ['A','A#','B','C','C#','D','D#','E','F','F#','G','G#'] while notes[0] != key: notes.append(notes.pop(0)) return notes def generate_scale(string, scale_notes, full=False): notes = generate_notes(string.upper())*2 if full else generate_notes(string.upper()) notes.append(notes[0]) # add root note to the end for index,note in enumerate(notes): if note in scale_notes: notes[index] = notes[index].center(5, '-') else: notes[index] = '-'*5 return notes def get_pattern(pattern): new_pattern = list() for step in pattern: if step == '1' : new_pattern.append('H') elif step == '2' : new_pattern.append('W') elif step == '3' : new_pattern.append('WH') return ' '.join(new_pattern) def scale(type, key): last = 0 notes = generate_notes(key) scale_notes = [notes[0],] for step in scales[type]: last += int(step) if last >= len(notes): last -= len(notes) scale_notes.append(notes[last]) return scale_notes def print_chord(): # todo: finish this print('◯ ⬤ ') print('''╳ ╳ ╳ ╳ ╳ ╳ ┌───┬───┬───┬───┬───┐ │ │ │ │ │ │ ├───┼───┼───┼───┼───┤ │ │ │ │ │ │ ├───┼───┼───┼───┼───┤ │ │ │ │ │ │ ├───┼───┼───┼───┼───┤ │ │ │ │ │ │ ├───┼───┼───┼───┼───┤ │ │ │ │ │ │ └───┴───┴───┴───┴───┘ E A D G B e''') def print_circle_of_fifths(): ''' definition: the relationship among the 12 tones of the chromatic scale, their corresponding key signatures, & the associated major/minor keys accidentals: sharps - F, C, G, D, A, E, B flats - B, E, A, D, G, C, F intervals: unison perfect fifth major sencond major sixth major third major seventh augmented fourth minor second minor sixth minor third minor seventh perfect fourth ''' circle = constants.circle.replace('\n',' \n') + ' ' # todo: fix this for note in ('major','C','F','B♭','E♭','A♭','D♭','C♯','G♭/F♯','B','C♭','E','A','D','G'): # todo: reverse circle = circle.replace(f' {note} ', f' \033[91m{note}\033[0m ') for item in ('♮','1♭','2♭','3♭','4♭','5♭/7♯','6♭/6♯','7♭/5♯','4','3♯','2♯','1♯'): circle = circle.replace(f' {item} ', f' \033[90m{item}\033[0m ') for note in ('minor','a','d','g','c','f','b♭','e♭/d♯','g♯','c♯','f♯','b','c'): circle = circle.replace(f' {note} ', f' \033[92m{note}\033[0m ') print(circle) #print(print_circle_of_fifths.__doc__) def print_intervals(): ''' definition: the distance between two notes or pitches note: semitone - half step tone - whole step (b to c & e to f is a tone) types: harmonic interval - notes played simultaneously melodic interval - notes played successively makeup: quantity - distance between two notes quality - number of semitones between notes qualities: major/minor - 2nds, 3rds, 6ths, 7ths perfect - 4ths, 5ths, octaves diminished - minor/perfect - 1 semitone augmented - major/perfect + 1 semitone ''' print(' I N T E R V A L S ') print('┌───────────┬──────────────────┬───────┐') print('│ semitones │ quality │ short │') print('├───────────┼──────────────────┼───────┤') for interval, info in constants.intervals.items(): print('│ {0} │ {1} │ {2} │'.format(str(info['semitones']).rjust(9), interval.ljust(16), info['short_name'].ljust(5))) print('└───────────┴──────────────────┴───────┘') #print(print_intervals.__doc__) def print_scale(root, type, full=False): frets = (24,147) if full else (12,75) print(f'{root.upper()} {type.upper()} SCALE'.center(frets[1])) print(' ┌' + '┬'.join('─'*5 for x in range(frets[0])) + '┐') print('0 │' + '│'.join(str(x).center(5) for x in range(1,frets[0]+1)) + '│') print(' ├' + '┼'.join('─'*5 for x in range(frets[0])) + '┤') scale_notes = scale(type, root) for string in ('eBGDAE'): string_notes = generate_scale(string, scale_notes, full) print(string + ' │' + '│'.join(note.center(5, '-') for note in string_notes[1:]) + '│') print(' └' + '┴'.join('─'*5 for x in range(frets[0])) + '┘') print((', '.join(scale_notes) + ' / ' + get_pattern(scales[type])).rjust(frets[1])) def print_scales(): ''' definition: any set of musical notes ordered by fundamental frequency or pitch note: 1 - half step 2 - whole step 3 - whole step half step''' print(' S C A L E S ') print('┌───────────────────────┬─────────────────┐') print('│ name │ intervals │') print('├───────────────────────┼─────────────────┤') for name, pattern in constants.scales.items(): print(f'│ {name.ljust(21)} │ {get_pattern(pattern).rjust(15)} │') print('└───────────────────────┴─────────────────┘') #print(print_scales.__doc__)