Chord Rules for Jazz?
-
- KVRist
- Topic Starter
- 144 posts since 31 Jan, 2017
Ok!
So…
My geeky project continues. (I’m an ethnomusicologist, not a coder. Still, I get enthusiastic about these things. My guess is that Attila might find this at least amusing.)
Using the JSON files from Mike Oliphant, I was able to extract all the chords from each section of about 1.4k Jazz Standards. The Python script I’ve generated (with help from LLaMa and gpt4o) is included. After creating this in Google Colab, I tested using python3 on my Mac. The resulting CSV is attached in the same zip file.
Now… the next step, very important, is to convert all of these chord names (Dm7, Bbmaj7…) to functional chord names (IIImin7, IVmaj7…). While music21’s harmony module is an obvious choice, in Python context, I need to really understand what chord and key notation works in music21. Code generated by LLMs isn’t able to produce that notation. I’m rather hopeful that I’ll find a way.
Once I have that dataset, I’ll try to do the kind of analysis which will generate a list of “transformations” between chords, with weights for the frequency of occurrence in the dataset.
So…
Imaj7->VImin7 1458
IImin7->V7 1327
…
Imaj7->bIII7 336
With that, I’ll manually create Chord rules, with weights, in RapComp.
And play with them until I get the results I want, from fully expected to fully unexpected (and still Jazz-like).
So…
My geeky project continues. (I’m an ethnomusicologist, not a coder. Still, I get enthusiastic about these things. My guess is that Attila might find this at least amusing.)
Using the JSON files from Mike Oliphant, I was able to extract all the chords from each section of about 1.4k Jazz Standards. The Python script I’ve generated (with help from LLaMa and gpt4o) is included. After creating this in Google Colab, I tested using python3 on my Mac. The resulting CSV is attached in the same zip file.
Now… the next step, very important, is to convert all of these chord names (Dm7, Bbmaj7…) to functional chord names (IIImin7, IVmaj7…). While music21’s harmony module is an obvious choice, in Python context, I need to really understand what chord and key notation works in music21. Code generated by LLMs isn’t able to produce that notation. I’m rather hopeful that I’ll find a way.
Once I have that dataset, I’ll try to do the kind of analysis which will generate a list of “transformations” between chords, with weights for the frequency of occurrence in the dataset.
So…
Imaj7->VImin7 1458
IImin7->V7 1327
…
Imaj7->bIII7 336
With that, I’ll manually create Chord rules, with weights, in RapComp.
And play with them until I get the results I want, from fully expected to fully unexpected (and still Jazz-like).
You do not have the required permissions to view the files attached to this post.
-
- KVRist
- 44 posts since 26 Feb, 2023
Cool, you seem to do something similar as I do.
I am also using RC as a tool to study Jazz Harmony. I am a member of Openstudio and I usually try to enter their voicings and ideas into RC. Together with the note coloring feature you can immediately see how the voicings work (e.g. root-shell voicings).
I have not looked into the chord rules of RC yet. I am just gettings started.
So keep up the Jazz stuff for RC!
Cheers
Jens
P.S.: I play the guitar, a bit of bass and try to get started on the piano (RC is a great way to understand what is actually happening).
I am also using RC as a tool to study Jazz Harmony. I am a member of Openstudio and I usually try to enter their voicings and ideas into RC. Together with the note coloring feature you can immediately see how the voicings work (e.g. root-shell voicings).
I have not looked into the chord rules of RC yet. I am just gettings started.
So keep up the Jazz stuff for RC!
Cheers
Jens
P.S.: I play the guitar, a bit of bass and try to get started on the piano (RC is a great way to understand what is actually happening).
-
- KVRist
- Topic Starter
- 144 posts since 31 Jan, 2017
Got my chord transitions! Will start encoding them as “chord rules”, testing things along the way.
My code needs some refactoring, mostly because my coding skills are really fragmentary. Most of the code came from Gemini in Google Colab, except for the stuff related to music21, which probably doesn’t have enough of a presence in openly available data. Used a clunky way to convert all chords to Roman numerals by splitting the root (Eb, G#…) from the chord quality (m7b5, m11…), converting some characters (music21 uses '-' for flat and minor key is lowercase), and bringing things back together.
I did use all the sections and endings (so A, ending 1, A, ending 2, B…).
I eliminated slash chords (Ebmaj7/G became Ebmaj7). And when there was a chord in parentheses with another one, I treated that as an extra chord.
At any rate, here’s the current code:
My code needs some refactoring, mostly because my coding skills are really fragmentary. Most of the code came from Gemini in Google Colab, except for the stuff related to music21, which probably doesn’t have enough of a presence in openly available data. Used a clunky way to convert all chords to Roman numerals by splitting the root (Eb, G#…) from the chord quality (m7b5, m11…), converting some characters (music21 uses '-' for flat and minor key is lowercase), and bringing things back together.
I did use all the sections and endings (so A, ending 1, A, ending 2, B…).
I eliminated slash chords (Ebmaj7/G became Ebmaj7). And when there was a chord in parentheses with another one, I treated that as an extra chord.
At any rate, here’s the current code:
Code: Select all
from google.colab import drive
import pandas as pd
import json
import glob
import re
from collections import defaultdict
from music21 import *
drive.mount('/content/drive')
def simplify_chord(chord):
"""Simplifies a chord by removing the part after a slash."""
if '/' in chord:
return chord.split('/')[0]
return chord
def split_chord(chord):
match = re.match(r"([a-gA-G]#?b?)(.*)", chord)
if match:
root, quality = match.groups()
return f"{root} {quality}"
else:
return chord
# Path to the folder containing JSON files
folder_path = '/content/drive/MyDrive/JazzStandards/*.json'
# Initialize a dictionary to hold chords for each title and key
title_key_chords = {}
# Iterate through each JSON file in the specified folder
for file_path in glob.glob(folder_path):
with open(file_path, 'r') as file:
# Load the JSON data
data = json.load(file)
# Extract the Key from the main JSON object
key_str = data.get('Key', None)
# Iterate through each section in the JSON data
for section in data.get('Sections', []):
# Extract the Label
label = section.get('Label', None)
# Extract MainSegment chords
main_segment_chords = section['MainSegment']['Chords']
# Prepare the chords string
chords_string = main_segment_chords
# Extract Endings chords (if they exist)
endings_chords = [ending['Chords'] for ending in section.get('Endings', [])]
# Append first Ending
if endings_chords:
chords_string += '|' + endings_chords[0] # First Ending
# Append MainSegment again
chords_string += '|' + main_segment_chords
# Append second Ending
if len(endings_chords) > 1:
chords_string += '|' + endings_chords[1] # Second Ending
# Create a unique key for the title and key
unique_key = (data.get('Title', None), key_str)
# Append the chords to the dictionary
if unique_key in title_key_chords:
title_key_chords[unique_key] += '|' + chords_string
else:
title_key_chords[unique_key] = chords_string
def convert_key(key_str):
"""Converts a key to music21's minor key representation."""
key_str=key_str.replace('b','-')
if 'min' in key_str:
key_str = key_str.lower()
key_str=key_str.replace('min','')
return key_str
# Create a list to hold the final data for the new DataFrame
final_data = []
# Function to remove consecutive duplicates from a list
def remove_consecutive_duplicates(chords):
if not chords:
return []
unique_chords = [chords[0]] # Start with the first chord
for chord in chords[1:]:
if chord != unique_chords[-1]: # Only add if it's different from the last added
unique_chords.append(chord)
return unique_chords
# Populate the final data list with unique titles, keys, and concatenated chords
for (title, key_str), chords in title_key_chords.items():
# Replace pipe signs with commas for the final output
chords = chords.replace('|', ',')
chords = chords.replace('(', ',')
chords = chords.replace(')', ',')
# Split the chords into a list and remove consecutive duplicates
chords_list = chords.split(',')
# Remove empty strings from the list
chords_list = [chord for chord in chords_list if chord]
simplified_chords_list = [simplify_chord(chord) for chord in chords_list]
unique_chords_list = remove_consecutive_duplicates(simplified_chords_list)
# Join the unique chords back into a string
unique_chords_string = ','.join(unique_chords_list)
# Append to final data, replacing missing key with 'C'
final_data.append({
'Title': title,
'Key': key_str if key_str is not None else 'C', # Replace None with 'C'
'Chords': unique_chords_string
})
# Create a DataFrame from the final data
unique_chords_split_df = pd.DataFrame(final_data)
unique_chords_split_df['Converted_Key'] = unique_chords_split_df['Key'].apply(convert_key)
# unique_chords_split_df['separated_chords'] = unique_chords_split_df['Chords'].str.split(',').apply(lambda x: ','.join([split_chord(chord) for chord in x]))
def chord_to_roman(full_chord, key_str):
"""Converts a chord root to Roman numeral based on the key."""
try:
match = re.match(r"([a-gA-G]#?b?)(.*)", full_chord)
if match:
chord_root, chord_quality = match.groups()
key_str=key_str.replace('b','-')
if 'min' in key_str:
key_str = key_str.lower()
key_str=key_str.replace('min','')
k = key.Key(key_str)
chord_root=chord_root.replace('b','-')
route=pitch.Pitch(chord_root)
kord = chord.Chord([route])
rnr = roman.romanNumeralFromChord(kord, k)
rnr_str = str(rnr.figure).upper()
rnr_str = rnr_str.replace('B','b')
rn = rnr_str + chord_quality
return rn
except Exception as e:
# Handle cases where chord_root or key_str is invalid
print(f"Error converting {chord_root} in key {key_str}: {e}")
return "Error"
# Apply the function to create a new 'roman_numerals' column
unique_chords_split_df['roman_numerals'] = unique_chords_split_df.apply(
lambda row: ','.join([chord_to_roman(chord.split()[0], row['Key'])
for chord in row['Chords'].split(',')]), axis=1)
# Display the unique chords DataFrame
print(unique_chords_split_df)
unique_chords_split_df.to_csv('/content/drive/MyDrive/jazzstandardschordsroman.csv', index=False)
def get_first_roman_numeral(roman_numerals_str):
"""Extracts the first Roman numeral from a string."""
if pd.isna(roman_numerals_str) or not roman_numerals_str: # Handle missing or empty strings
return None
roman_numerals = roman_numerals_str.split(',')
if roman_numerals and roman_numerals[0]:
return roman_numerals[0]
return None
def get_last_roman_numeral(roman_numerals_str):
"""Extracts the last Roman numeral from a string."""
if pd.isna(roman_numerals_str) or not roman_numerals_str: # Handle missing or empty strings
return None
roman_numerals = roman_numerals_str.split(',')
if roman_numerals:
return roman_numerals[-1]
return None
# Create the new columns
unique_chords_split_df['Major/Minor'] = unique_chords_split_df['Key'].str.contains('min').map({True: 'Minor', False: 'Major'})
unique_chords_split_df['First_Roman_Numeral'] = unique_chords_split_df['roman_numerals'].apply(get_first_roman_numeral)
unique_chords_split_df['Last_Roman_Numeral'] = unique_chords_split_df['roman_numerals'].apply(get_last_roman_numeral)
# Display the updated DataFrame
unique_chords_split_df.to_csv('/content/drive/MyDrive/JazzStandardsRomanChords.csv', index=False)
unique_chords_split_df
def get_chord_transitions(roman_numerals_str):
"""Generates a list of chord transitions from a string of Roman numerals."""
if pd.isna(roman_numerals_str) or not roman_numerals_str:
return []
roman_numerals = roman_numerals_str.split(',')
transitions = []
for i in range(len(roman_numerals) - 1):
transitions.append(f"{roman_numerals[i]}/{roman_numerals[i+1]}")
return transitions
# Apply the function to create a new 'chord_transitions' column
unique_chords_split_df['chord_transitions'] = unique_chords_split_df['roman_numerals'].apply(get_chord_transitions)
# Display the updated DataFrame
print(unique_chords_split_df)
unique_chords_split_df.to_csv('/content/drive/MyDrive/JazzStandardsChordTransitions.csv', index=False)
def group_chord_transitions(df):
"""Splits the chord transitions between Major/Minor and groups them."""
grouped_transitions = {}
for _, row in df.iterrows():
key = row['Major/Minor']
for transition in row['chord_transitions']:
first_chord = transition.split('/')[0]
if key not in grouped_transitions:
grouped_transitions[key] = {}
if first_chord not in grouped_transitions[key]:
grouped_transitions[key][first_chord] = []
grouped_transitions[key][first_chord].append(transition)
return grouped_transitions
grouped_transitions = group_chord_transitions(unique_chords_split_df)
grouped_transitions
# Example: Access transitions starting with 'I' in Major key:
# if 'Major' in grouped_transitions and 'I' in grouped_transitions['Major']:
# print(grouped_transitions['Major']['I'])
from collections import Counter
def order_transitions_by_frequency(grouped_transitions):
"""Orders chord transitions by frequency for each group (Major/Minor)."""
ordered_transitions = {}
for key, transitions_dict in grouped_transitions.items():
ordered_transitions[key] = {}
for first_chord, transitions_list in transitions_dict.items():
# Count the frequency of each transition
transition_counts = Counter(transitions_list)
# Order transitions by frequency (most frequent first)
ordered_transitions[key][first_chord] = transition_counts.most_common()
return ordered_transitions
ordered_transitions = order_transitions_by_frequency(grouped_transitions)
def save_transitions_to_json(ordered_transitions):
"""Saves ordered transitions to separate JSON files for Major and Minor keys."""
for key_type, transitions in ordered_transitions.items():
filename = f"{key_type}_Key_Transitions.json"
with open(filename, 'w') as f:
json.dump(transitions, f, indent=2)
save_transitions_to_json(ordered_transitions)
You do not have the required permissions to view the files attached to this post.
-
- KVRist
- Topic Starter
- 144 posts since 31 Jan, 2017
Neat stuff! Nice to get confirmation that my approach isn’t that crazy.frimpiso wrote: Sun Dec 15, 2024 7:51 pm Cool, you seem to do something similar as I do.
I am also using RC as a tool to study Jazz Harmony. I am a member of Openstudio and I usually try to enter their voicings and ideas into RC. Together with the note coloring feature you can immediately see how the voicings work (e.g. root-shell voicings).
I have not looked into the chord rules of RC yet. I am just gettings started.
So keep up the Jazz stuff for RC!
Cheers
Jens
P.S.: I play the guitar, a bit of bass and try to get started on the piano (RC is a great way to understand what is actually happening).
With guitar, you almost get a headstart. Do you find the guitar-related material useful enough?
As I was never able to learn piano, despite years of lessons, I’ve been really pleased with using “isomorphic grids” (Launchpad and such at first, in fourths as on the bass, now with Exquis’s “hex keys” in a layout similar to Tonnetz, going up in minor thirds in one diagonal and major thirds in another). The trick will be to apply the approaches they describe on Open Studio to these grids. Should be really slow at first and pretty quick once I get the hang of things (since all keys are played the same way).
So… Thanks a lot for chiming in! If you do start playing with chord rules, let us know what you think. Sounds to me like it can be the basis of some solid learning.
-
- KVRAF
- 2154 posts since 15 May, 2017
If you have the time, maybe create a post in the "Tips and Tricks" area on your work flow. I think it would be useful to know for sure. Maybe others have similar ideas..
-
- KVRist
- Topic Starter
- 144 posts since 31 Jan, 2017
If you were asking me…BluGenes wrote: Mon Dec 16, 2024 12:56 pm If you have the time, maybe create a post in the "Tips and Tricks" area on your work flow. I think it would be useful to know for sure. Maybe others have similar ideas..
Don’t really have tips & tricks, yet. The workflow to create that script and get those results was a bunch of interactions with Gemini in Google Colab (which is an online version of Jupyter notebook which, itself, is a Python-based version of environments like Mathematica). Lots of trial and error. Because, again, I’m not a coder. The key, in this kind of thing, is to bring things down to small steps that you can explain. For instance, “split this set between major and minor keys” worked instantly. Getting things to conform to what music21 expects didn’t, at least not until I understood what it did expect. So, converting to lowercase for minor keys, replace 'b' with '-'… And because music21 doesn’t handle all the chord qualities found in Jazz, it was better to split the root to convert it instead of passing the full chord symbol.
So, geeky stuff, for sure. Nothing too difficult, though.
At this point, I’m using the transitions to encode chord rules. Manually. One by one. With loose “weights”/probabilities. Not scientific in the least. In fact, I expect tweaking things to my liking to be a big part of my process, once I’m done putting all those rules together.
And it does help me to understand a number of things about Jazz Harmony. Subtle things which are hard to describe at this point. Things I notice like the significant number of nondiatonic chords (bII, #V, etc.). And just a sense that Jazz Theory doesn’t necessarily follow as much of a common pattern as one might expect.
-
- KVRist
- Topic Starter
- 144 posts since 31 Jan, 2017
Something which might be worth mentioning as a quirk in parts of that corpus.
A few pieces have some double-flat Roman numerals. Most of these are VII, so they’re VI chords notated differently, I guess? No idea why.
Black Narcissus is labelled as being in G♯ yet the notation is pretty much in A♭, AFAICT.
An interesting case is Green Chimneys which might also be in A♭… yet has a bunch of chords which wouldn’t fit in A♭ minor.
G#min Abm,F#7,B7,F#7,B7,F#7,B7,F#7,B7,F#7,B7,F#7,B7,F#7,B7,F#7,B7,Abm g# bbIIm,bVII7,III7,bVII7,III7,bVII7,III7,bVII7,III7,bVII7,III7,bVII7,III7,bVII7,III7,bVII7,III7,bbIIm
So, again, these lists of transitions aren’t meant to be a scientific measure of what happens in that corpus. As with the hardcopy of the Real Book, there’s a bunch of things which might have been notated differently. In fact, I notice some alternative versions of some pieces in my copy of iReal Pro. That might have come after Mike Oliphant parsed the corpus to create JSON files.
A few pieces have some double-flat Roman numerals. Most of these are VII, so they’re VI chords notated differently, I guess? No idea why.
Black Narcissus is labelled as being in G♯ yet the notation is pretty much in A♭, AFAICT.
An interesting case is Green Chimneys which might also be in A♭… yet has a bunch of chords which wouldn’t fit in A♭ minor.
G#min Abm,F#7,B7,F#7,B7,F#7,B7,F#7,B7,F#7,B7,F#7,B7,F#7,B7,F#7,B7,Abm g# bbIIm,bVII7,III7,bVII7,III7,bVII7,III7,bVII7,III7,bVII7,III7,bVII7,III7,bVII7,III7,bVII7,III7,bbIIm
So, again, these lists of transitions aren’t meant to be a scientific measure of what happens in that corpus. As with the hardcopy of the Real Book, there’s a bunch of things which might have been notated differently. In fact, I notice some alternative versions of some pieces in my copy of iReal Pro. That might have come after Mike Oliphant parsed the corpus to create JSON files.
-
- KVRist
- Topic Starter
- 144 posts since 31 Jan, 2017
Ha!! Neat!
Turns out that applying these rules through Python is trivial. Should have known.
With Python3 installed, unzipping that folder, navigating to it, and running the command:
`python3 ProgGen.py 7 Major 0.3`
Generates a progression of 7 chords in Major, with a commonality of 30%.
And since it runs from the transitions files, it’s instantaneous. (The whole conversion script from before, to get these transitions, takes a while to run.)
Soooo… I’ll still try things in RapComp, of course. Yet I might have more of a basis for an independent “something” to run without the app. In fact, it should be possible to run on iPad.
[Edit: tiny change to the script so that it’d create a space-separated list of chords, as RC5 expects.]
Turns out that applying these rules through Python is trivial. Should have known.
With Python3 installed, unzipping that folder, navigating to it, and running the command:
`python3 ProgGen.py 7 Major 0.3`
Generates a progression of 7 chords in Major, with a commonality of 30%.
And since it runs from the transitions files, it’s instantaneous. (The whole conversion script from before, to get these transitions, takes a while to run.)
Soooo… I’ll still try things in RapComp, of course. Yet I might have more of a basis for an independent “something” to run without the app. In fact, it should be possible to run on iPad.
[Edit: tiny change to the script so that it’d create a space-separated list of chords, as RC5 expects.]
You do not have the required permissions to view the files attached to this post.
-
- KVRist
- 44 posts since 26 Feb, 2023
Looks great.
Question: How do you deal with changes of scale / tonal center?
Like "All the things you are" (ATTYA) modulates through several tonal centers:
That cannot be that easily extracted from the real book.
Side note:
In fact, in a perfect world, rapid composer would also have a "scale rules editor" where you can select the most next likely scale to transition/modulate to. Or is there something like this in RC?
If RC would aid you in choosing a nice next tonal center to modulate to in your song, this would make the compositions much more lively.
Question: How do you deal with changes of scale / tonal center?
Like "All the things you are" (ATTYA) modulates through several tonal centers:
That cannot be that easily extracted from the real book.
Side note:
In fact, in a perfect world, rapid composer would also have a "scale rules editor" where you can select the most next likely scale to transition/modulate to. Or is there something like this in RC?
If RC would aid you in choosing a nice next tonal center to modulate to in your song, this would make the compositions much more lively.
-
- KVRist
- Topic Starter
- 144 posts since 31 Jan, 2017
Simple: I don’t.frimpiso wrote: Tue Dec 17, 2024 11:13 pm Question: How do you deal with changes of scale / tonal center?
(For scales, there’s an approach to Jazz improv which simply associates the scale with the current chord. Play G Mixo over that G7 even if you switch to D♭ Lydian on the next chord. Voice leading can still help.)
Tonal centres may be very useful for analysis. I’m not paying attention to those in terms of creating what I want to create.
In fact, it’s part of the reason I wanted to use this approach. The idea is that a modulation is pretty much the same thing as a parallel chord which is pretty much the same thing as a chord substitution which is pretty much the same thing as Coltrane changes which are pretty much the same thing as moving around within the same tonal structure.
In the end, what my ear wants has to do with what happens in a number of patterns between chords. Sure, they refer to the tonal centre in the sense that the Roman numerals refer to the key. If a certain pattern to move to another tonality is common (which I’m pretty sure is the case), it can easily show up as part of the “rules”.
In AtTYA, it’s neither immediately obvious nor completely obscure.
The five times #VIm7b5/#II7b9 occurs in the corpus… are mostly from that one title. Still, it comes up as a possibility and, if I end up on #VIm7b5 (from VII7, IIImaj7, VImaj7, VI7, VIImaj7, VII7b9), #II7b9 is the most common way to go.VIm7,IIm7,V7,Imaj7,IVmaj7,#IVm7,VII7,IIImaj7,VIm7,IIm7,V7,Imaj7,IVmaj7,#IVm7,VII7,IIImaj7,IIIm7,VIm7,II7,Vmaj7,Imaj7,#Im7,#IV7,VIImaj7,IIIm7,VIm7,II7,Vmaj7,Imaj7,#Im7,#IV7,VIImaj7,#Im7,#IV7,VIImaj7,#VIm7b5,#II7b9,#Vmaj7,III7b13,#Im7,#IV7,VIImaj7,#VIm7b5,#II7b9,#Vmaj7,III7b13,VIm7,IIm7,V7,Imaj7,IVmaj7,IVm,IIIm7,#II07,IIm7,V7,Imaj7,VIIm7b5,III7b9,VIm7,IIm7,V7,Imaj7,IVmaj7,IVm,IIIm7,#II07,IIm7,V7,Imaj7,VIIm7b5,III7b9
In other words, this prog gen technique isn’t really tonal.
(Part of the reason Mapping Tonal Harmony never clicked, for me, is that there’s a set of builtin expectations which don’t match my experience. Explanations about chord substitutions do. And transitions between chords teach me more about improvisation than anything I’ve heard in traditional approaches to “music theory”.)
Especially since that’s not the type of info that leadsheets contain.
Things could have been different.
Still, because Jazz improvisation can follow diverse paths, I don’t feel much of a need for a notation in terms of tonal centres.
Dunno. I’m very new to RC. I do realize that it can create chord rules from selected chords and it sounds like there are ways to associate scales with chords (even while entering chords). No idea yet if these scales can be part of any kind of ruleset.frimpiso wrote: Tue Dec 17, 2024 11:13 pm in a perfect world, rapid composer would also have a "scale rules editor" where you can select the most next likely scale to transition/modulate to. Or is there something like this in RC?
-
- KVRAF
- 2154 posts since 15 May, 2017
fair enough and all.. I have used Python before, so, just a quick tip for you and anyone just getting into this stuff is, with Python, especially if you have it installed locally on your computer, think of that local install as like a "folder" structure for all your projects (In your minds eye). You want to always create a "folder" for your various projects and work in that "folder".Enkerli wrote: Tue Dec 17, 2024 12:34 am
If you were asking me…
Don’t really have tips & tricks, yet. The workflow to create that script and get those results was a bunch of interactions with Gemini in Google Colab (which is an online version of Jupyter notebook which, itself, is a Python-based version of environments like Mathematica). Lots of trial and error. Because, again, I’m not a coder.
In Python, that is called "environments". Anyways, the very big point I am trying to make is keeping projects separated because Python can download a LOT of required packages to run your script.
Sometimes this can cause problems, if you don't, because you are applying those packages to everything.
Yes, it's a very fun language and not really that difficult to get to know.
Would be kind of cool if RCs supported scripting, but, that is a whole world away..
cheers and have fun with it!
-
- KVRist
- 44 posts since 26 Feb, 2023
Interesting.In fact, it’s part of the reason I wanted to use this approach. The idea is that a modulation is pretty much the same thing as a parallel chord which is pretty much the same thing as a chord substitution which is pretty much the same thing as Coltrane changes which are pretty much the same thing as moving around within the same tonal structure.
In the end, what my ear wants has to do with what happens in a number of patterns between chords. Sure, they refer to the tonal centre in the sense that the Roman numerals refer to the key. If a certain pattern to move to another tonality is common (which I’m pretty sure is the case), it can easily show up as part of the “rules”.
But I am just a lazy guitar player and I simply switch my scale pattern when the tonal center changes and then noodle around on that scale. I guess my improvisational skill would become much better if I would focus on the chords, their transitions and voicings.
But I can remember standards much better if I relate them to the changing respective tonal center. Like ATTYA repeats the vi-ii-V-I-IV pattern in at least two tonal centers which makes it much easier to memorize. (By the way: openstudio appears to be based on that understanding).
So how do you select your tonal center (i.e. the I) for the real book pieces you process ? Is that based on the first chord?
-
- KVRist
- Topic Starter
- 144 posts since 31 Jan, 2017
Good points. And it’s the reason I was using Anaconda, for some projects.BluGenes wrote: Wed Dec 18, 2024 1:38 pmfair enough and all.. I have used Python before, so, just a quick tip for you and anyone just getting into this stuff is, with Python, especially if you have it installed locally on your computer, think of that local install as like a "folder" structure for all your projects (In your minds eye). You want to always create a "folder" for your various projects and work in that "folder".Enkerli wrote: Tue Dec 17, 2024 12:34 am
If you were asking me…
Don’t really have tips & tricks, yet. The workflow to create that script and get those results was a bunch of interactions with Gemini in Google Colab (which is an online version of Jupyter notebook which, itself, is a Python-based version of environments like Mathematica). Lots of trial and error. Because, again, I’m not a coder.
In Python, that is called "environments". Anyways, the very big point I am trying to make is keeping projects separated because Python can download a LOT of required packages to run your script.
Sometimes this can cause problems, if you don't, because you are applying those packages to everything.
Yes, it's a very fun language and not really that difficult to get to know.
Would be kind of cool if RCs supported scripting, but, that is a whole world away..
cheers and have fun with it!
In this case, though, I was using Google Colab (cloud version of Jupyter notebooks).
I did end up running the scripts locally. The libraries they use aren’t demanding and I had installed them.
-
- KVRist
- Topic Starter
- 144 posts since 31 Jan, 2017
Valid approaches, yours and mine. Results can be similar.frimpiso wrote: Wed Dec 18, 2024 9:29 pmInteresting.In fact, it’s part of the reason I wanted to use this approach. The idea is that a modulation is pretty much the same thing as a parallel chord which is pretty much the same thing as a chord substitution which is pretty much the same thing as Coltrane changes which are pretty much the same thing as moving around within the same tonal structure.
In the end, what my ear wants has to do with what happens in a number of patterns between chords. Sure, they refer to the tonal centre in the sense that the Roman numerals refer to the key. If a certain pattern to move to another tonality is common (which I’m pretty sure is the case), it can easily show up as part of the “rules”.
But I am just a lazy guitar player and I simply switch my scale pattern when the tonal center changes and then noodle around on that scale. I guess my improvisational skill would become much better if I would focus on the chords, their transitions and voicings.
But I can remember standards much better if I relate them to the changing respective tonal center. Like ATTYA repeats the vi-ii-V-I-IV pattern in at least two tonal centers which makes it much easier to memorize. (By the way: openstudio appears to be based on that understanding).
So how do you select your tonal center (i.e. the I) for the real book pieces you process ? Is that based on the first chord?
In terms of improv, I feel the "constant shift” approach leads me to interesting things. It’s freeing, somehow.
As for the dataset, a key is set for each piece and that’s what I’ve used. In minor pieces, most do start on I.
-
- KVRist
- Topic Starter
- 144 posts since 31 Jan, 2017
New approach, with improved results.
Using JavaScript instead of Python (and Tonal instead of music21). Was able to reanalyze the same dataset (input.zip), from Mike Oliphant's JazzStandards. Converted all of the chords to Roman numerals (chord_progressions.json). Got the counts for the first and last chords of each title, grouped by Major or Minor (first_chord_counts.json and last_chord_counts.json). Also got the counts for all transitions, split between Minor and Major (transitions.json).
From these outputs, got a little script (progGen.js) which generates chord progressions from the command line taking mode, number of chords, and probability:
which generates:
which generates:
which increases the values for 'IVm9 Vm7' and for 'Vm7 VImaj7' by 10%
or
which decreases the value for 'VImaj7 Vm7' by 20%.
So, at this point, the playflow can be…
Use
copy the result and paste it in RapComp.
Then, I can listen to the progression (using a voiceleading version of the Chord Generator, Ctrl-Shift-H). When I find transitions I enjoy more or less than others, I can tweak their probabilities in transitions.js. Doing this a number of times, with different values for the probabilities, I should get generative rules that I like enough to “commit” to RC5.
Might also end up using JS to create the MIDI files. AFAICT, tonal supports voiceleading.
Using JavaScript instead of Python (and Tonal instead of music21). Was able to reanalyze the same dataset (input.zip), from Mike Oliphant's JazzStandards. Converted all of the chords to Roman numerals (chord_progressions.json). Got the counts for the first and last chords of each title, grouped by Major or Minor (first_chord_counts.json and last_chord_counts.json). Also got the counts for all transitions, split between Minor and Major (transitions.json).
From these outputs, got a little script (progGen.js) which generates chord progressions from the command line taking mode, number of chords, and probability:
Code: Select all
node progGen.js minor 8 0.4orIIm7b5 V7b13 IVm7 VI7 bIImaj7 IIm7b5 V7b9 Im7
Code: Select all
node progGen.js major 16 0.7Then(!), I can boost the probabilities of transitions I like or decrease the likelihood of transitions I don’t like.IIm7 V7 Imaj VI7 II7 Vmaj7 I7 IVmaj7 IIm7 V7b9 Im7 IV7sus Vmaj V7 I6 Imaj7
Code: Select all
node transitionBoost.js 10 IVm9 Vm7 VImaj7or
Code: Select all
node transitionBoost.js -20 VImaj7 Vm7So, at this point, the playflow can be…
Use
Code: Select all
node progGen.js major 8 0.7Then, I can listen to the progression (using a voiceleading version of the Chord Generator, Ctrl-Shift-H). When I find transitions I enjoy more or less than others, I can tweak their probabilities in transitions.js. Doing this a number of times, with different values for the probabilities, I should get generative rules that I like enough to “commit” to RC5.
Might also end up using JS to create the MIDI files. AFAICT, tonal supports voiceleading.
You do not have the required permissions to view the files attached to this post.
