mirror of
https://github.com/kennethreitz/notebooks.git
synced 2026-06-20 23:10:58 +00:00
1 line
8.9 KiB
Plaintext
1 line
8.9 KiB
Plaintext
{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"notes-and-scales.ipynb","version":"0.3.2","provenance":[],"collapsed_sections":[]},"kernelspec":{"name":"python3","display_name":"Python 3"}},"cells":[{"cell_type":"markdown","metadata":{"colab_type":"text","id":"_EMGkCYzn9UY"},"source":["# A Premier on PyTheory\n","\n","PyTheory is a music theory library, which procedurally generates all known Western tones, scales, and chord fingering charts (for custom fretboards).\n","\n","It is capable of outputting either a rounded decimal for pitch representation, or the *proper* symbolic representation of the pitch (as a SymPy object).\n","\n","\n","## Install PyTheory:"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[{"name":"stdout","output_type":"stream","text":"Requirement already satisfied: pytheory in /usr/local/anaconda3/lib/python3.7/site-packages (0.1.2)\nRequirement already satisfied: requests in /usr/local/anaconda3/lib/python3.7/site-packages (2.22.0)\nRequirement already satisfied: pytuning in /usr/local/anaconda3/lib/python3.7/site-packages (from pytheory) (0.7.2)\nRequirement already satisfied: scipy in /usr/local/anaconda3/lib/python3.7/site-packages (from pytheory) (1.4.1)\nRequirement already satisfied: pygame in /usr/local/anaconda3/lib/python3.7/site-packages (from pytheory) (1.9.6)\nRequirement already satisfied: numeral in /usr/local/anaconda3/lib/python3.7/site-packages (from pytheory) (0.1.0.11)\nRequirement already satisfied: idna<2.9,>=2.5 in /usr/local/anaconda3/lib/python3.7/site-packages (from requests) (2.8)\nRequirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/anaconda3/lib/python3.7/site-packages (from requests) (1.24.2)\nRequirement already satisfied: chardet<3.1.0,>=3.0.2 in /usr/local/anaconda3/lib/python3.7/site-packages (from requests) (3.0.4)\nRequirement already satisfied: certifi>=2017.4.17 in /usr/local/anaconda3/lib/python3.7/site-packages (from requests) (2019.9.11)\nRequirement already satisfied: numpy in /usr/local/anaconda3/lib/python3.7/site-packages (from pytuning->pytheory) (1.17.2)\nRequirement already satisfied: sympy in /usr/local/anaconda3/lib/python3.7/site-packages (from pytuning->pytheory) (1.4)\nRequirement already satisfied: mpmath>=0.19 in /usr/local/anaconda3/lib/python3.7/site-packages (from sympy->pytuning->pytheory) (1.1.0)\n"}],"source":["!pip install pytheory requests"]},{"cell_type":"markdown","metadata":{"colab_type":"text","id":"c1duUNkKoGOA"},"source":["## Import PyTheory:"]},{"cell_type":"code","execution_count":2,"metadata":{},"outputs":[],"source":["from pytheory import TonedScale"]},{"cell_type":"markdown","metadata":{"colab_type":"text","id":"VZQzVX0UoG7f"},"source":["Let's reference a great key (and the only one I can play on piano), A Minor:\n"]},{"cell_type":"code","execution_count":3,"metadata":{},"outputs":[{"data":{"text/plain":"<Scale I=G#4 II=A#5 III=B5 IV=C#5 V=D#5 VI=E5 VII=F#5 VIII=G#5>"},"execution_count":3,"metadata":{},"output_type":"execute_result"}],"source":["a_min = TonedScale(tonic=\"G#4\")[\"minor\"]\n","a_min"]},{"cell_type":"markdown","metadata":{"colab_type":"text","id":"oSmNsjmSogOt"},"source":["Let's reference another great key, C Major:"]},{"cell_type":"code","execution_count":4,"metadata":{},"outputs":[{"data":{"text/plain":"<Scale I=C4 II=D4 III=E4 IV=F4 V=G4 VI=A5 VII=B5 VIII=C5>"},"execution_count":4,"metadata":{},"output_type":"execute_result"}],"source":["c_maj = TonedScale(tonic=\"C4\")[\"major\"]\n","c_maj"]},{"cell_type":"markdown","metadata":{"colab_type":"text","id":"8HUSLP8Qpx5J"},"source":["That's interesting, they contain all the same notes! \n","\n","----------------\n","\n","Let's see if we can automatically detect what the modal correspondents are to A Minor:"]},{"cell_type":"code","execution_count":5,"metadata":{},"outputs":[],"source":["from pytheory import SYSTEMS\n","\n","def get_scale(tonic, mode):\n"," return TonedScale(tonic=tonic)[mode]\n","\n","def get_all_scales(octave=4): \n"," scales = []\n"," \n"," # Iterate over all 12 tones of the Western system: \n"," for tone in SYSTEMS[\"western\"].tones:\n"," \n"," # Create a scale for each tone.\n"," new_scale = TonedScale(tonic=f\"{tone.name}{octave}\")\n"," \n"," for mode in new_scale._scales.keys():\n"," # Create every possible permutation of the scale. \n"," newest_scale = TonedScale(tonic=f\"{tone.name}{octave}\")[mode]\n"," \n"," # (tone, mode, scale) tuple. \n"," scales.append((tone, mode, newest_scale))\n"," \n"," return scales\n","\n","\n","def get_matches_filter(scale):\n"," \n"," def get_good_tones(scale):\n"," good_tones = list(scale.tones)\n","\n"," # Add an upper and lower octave to the list of good known tones. \n"," for i in range(len(SYSTEMS[\"western\"].tones)):\n"," good_tones.append(good_tones[i].add(12))\n"," good_tones.append(good_tones[i].add(-12))\n"," \n"," return good_tones\n","\n"," def matches_the_key(tmst):\n"," # Expand the (tone, mode, scale) tuple. \n"," tone, mode, other_scale = tmst\n","\n"," trusted = True\n"," good_tones = get_good_tones(scale)\n"," \n"," # Iterate over each tone: \n"," for tone in other_scale.tones:\n","\n"," # If the tone isn't in a set of known good tones, don't trust it.\n"," if tone not in good_tones:\n"," trusted = False\n","\n"," return trusted\n"," \n"," return matches_the_key"]},{"cell_type":"code","execution_count":0,"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":210},"colab_type":"code","executionInfo":{"elapsed":2648,"status":"ok","timestamp":1552130376196,"user":{"displayName":"Kenneth Reitz","photoUrl":"https://lh6.googleusercontent.com/-qNz3MhUV36k/AAAAAAAAAAI/AAAAAAAAAGo/76Jc7mhFY4w/s64/photo.jpg","userId":"08676952092761616435"},"user_tz":300},"id":"fHqLEp0c-s49","outputId":"56474657-9cbf-4bad-91a9-1c55efe8e176"},"outputs":[{"name":"stdout","output_type":"stream","text":["Scales that match A minor:\n","\n","A# ionian: <Scale I=A#4 II=B4 III=C#4 IV=D#4 V=E4 VI=F#4 VII=G#4 VIII=A#5>\n","A# aeolian: <Scale I=A#4 II=B4 III=C#4 IV=D#4 V=E4 VI=F#4 VII=G#4 VIII=A#5>\n","B major: <Scale I=B4 II=C#4 III=D#4 IV=E4 V=F#4 VI=G#4 VII=A#5 VIII=B5>\n","D# dorian: <Scale I=D#4 II=E4 III=F#4 IV=G#4 V=A#5 VI=B5 VII=C#5 VIII=D#5>\n","E phrygian: <Scale I=E4 II=F#4 III=G#4 IV=A#5 V=B5 VI=C#5 VII=D#5 VIII=E5>\n","F# lydian: <Scale I=F#4 II=G#4 III=A#5 IV=B5 V=C#5 VI=D#5 VII=E5 VIII=F#5>\n","G# minor: <Scale I=G#4 II=A#5 III=B5 IV=C#5 V=D#5 VI=E5 VII=F#5 VIII=G#5>\n","G# locrian: <Scale I=G#4 II=A#5 III=B5 IV=C#5 V=D#5 VI=E5 VII=F#5 VIII=G#5>\n","G# mixolydian: <Scale I=G#4 II=A#5 III=B5 IV=C#5 V=D#5 VI=E5 VII=F#5 VIII=G#5>\n"]}],"source":["# Here's the good stuff:\n","scale = get_scale(tonic=\"G#4\", mode=\"minor\")\n","\n","print(f\"Scales that match A minor:\\n\")\n","\n","for tmst in filter(get_matches_filter(scale), get_all_scales()):\n"," tone, mode, other_scale = tmst\n"," \n"," # Filter out chromatic scales. \n"," if len(other_scale.tones) == len(scale.tones):\n"," print(f\"{tone.name} {mode}: {other_scale}\")"]},{"cell_type":"markdown","metadata":{"colab_type":"text","id":"C8aWpnu98HOh"},"source":["## Playing With Pitch:\n","\n","PyTheory also supports some advanced pitch exploration:"]},{"cell_type":"code","execution_count":6,"metadata":{},"outputs":[{"data":{"text/plain":"<Scale I=C4 II=D4 III=D#4 IV=F4 V=G4 VI=G#4 VII=A#5 VIII=C5>"},"execution_count":6,"metadata":{},"output_type":"execute_result"}],"source":["c_min = TonedScale(tonic='C4')['minor']\n","c_min"]},{"cell_type":"code","execution_count":7,"metadata":{},"outputs":[{"data":{"text/plain":"<Tone G4>"},"execution_count":7,"metadata":{},"output_type":"execute_result"}],"source":["g4 = c_min[\"mixolydian\"]\n","g4"]},{"cell_type":"code","execution_count":8,"metadata":{},"outputs":[{"data":{"text/latex":"$\\displaystyle 783.990871963499$","text/plain":"783.990871963499"},"execution_count":8,"metadata":{},"output_type":"execute_result"}],"source":["# Rounded decimal.\n","g4.pitch()"]},{"cell_type":"code","execution_count":9,"metadata":{},"outputs":[{"data":{"text/latex":"$\\displaystyle 440 \\cdot 2^{\\frac{5}{6}}$","text/plain":"440*2**(5/6)"},"execution_count":9,"metadata":{},"output_type":"execute_result"}],"source":["g4.pitch(symbolic=True)"]},{"cell_type":"code","execution_count":0,"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":35},"colab_type":"code","executionInfo":{"elapsed":411,"status":"ok","timestamp":1550575271429,"user":{"displayName":"Kenneth Reitz","photoUrl":"https://lh6.googleusercontent.com/-qNz3MhUV36k/AAAAAAAAAAI/AAAAAAAAAGo/76Jc7mhFY4w/s64/photo.jpg","userId":"08676952092761616435"},"user_tz":300},"id":"Ek1Jj9EA98Hc","outputId":"a03b1ec3-d901-4a91-93e5-fc60f39568da"},"outputs":[{"data":{"text/plain":["7040/9"]},"execution_count":11,"metadata":{"tags":[]},"output_type":"execute_result"}],"source":["g4.pitch(temperament=\"pythagorean\", symbolic=True)"]}]} |