commit 04a1f6e01876eaee762033ca2f9ed372d8d99c2d Author: acidvegas Date: Sat Jul 13 18:52:23 2019 -0400 Initial commit diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..69997e8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2019, acidvegas + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/mzk/constants.py b/mzk/constants.py new file mode 100644 index 0000000..670489d --- /dev/null +++ b/mzk/constants.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# mzk music theory helper - developed by acidvegas in python (https://acid.vegas/mzk) +# constants.py + +circle = ''' major + + C + F G + ♮ + 1♭ 1♯ + a + B♭ d c D + 2♭ 2♯ + g minor b + + + E♭ 3♭ c f♯ 3♯ A + + + f c♯ + 4♭ 4 + A♭ b♭ g♯ E + e♭/d♯ + 5♭/7♯ 7♭/5♯ + 6♭/6♯ + D♭ B + G♭/F♯ + C♯ C♭''' + +colors = { + 'gray' : '\033[0;90m', + 'red' : '\033[0;91m', + 'green' : '\033[0;92m', + 'reset' : '\033[0m' +} + +intervals = { + 'unison' : {'semitones':0, 'short_name':'P1' }, + 'minor_second' : {'semitones':1, 'short_name':'m2' }, + 'major_second' : {'semitones':2, 'short_name':'M2' }, + 'minor_third' : {'semitones':3, 'short_name':'m3' }, + 'major_third' : {'semitones':4, 'short_name':'M3' }, + 'perfect_fourth' : {'semitones':5, 'short_name':'P4' }, + 'augmented_fourth' : {'semitones':6, 'short_name':'+4' }, + 'diminished_fifth' : {'semitones':6, 'short_name':'d5' }, + 'perfect_fifth' : {'semitones':7, 'short_name':'P5' }, + 'minor_sixth' : {'semitones':8, 'short_name':'m6' }, + 'major_sixth' : {'semitones':9, 'short_name':'M6' }, + 'minor_seventh' : {'semitones':10, 'short_name':'m7' }, + 'major_seventh' : {'semitones':11, 'short_name':'M7' }, + 'perfect_octave' : {'semitones':12, 'short_name':'8va'} +} + +notes = ('A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#' ) +numerals = ('I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI', 'XII' ) +scale_degrees = ('tonic','supertonic','mediant','subdominant','dominant''submediant','subtonic') + +scales = { + 'algerian' : '2131131', + 'aeolian' : '2122122', + 'blues' : '321132', + 'chromatic' : '1111111', + 'dorian' : '2122212', + 'half_whole_diminished' : '12121212', + 'harmonic_minor' : '2122131', + 'ionian' : '2212221', + 'locrian' : '1221222', + 'lydian' : '2221221', + 'major' : '2212221', + 'major_pentatonic' : '22323', + 'melodic_minor' : '2122221', + 'mixolydian' : '2212212', + 'natural_minor' : '2122122', + 'persian' : '1311231', + 'phrygian' : '1222122', + 'whole_half_diminished' : '21212121', + 'whole_tone' : '2222222' +} \ No newline at end of file diff --git a/mzk/functions.py b/mzk/functions.py new file mode 100644 index 0000000..b3cf09a --- /dev/null +++ b/mzk/functions.py @@ -0,0 +1,153 @@ +#!/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__) \ No newline at end of file diff --git a/mzk/main.py b/mzk/main.py new file mode 100644 index 0000000..ab013d2 --- /dev/null +++ b/mzk/main.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python +# mzk music theory helper - developed by acidvegas in python (https://acid.vegas/mzk) +# main.py + +import argparser +import sys \ No newline at end of file