Compare commits

...

10 Commits

Author SHA1 Message Date
Dionysus 57bbc0ef4e
Updated mirrors and LICENSE 2024-01-20 20:48:05 -05:00
Dionysus 385132b9e2
Making progress on chord generation 2023-05-18 20:30:06 -04:00
Dionysus 400703d72f
Making progress on chord generation 2023-05-18 20:29:41 -04:00
Dionysus 703aacb1d5
Updated git url & added mirrors 2023-05-08 23:59:37 -04:00
Dionysus e9326b22d9
fixed casing 2019-07-25 02:36:58 -04:00
Dionysus f2506cd785
print compound intervals 2019-07-25 02:36:25 -04:00
Dionysus 99519b0d9e
fixed double octave type 2019-07-25 02:35:55 -04:00
Dionysus ff5d07b842
added compound intervals 2019-07-25 02:32:18 -04:00
Dionysus 47e74cd31f
fixed help function name 2019-07-25 02:12:59 -04:00
Dionysus b2c7601714
fixed 2019-07-25 02:11:43 -04:00
9 changed files with 127 additions and 50 deletions

View File

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 88 KiB

View File

Before

Width:  |  Height:  |  Size: 168 KiB

After

Width:  |  Height:  |  Size: 168 KiB

View File

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View File

@ -1,6 +1,6 @@
ISC License ISC License
Copyright (c) 2019, acidvegas <acid.vegas@acid.vegas> Copyright (c) 2024, acidvegas <acid.vegas@acid.vegas>
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above

View File

@ -1,17 +1,31 @@
# mzk # mzk
> music theory helper > music theory helper
![](screens/circle.png) ![](.screens/circle.png)
![](screens/intervals_scales.png) ![](.screens/intervals_scales.png)
![](screens/scale.png) ![](.screens/scale.png)
## Information ## Information
This repository originally started off as a means of using Python to learn music theory, specifcally guitar theory, since the basis of musical sound can be described mathematically *(in acoustics)* and exhibits a remarkable array of number properties. This repository originally started off as a means of using Python to learn music theory, specifcally guitar theory, since the basis of musical sound can be described mathematically *(in acoustics)* and exhibits a remarkable array of number properties.
It is still a work in progress, so some functions and features may not work as excepted or at all. Would love some collaboration on this project! It is still a work in progress, so some functions and features may not work as excepted or at all. Would love some collaboration on this project!
## Notes
A chromatic scale is comprised of all the semitones between an octave:
A A# B C C# D D# E F F# G G#
Using the root of C, we can apply the pattern of the major scale to the C chromatic scale:
C C# D D# E F F# G G# A A# B C
C D E F G A B C
W W H W W W H
## Todo ## Todo
* Dynamic table sizing based on item/key lengths * Dynamic table sizing based on item/key lengths
* Finish chord generation * Finish chord generation
* Color support for windows * Color support for windows
* Scale/chord ASCII coloring * Scale/chord ASCII coloring
___
###### Mirrors for this repository: [acid.vegas](https://git.acid.vegas/mzk) • [SuperNETs](https://git.supernets.org/acidvegas/mzk) • [GitHub](https://github.com/acidvegas/mzk) • [GitLab](https://gitlab.com/acidvegas/mzk) • [Codeberg](https://codeberg.org/acidvegas/mzk)

View File

@ -1,7 +1,25 @@
#!/usr/bin/env python #!/usr/bin/env python
# mzk music theory helper - developed by acidvegas in python (https://acid.vegas/mzk) # mzk music theory helper - developed by acidvegas in python (https://git.acid.vegas/mzk)
# constants.py # constants.py
chords = {
'major' : {'symbol':'', 'pattern':'1 3 5'},
'minor' : {'symbol':'m', 'pattern':'1 b3 5'},
'7th' : {'symbol':'7', 'pattern':'1 3 5 b7'},
'minor_7th' : {'symbol':'m7', 'pattern':'1 b3 5 b7'},
'major_7th' : {'symbol':'maj7', 'pattern':'1 3 5 7'},
'minor_7th_flat_5th' : {'symbol':'m7b5', 'pattern':'1 b3 b5 b7'},
'suspended_4th' : {'symbol':'sus4', 'pattern':'1 4 5'},
'diminished' : {'symbol':'dim', 'pattern':'1 b3 b5'},
'augmented' : {'symbol':'aug', 'pattern':'1 3 #5'},
'6th' : {'symbol':'6', 'pattern':'1 3 5 6'},
'minor_6th' : {'symbol':'m6', 'pattern':'1 b3 5 6'},
'minor_6th_add_9th' : {'symbol':'6add9', 'pattern':'1 3 5 6 9'},
'9th' : {'symbol':'9', 'pattern':'1 3 5 b7 9'},
'minor_9th' : {'symbol':'m9', 'pattern':'1 b3 5 b7 9'},
'major_9th' : {'symbol':'maj9', 'pattern':'1 3 5 7 9'}
}
circle = ''' major circle = ''' major
C C
@ -34,6 +52,21 @@ colors = {
'reset' : '\033[0m' 'reset' : '\033[0m'
} }
compound_intervals = {
'minor_ninth' : {'semitones':13, 'short_name':'m9'},
'major_ninth' : {'semitones':14, 'short_name':'M9'},
'minor_tenth' : {'semitones':15, 'short_name':'m10'},
'major_tenth' : {'semitones':16, 'short_name':'M10'},
'perfect_eleventh' : {'semitones':17, 'short_name':'P11'},
'augmented_eleventh' : {'semitones':18, 'short_name':'TT'},
'perfect_twelfth' : {'semitones':19, 'short_name':'P12'},
'minor_thirteenth' : {'semitones':20, 'short_name':'m13'},
'major_thirteenth' : {'semitones':21, 'short_name':'M13'},
'minor_fourteenth' : {'semitones':22, 'short_name':'m14'},
'major_fourteenth' : {'semitones':23, 'short_name':'M14'},
'double_octave' : {'semitones':24, 'short_name':'15ma'}
}
intervals = { intervals = {
'perfect_unison' : {'semitones':0, 'short_name':'P1'}, 'perfect_unison' : {'semitones':0, 'short_name':'P1'},
'minor_second' : {'semitones':1, 'short_name':'m2'}, 'minor_second' : {'semitones':1, 'short_name':'m2'},
@ -50,7 +83,7 @@ intervals = {
'perfect_octave' : {'semitones':12, 'short_name':'P8'} 'perfect_octave' : {'semitones':12, 'short_name':'P8'}
} }
notes = ('A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#') notes = ('A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#') # Chromatic scale
numerals = ('I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI', 'XII') numerals = ('I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI', 'XII')
scale_degrees = ('tonic','supertonic','mediant','subdominant','dominant''submediant','subtonic') scale_degrees = ('tonic','supertonic','mediant','subdominant','dominant''submediant','subtonic')
@ -58,7 +91,6 @@ scales = {
'algerian' : '2131131', 'algerian' : '2131131',
'aeolian' : '2122122', 'aeolian' : '2122122',
'blues' : '321132', 'blues' : '321132',
'chromatic' : '1111111',
'dorian' : '2122212', 'dorian' : '2122212',
'half_whole_diminished' : '12121212', 'half_whole_diminished' : '12121212',
'harmonic_minor' : '2122131', 'harmonic_minor' : '2122131',
@ -74,4 +106,4 @@ scales = {
'phrygian' : '1222122', 'phrygian' : '1222122',
'whole_half_diminished' : '21212121', 'whole_half_diminished' : '21212121',
'whole_tone' : '2222222' 'whole_tone' : '2222222'
} }

View File

@ -1,17 +1,17 @@
#!/usr/bin/env python #!/usr/bin/env python
# mzk music theory helper - developed by acidvegas in python (https://acid.vegas/mzk) # mzk music theory helper - developed by acidvegas in python (https://git.acid.vegas/mzk)
# functions.py # functions.py
import constants import constants
def generate_notes(key): def chromatic_scale(key):
notes = ['A','A#','B','C','C#','D','D#','E','F','F#','G','G#'] notes = list(constants.notes)
while notes[0] != key: while notes[0] != key:
notes.append(notes.pop(0)) notes.append(notes.pop(0))
return notes return notes
def generate_scale(string, scale_notes, full=False): def generate_scale_string(string, scale_notes, full=False):
notes = generate_notes(string.upper())*2 if full else generate_notes(string.upper()) notes = chromatic_scale(string.upper())*2 if full else chromatic_scale(string.upper())
notes.append(notes[0]) notes.append(notes[0])
for index,note in enumerate(notes): for index,note in enumerate(notes):
if note in scale_notes: if note in scale_notes:
@ -28,18 +28,43 @@ def get_pattern(pattern):
elif step == '3' : new_pattern.append('WH') elif step == '3' : new_pattern.append('WH')
return ' '.join(new_pattern) return ' '.join(new_pattern)
def scale(type, key): def chord_notes(type, key):
notes = scale_notes(type, key)
pattern = constants.chords[type]['pattern']
_notes = [key,]
for step in pattern.split()[1:]: #1 b3 5
if len(step) == 2:
if step[:1] == 'b':
_notes.append(notes[int(step)-2])
elif step[:1] == '#':
_notes.append(notes[int(step)])
else:
_notes.append(notes[int(step)-1])
return _notes
def print_scale(root, type, full=False, chord=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])) + '')
notes = chord_notes(type, root) if chord else scale_notes(type, root)
for string in ('eBGDAE'):
string_notes = generate_scale_string(string, 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(notes) + ' / ' + get_pattern(constants.scales[type])).rjust(frets[1]))
def scale_notes(type, key):
last = 0 last = 0
notes = generate_notes(key) all_notes = chromatic_scale(key)*2
scale_notes = [notes[0],] scale_notes = [all_notes[0],]
for step in constants.scales[type]: for step in constants.scales[type]:
last += int(step) last += int(step)
if last >= len(notes): scale_notes.append(all_notes[last])
last -= len(notes)
scale_notes.append(notes[last])
return scale_notes return scale_notes
def print_chord(): def print_chord(root, type):
# todo: finish this # todo: finish this
print('◯ ⬤ ') print('◯ ⬤ ')
print(''' print('''
@ -55,6 +80,20 @@ def print_chord():
E A D G B e''') E A D G B e''')
print(''' ◯ ◯
E A D G B e''')
def print_circle_of_fifths(): def print_circle_of_fifths():
'''definition: '''definition:
@ -87,7 +126,7 @@ def print_circle_of_fifths():
print(circle) print(circle)
print(print_circle_of_fifths.__doc__) print(print_circle_of_fifths.__doc__)
def help(): def print_help():
print('usage: python mzk.py [OPTIONS]') print('usage: python mzk.py [OPTIONS]')
print('\noptions:') print('\noptions:')
print('--chord=KEY_TYPE │ print a TYPE chord in the key of KEY') print('--chord=KEY_TYPE │ print a TYPE chord in the key of KEY')
@ -125,21 +164,15 @@ def print_intervals():
for interval, info in constants.intervals.items(): for interval, info in constants.intervals.items():
print('{0}{1}{2}'.format(str(info['semitones']).rjust(9), interval.ljust(14), info['short_name'].ljust(5))) print('{0}{1}{2}'.format(str(info['semitones']).rjust(9), interval.ljust(14), info['short_name'].ljust(5)))
print('└───────────┴────────────────┴───────┘') print('└───────────┴────────────────┴───────┘')
print('\nC O M P O U N D I N T E R V A L S'.center(42))
print('┌───────────┬────────────────────┬───────┐')
print('│ semitones │ quality │ short │')
print('├───────────┼────────────────────┼───────┤')
for interval, info in constants.compound_intervals.items():
print('{0}{1}{2}'.format(str(info['semitones']).rjust(9), interval.ljust(18), info['short_name'].ljust(5)))
print('└───────────┴────────────────────┴───────┘')
print(print_intervals.__doc__) 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(constants.scales[type])).rjust(frets[1]))
def print_scales(): def print_scales():
'''definition: '''definition:
any set of musical notes ordered by fundamental frequency or pitch any set of musical notes ordered by fundamental frequency or pitch
@ -155,6 +188,4 @@ def print_scales():
for name, pattern in constants.scales.items(): for name, pattern in constants.scales.items():
print(f'{name.ljust(21)}{get_pattern(pattern).rjust(15)}') print(f'{name.ljust(21)}{get_pattern(pattern).rjust(15)}')
print('└───────────────────────┴─────────────────┘') print('└───────────────────────┴─────────────────┘')
print(print_scales.__doc__) print(print_scales.__doc__)
print_scale('C','major')

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
# mzk music theory helper - developed by acidvegas in python (https://acid.vegas/mzk) # mzk music theory helper - developed by acidvegas in python (https://git.acid.vegas/mzk)
# main.py # main.py
import sys import sys
@ -12,26 +12,26 @@ import functions
if len(sys.argv) != 2: if len(sys.argv) != 2:
functions.print_help() functions.print_help()
else: else:
sys.argv[1] = sys.argv[1].lower() print(sys.argv[1])
if sys.argv[1].startswith('--chord='): if sys.argv[1] == '--chords':
functions.print_chords()
elif sys.argv[1].startswith('--chord='):
chord = sys.argv[1][8:] chord = sys.argv[1][8:]
key = chord.split('_')[0] key = chord.split('_')[0].upper()
type = chord[len(key)+1:] type = chord[len(key)+1:].lower()
if key in constants.notes and type in constants.scales: if key in constants.notes and type in constants.chords:
functions.print_chord(key, type) functions.print_scale(key, type, chord=True)
else: else:
print('error: invalid key or chord type\n\n') print('error: invalid key or chord type\n\n')
functions.print_help() functions.print_help()
elif sys.argv[1] == '--chords':
functions.print_chords()
elif sys.argv[1] == '--circle': elif sys.argv[1] == '--circle':
functions.print_circle() functions.print_circle_of_fifths()
elif sys.argv[1] == '--intervals': elif sys.argv[1] == '--intervals':
functions.print_intervals() functions.print_intervals()
elif sys.argv[1].startswith('--scale='): elif sys.argv[1].startswith('--scale='):
scale = sys.argv[1][8:] scale = sys.argv[1][8:]
key = scale.split('_')[0] key = scale.split('_')[0].upper()
type = scale[len(key)+1:] type = scale[len(key)+1:].lower()
if key in constants.notes and type in constants.scales: if key in constants.notes and type in constants.scales:
functions.print_scale(key, type) functions.print_scale(key, type)
else: else: