Skip to content

Commit a05a990

Browse files
Merge pull request prathimacode-hub#1008 from theshredbox/main
Scale Chart for Musical Composition
2 parents 00dd1c0 + 58169d9 commit a05a990

File tree

7 files changed

+271
-0
lines changed

7 files changed

+271
-0
lines changed
354 KB
Loading
41 KB
Loading
127 KB
Loading
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# 🎼 **SCALE CHART FOR MUSICAL COMPOSITION**
2+
<p align="center">
3+
<img width="500" height="300" src="https://media.giphy.com/media/EA4ZexjGOnfP2/giphy.gif">
4+
</p>
5+
6+
## :ideograph_advantage: **INTRODUCTION**
7+
* Beginners in the field of music learning, especially guitar learners face a lot of dilemma on where to begin with and many at times they lose a track of their learning which makes learning a complicated task. So to cut this slack off, we come with an easy, yet an efficient interface that would facilitate better learning.
8+
* Python 3 and Tk can be used for building a creative application that visually represents different scales, notes, modes, and keys. Such tools are particularly common for string instruments like the guitar. Here, the users can navigate different scales (major, natural minor, harmonic minor, pentatonic, blues, etc.) and chords (5 chords, major, minor, diminished, augmented, and so on) on a 24- fret chart. The purpose of this project is to create a program with which you can find the position of the notes of a given scale in the guitar. 
9+
10+
## :question: **WHAT IS TKINTER ?**
11+
Python offers multiple options for developing GUI (Graphical User Interface). Out of all the GUI methods, tkinter is the most commonly used method. It is a standard Python interface to the Tk GUI toolkit shipped with Python. Python with tkinter is the fastest and easiest way to create the GUI applications. Creating a GUI using tkinter is an easy task.
12+
13+
## **WHY EXACTLY DO WE NEED A SCALE CHART ?**
14+
Pretend that you can imagine the spectrum of audible sound, and try to divide it into a musical system that makes sense for you and everyone around you. This is not easy! After centuries of struggle, humans have come up with a system but there are still disputes going on. Using the intervals of a given scale as index, we can retrieve the notes that make up the scale. This is all you need to understand. We will be applying this principle over and over again to extract the notes that compose a given scale. Using this information, we will then plot where these notes are located in the guitar. These plots all together make a SCALE CHART.
15+
<p align="center">
16+
<img width="500" height="300" src="https://user-images.githubusercontent.com/36481036/135743837-ef05b516-cb7b-409b-adec-6ab39fa94a8e.png">
17+
</p>
18+
19+
20+
## :bookmark: **MODULE DESCRIPTION**
21+
* The project being a GUI based application is made using Tkinter, a Python binding to the GUI toolkit. We started off from scratch and saw how we can use lists, dictionaries to build a tool that can help us play the guitar. We all know Music theory is a complex subject made up of a lot of components. For the purposes of this post, we will be simplifying things here quite a bit.
22+
* Here we will treat the fretboard as a UX Component and treat it as an image.  Based on the design guidelines and the test variations, we introduce potential flaws in direct correlation to the design input. These flawed design mockups are manifested as images. Proper labeling of these images ensure proper organization of test data. Once we have a minimal set of images in our arsenal, we are ready to train our model.
23+
24+
![workflow](https://user-images.githubusercontent.com/36481036/135594695-dcba5d00-fc95-4ae8-abec-7d8d28ed54d5.png)
25+
26+
## :bulb: **STEPS FOLLOWED**
27+
1. The first and the most important step was to import the tkinter package and the OrderedDict package.
28+
2. Then we needed to define the notes that would help us to get a Note name from 0-11 INT.
29+
3. After entering the name of the scales in a rotated sorted array, we return a scale of 16 notes.
30+
4. Then we set the default scale and the offnote.
31+
5. When the user wants to change the scale, we need to reset the window and redraw the table. And also highlight the tabs that must be played.
32+
6. Until now we have created all the required fundamentals that will be the modules of the GUI. After this, we configure our main window.
33+
34+
35+
## :white_check_mark: **HOW TO USE ?**
36+
Import the code and in the command line type <code> python scale_chart_code.py> </code>
37+
38+
## :chart_with_upwards_trend: **ADVATANGES OF THE INTERFACE**
39+
* It will be easy way to create chromatic scales (without typing them explicitly).
40+
* We can play any scale we want to without having to google it all the time.
41+
* It will be very useful in teaching students in musical school.
42+
* Easy understanding and learning of musical instruments is possible through this project.
43+
* Common people can learn any musical instrument without attending any coaching or workshops.
44+
* It will help to produce quality music.
45+
* Combining music with high end programming technologies might help create a global impact on the music industry.
46+
47+
## :key: **PREQUISITES**
48+
All the dependencies and required libraries are included in the file <code>requirements.txt</code> [See here](./requirements.txt)
49+
50+
## :round_pushpin: **CODE OUTPUTS**
51+
<p align="center">
52+
<img width="600" height="300" src="https://user-images.githubusercontent.com/36481036/135593785-f8abbb1e-03fb-4176-aab9-e6e5eeba9600.png">
53+
54+
</p>
55+
56+
57+
<p align="center">
58+
<img width="600" height="250" src="https://user-images.githubusercontent.com/36481036/135593790-730c662a-2926-4afb-a2f4-9a4bf7e27738.png">
59+
60+
</p>
61+
62+
<p align="center">
63+
<img width="3000" height="300" src="https://user-images.githubusercontent.com/36481036/135742600-16311aaa-5a85-4612-8c41-e3927fbf22f2.gif">
64+
65+
</p>
66+
67+
## :bust_in_silhouette: **CREDITS & REFERENCES**
68+
* https://github.com/crawsome/GuitarScaleChart
69+
* https://tkdocs.com/
70+
* https://github.com/kevinadi/scales
71+
* https://giphy.com/
72+
73+
**:sunglasses:** **CREATOR**- https://github.com/theshredbox
74+
75+
76+
77+
78+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[1008/214643.214:ERROR:file_io.cc(90)] ReadExactly: expected 36, observed 0
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
tkinter==8.6.10
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
#python3
2+
import sys
3+
from tkinter import *
4+
from collections import OrderedDict
5+
6+
7+
# This program creates a guitar scale gui from grid elements, and fills them in color-coded appropriately.
8+
9+
# Get Note name from a 0-11 INT
10+
def getnotename(tonename):
11+
notedict = ['E ', 'F ', 'F#', 'G ', 'Ab',
12+
'A ', 'Bb', 'B ', 'C ', 'Db', 'D ', 'Eb']
13+
return notedict[tonename % 12]
14+
15+
16+
# Contains int offsets, based on note string, added for convenience, which
17+
# is simply offset relative to C.
18+
def getoffset_tonename(tonename):
19+
scaleref = {
20+
'E ': 0, 'F ': 1, 'F#': 2, 'G ': 3, 'Ab': 4, 'A ': 5, 'Bb': 6, 'B ': 7, 'C ': 8, 'Db': 9, 'D ': 10,
21+
'Eb': 11}
22+
23+
24+
return scaleref[tonename]
25+
26+
27+
# Return array that is rotated circular
28+
def rotate(l, n):
29+
return l[-n:] + l[:-n]
30+
31+
32+
scales = OrderedDict([
33+
('Major', [0, 2, 2, 1, 2, 2, 2, 1]),
34+
('Natural minor', [0, 2, 1, 2, 2, 1, 2, 2]),
35+
('Harmonic minor', [0, 2, 1, 2, 2, 1, 3, 1]),
36+
('Melodic minor', [0, 2, 1, 2, 2, 2, 2, 2]),
37+
('Dorian mode', [0, 2, 1, 2, 2, 2, 1, 2]),
38+
('Phrygian mode', [0, 1, 2, 2, 2, 1, 2, 2]),
39+
('Lydian mode', [0, 2, 2, 2, 1, 2, 2, 1]),
40+
('Mixolydian mode', [0, 2, 2, 1, 2, 2, 1, 2]),
41+
('Locrian mode', [0, 1, 2, 2, 1, 2, 2, 2]),
42+
('Ahava raba mode', [0, 1, 3, 1, 2, 1, 2, 2]),
43+
('Minor pentatonic', [0, 3, 2, 2, 3, 2]),
44+
('Pentatonic', [0, 2, 2, 3, 2, 3]),
45+
('Blues', [0, 3, 2, 1, 1, 3]),
46+
('5 chord', [0, 7]),
47+
('Major chord', [0, 4, 3]),
48+
('Minor chord', [0, 3, 4]),
49+
('Diminished chord', [0, 3, 3]),
50+
('Augmented chord', [0, 4, 4]),
51+
('Sus2 chord', [0, 2, 5]),
52+
('Sus4 chord', [0, 5, 2]),
53+
('Maj7 chord', [0, 4, 3, 4]),
54+
('min7 chord', [0, 3, 4, 3]),
55+
('7 chord', [0, 4, 3, 3]),
56+
('min7b5 chord', [0, 3, 3, 4]),
57+
('dim7 chord', [0, 3, 3, 3]),
58+
('9 chord', [0, 4, 3, 3, 4]),
59+
('Maj9 chord', [0, 4, 3, 4, 3]),
60+
('m9 chord', [0, 3, 4, 3, 4]),
61+
('11 chord', [0, 4, 3, 3, 4, 3]),
62+
('Maj11 chord', [0, 4, 3, 4, 3, 3]),
63+
('min11 chord', [0, 3, 4, 3, 4, 3]),
64+
])
65+
66+
# returns a scale of 16 notes, from the key tonic + 24
67+
68+
69+
def makescale(keyroot, keyopt):
70+
keywheel = []
71+
keywheel.extend(scales[keyopt])
72+
filler = 0
73+
# fill array with 16 notes relevant to key and option.
74+
ourscale = []
75+
lenvar = len(keywheel) # of notes we use (2 octaves of key notes)
76+
for inte in range(lenvar):
77+
filler += keywheel[inte % len(keywheel)]
78+
ourscale.append(int(filler + getoffset_tonename(keyroot)))
79+
return ourscale
80+
81+
82+
# fetches a default scale
83+
ourscale = makescale('E ', 'Major')
84+
85+
# Used for note offsets
86+
e = 0
87+
88+
# high e = (e+4), b = (e-1), g = (e+7), d = (e+2),a = (e+9), low e = (e+4)
89+
# added to each string to offset and identify the notes.
90+
offsetArray = [e, e + 7, e + 3, e + 10, e + 5, e]
91+
92+
# default e Major
93+
chartgui = Tk()
94+
95+
# our callback variables that change when menu options are selected
96+
variable = StringVar(chartgui)
97+
variable.set('E ')
98+
variable2 = StringVar(chartgui)
99+
variable2.set('Major')
100+
101+
102+
# variable3 = StringVar(chartgui)
103+
# variable3.set('View 1')
104+
105+
106+
# for clearing all our values, used for the "Reset" button.
107+
def resettable():
108+
print("Tried to reset!")
109+
for i in range(0, 25):
110+
for gss in range(0, 6):
111+
Label(chartgui, text=getnotename(i + offsetArray[gss]), bg='tan').grid(
112+
row=gss + 2, column=i + 1, padx=0, pady=0)
113+
114+
115+
# redraw our whole scale, the action for the "Apply" button
116+
def applyit(val):
117+
print("Trying to apply!")
118+
# print("var1 = %s"%variable.get())
119+
# print("var2 = %s"%variable2.get())
120+
# print("var3 = %s"%variable3.get())
121+
ourtonic = str(variable.get())
122+
ourkey = str(variable2.get())
123+
print(ourtonic)
124+
print(ourkey)
125+
126+
ourscale = makescale(ourtonic, ourkey)
127+
print(ourscale)
128+
ournotes = []
129+
130+
for notes in ourscale:
131+
ournotes.append(getnotename(notes))
132+
133+
print (ournotes)
134+
135+
# draw our whole scale
136+
for i in range(0, 25):
137+
for gss in range(0, 6):
138+
start = offsetArray[gss]
139+
140+
# draw lawngreen for roots
141+
if ourtonic == getnotename(i + start % 12):
142+
Label(
143+
chartgui, text=getnotename(i + start), bg='lawngreen').grid(row=gss + 2, column=i + 1,
144+
padx=0, pady=0)
145+
# draw cyan for notes in the scale
146+
elif getnotename(i + start) in ournotes:
147+
Label(
148+
chartgui, text=getnotename(i + start), bg='cyan').grid(row=gss + 2, column=i + 1,
149+
padx=0, pady=0)
150+
# only write notename
151+
else:
152+
Label(chartgui, text=getnotename(i + start), bg='tan').grid(
153+
row=gss + 2, column=i + 1, padx=0, pady=0)
154+
155+
156+
if __name__ == "__main__":
157+
158+
chartgui.geometry('700x300+400+300')
159+
chartgui.title('Guitarex- Playing Made Easier ')
160+
chartgui.configure(bg= 'tan')
161+
ourx = 40
162+
oury = 20
163+
chartgui.iconbitmap(r'C:\Users\Aryan\Downloads\IMG_20200108_094316_201.jpg')
164+
165+
# For our fret (column) labels on top and bottom
166+
for i in range(0, 25):
167+
Label(chartgui, text=i, font='boulder', bg='tan').grid(
168+
row=0, column=i + 1, padx=0, pady=10)
169+
Label(chartgui, text=i, font='boulder', bg='tan').grid(
170+
row=9, column=i + 1, padx=0, pady=10)
171+
172+
# For our string (row) labels
173+
stringarray = ['E', 'B', 'G', 'D', 'A', 'E']
174+
for gss in range(0, 6):
175+
Label(chartgui, text=stringarray[gss], font="comicsans", bg='tan').grid(
176+
row=gss + 2, column=0, padx=10, pady=0)
177+
178+
print(ourscale)
179+
180+
# draw our whole scale
181+
applyit("")
182+
183+
keymenu = OptionMenu(
184+
chartgui, variable, 'E ', 'F ', 'F#', 'G ', 'Ab', 'A ', 'Bb', 'B ', 'C ', 'Db', 'D ',
185+
'Eb', command=applyit).place(x=ourx * 4, y=oury * 13)
186+
scalemenu = OptionMenu(chartgui, variable2, *scales.keys(), command=applyit).place(
187+
x=ourx * 6, y=oury * 13)
188+
resetbutton = Button(chartgui, text=' Reset ', command=resettable).place(
189+
x=ourx * 10, y=oury * 13)
190+
191+
chartgui.mainloop()

0 commit comments

Comments
 (0)