Python music! Scales, keys, music, beats, and Python!
Programming artificial music intelligence.
Date Created:Thursday June 12th, 2008 02:58 AM
Date Modified:Sunday August 03rd, 2008 01:06 PM
This is a work in progress:
# File: chords.py
# Author: Dan Lynch
if __name__ == "__main__":
print 'chords is main'
chords = {
'oldmaj' :[0,4,7],
'maj' :[0, 7, 12, 16, 19, 24],
'm' :[0, 7, 12, 15, 19, 24],
'oldm' :[0,3,7],
'7' :[0,4,7,11]
}
###### It would be nice to define the definitions of the chords, like teach how to make from a major
# with stretched voicing, WHICH SCREWS UP DURING COMPILE??????
chords_full = {
'maj' :[0, 7, 12, 16, 19, 24],
'7' :[0, 7, 12, 16, 19, 22],
'sus7' :[0, 7, 12, 17, 19, 22],
'9' :[0, 7, 16, 19, 22, 26],
'sus9' :[0, 7, 17, 19, 22, 26],
'7#9' :[0, 7, 12, 16, 22, 27],
'11' :[0, 7, 16, 22, 26, 29],
'sus11' :[0, 7, 17, 22, 26, 29],
'13' :[0, 7, 16, 22, 26, 29, 35],
'sus13' :[0, 7, 17, 22, 26, 29, 35],
'maj7' :[0, 7, 12, 16, 19, 23],
'maj9' :[0, 7, 12, 16, 23, 26],
'maj11' :[0, 7, 16, 23, 26, 29],
'maj13' :[0, 7, 16, 23, 26, 29, 35],
'm ' :[0, 7, 12, 15, 19, 24],
'm7' :[0, 7, 12, 15, 19, 22],
'mmaj7' :[0, 7, 12, 15, 19, 23],
'm9' :[0, 7, 15, 19, 22, 26],
'm11' :[0, 7, 15, 22, 26, 29],
'm13' :[0, 7, 15, 22, 26, 29, 35],
'6' :[0, 7, 12, 16, 19, 21],
'm6' :[0, 7, 12, 15, 19, 21],
'dim' :[0, 6, 12, 15, 18, 24],
'dim7' :[0, 6, 12, 15, 18, 21],
'aug' :[0, 8, 12, 16, 18, 22],
'm7b5' :[0, 6, 12, 15, 18, 22]
}
# for abc format only
def make_chord(key, chord):
from sys import stdout
from list_methods import list_element
from note_lists import scales_flats, scales_sharps
from keys import get_note_list
element = list_element(scales_flats, key)
if element == -1 : element = list_element(scales_sharps, key)
notes = get_note_list( range(128) , key)
##### NOT GETTING FULL RANGE????
add=shift_num(key)
add = add+36
# CHORD
ch = []
#stdout.write("\"%s%s\" [" % (key,chord) )
for x in chords.get(chord):
#stdout.write("%s" % notes[x+add] )
ch.append( notes[x+add] )
#stdout.write("] ")
return ch
def abc_chord(list):
n = '['
for x in list:
n = "%s%s" % (n,x)
n = "%s%s" % (n,']')
return n
### works, but not for Cb, read to see why
#determines how far the key is from C for make_chord
def shift_num(key):
# determines note position ( . represents a black key)
notes='C.D.EF.G.A.B'
n=notes.find( key[0] )
#finds if a b or # is inside of the key
if key.find('#') == 1: return n+1
elif key.find('b') == 1: return n-1
else: return n
# File gen.py
# Author: Dan Lynch
import random
import sys
# translates notes frmo b3 to 3 since the Maj 3rd is normally 4, get it?
def list_note(list):
from note_lists import ints
new =[ ints.get(y) for y in list ]
return new
def notes_rand():
from scales import scales
x = random.choice(scales.keys())
_scale = scales.get(x)
_length = len( _scale )
n = range( _length )
del n[:2]
n = random.choice(n)
nums = random.sample( _scale, n)
return list_note( nums )
if __name__ == '__main__':
nlist = notes_rand()
from keys import *
print get_note_list( nlist )
# File: keys.py
# Author: Dan Lynch
if __name__ == "__main__":
print 'keys is in session'
### if you print out 0-127 abc notes in C#, watch the octaves, B# will be far off B
# returns number of accidentals and the proper element, 0,1,2 for the note dictionary
# pass in a key and tells whether the scale is part of the shaps of flats, like D has two sharps for example
def num_accidentals(key):
from list_methods import list_element
from note_lists import scales_flats, scales_sharps
element = list_element(scales_flats, key)
type=0
if element == -1:
element = list_element(scales_sharps, key)
type = 1
if element == 6 : element = 1
elif element == 7 : element = 2
else : element = 0
return [type, element]
# return the octave for the
def get_octave( note ):
a = 0
b = 12
for x in range(13):
if ( ( note >= a ) and ( note < b ) ) : return x
a = a+12
b = b+12
if note > 127 : print "note, %d,is out of MIDI range" % note
# takes a list and swaps all sharps and flats for abc accidentals
def abc_accidental_list( notes ):
for x in range( len(notes) ):
if ( notes[x].find('#') != -1 ) :
notes[x] = "%s%s" % ( '^', notes[x][0] )
elif ( notes[x].find('b') != -1 ) :
notes[x] = "%s%s" % ( '_', notes[x][0] )
return notes
def issharp(letter_note):
if (letter_note.find('#') != -1) : return True
else: return False
def isflat(letter_note):
if (letter_note.find('b') != -1) : return True
else: return False
# caps for abc notes
def caps( x, oct):
from string import lower, upper
if oct > 5: return lower(x)
else: return upper(x)
# converts list of notes to abc style
def abc_note ( notes, names):
from string import upper, lower
names = abc_accidental_list( names )
append = [ ",,,,,", ",,,,", ",,,", ",,", ",", "", "", "'", "''", "'''", "''''", "'''''", "''''''" ]
return [ "%s%s" % ( caps( x, get_octave(y) ), append[ get_octave(y) ]) for x,y in zip(names,notes) ]
# returns note frequency
def note_freq(num):
return (27.50)*pow( pow(2, 0.08333333333333333333), num)
# returns the notes for proper usage based on key
def notes_from_key(notes, key):
from note_lists import accidentals
num_type = num_accidentals(key)
return [ accidentals[x][ num_type[0] ][ num_type[1] ] for x in notes ]
# notes passed in is list of numbers
def get_note_list( notes , key='C', type='abc'):
from note_lists import ss
if (type=='freq') : list = map( note_freq, notes )
elif (type=='abc' ) :
nam = notes_from_key(range(128), key)
list = abc_note( notes, nam)
elif (type=='oct' ) : list = notes_from_key(notes, key)
else: list = notes
return list
#IS THIS FUNCTION USED
# this will change a list to a new key with a new root notes
def new_key(key, notes):
n=notes.find( key[0] )
beg=notes[:n]
end=notes[n:]
for x in beg:
end.append(x)
return notes
# File: list_methods.py
# Author: Dan Lynch
if __name__ == "__main__":
print 'list_methods is main'
# finds an element in a list in which their is a match
def list_element( list, match ):
for x in list:
if x == match: return list.index(match)
return -1
# chops list at the place of an element and elements before go onto the end
def arrange_list(element, notes):
beg=notes[:element]
end=notes[element:]
for x in beg:
end.append(x)
return end
# makes all elements of a list uppercase
def upper_list(list):
from string import upper
for x in range( len(list) ):
list[x]=upper(list[x])
return list
# makes all elements of a list lowercase
def lower_list(list):
from string import lower
for x in range( len(list) ):
list[x]=lower(list[x])
return list
# fits list data
def fit_list(list):
oldmin = min(list)
oldmax = max(list)
for x in range( len(list) ):
list[x] = fit( list[x] , oldmin, oldmax, newmin, newmax)
# fits value data
def fit(value, oldmin, oldmax, newmin, newmax):
if (value <= oldmin): return newmin
if (value >= oldmax): return newmax
value = (value-oldmin) / (oldmax - oldmin)
value = value * (newmax-newmin) + newmin
return value
# finds an element in a list in which the first character is a match
#def list_element( list, match ):
# for x in range( len(list) ):
# p=list[x].find(match)
# if (p==0): return x
# else : return -1
# File: protos.py
# Author: Dan Lynch
# for abc format only
def make_chord(key, chord):
def abc_chord(list):
#determines how far the key is from C for make_chord
def shift_num(key):
def notes_rand():
def list_note(list):
# pass in a key and tells whether the scale is part of the shaps of flats, like D has two sharps for example
def num_accidentals(key):
# return the octave for the
def get_octave( note ):
# takes a list and swaps all sharps and flats for abc accidentals
def abc_accidental_list( notes ):
def issharp(letter_note):
def isflat(letter_note):
# caps for abc notes
def caps( x, oct):
# converts list of notes to abc style
def abc_note ( notes, names):
# returns note frequency
def note_freq(num):
# returns the notes for proper usage based on key
def notes_from_key(notes, key):
# notes passed in is list of numbers
def get_note_list( notes , key='C', type='abc'):
# this will change a list to a new key with a new root notes
def new_key(key, notes):
def list_element( list, match ):
# chops list at the place of an element and elements before go onto the end
def arrange_list(element, notes):
# File: scales.py
# Author: Dan Lynch
scales = {
'Natural Minor' : ['1', '2' , 'b3', '4' , '5' , 'b6', 'b7'],
'Harmonic Minor' : ['1', '2' , 'b3', '4' , '5' , 'b6', '7' ],
'Melodic Minor' : ['1', '2' , 'b3', '4' , '5' , '6' , '7' ],
'Minor Pentatonic' : ['1', 'b3', '4' , '5' , 'b7'] ,
'Pentatonic' : ['1', '2' , '3' , '5' , '6' ] ,
'Whole Tone' : ['1', '2' , '3' , '#4', '#5', '#6'] ,
'Blues' : ['1', 'b3', '4' , '#4', '5' , 'b7'] ,
'Dorian' : ['1', '2' , 'b3', '4' , '5' , '6' , 'b7'],
'Phrygian' : ['1', 'b2', 'b3', '4' , '5' , 'b6', 'b7'],
'Lydian' : ['1', '2' , '3' , '#4', '5' , '6' , '7' ],
'Mixolydian' : ['1', '2' , '3' , '4' , '5' , '6' , 'b7'],
'Aeolin' : ['1', '2' , 'b3', '4' , '5' , 'b6', 'b7'],
'Hungrian' : ['1', '2' , 'b3', '#4', '5' , '6' , 'b7'],
'Symmetrica' : ['l', 'b2', 'b3', '4' , '#5', '6' , 'b7'],
'Enigmatic' : ['1', 'b2', '3' , '#4', '#5', '#6', '7' ],
'Arabian' : ['1', '2' , '3' , '4' , 'b5', 'b6', 'b7']
}
#make notes like sequences of natural numbers
#let those share properties with functions
#make isincreasing() or isdecreasing() functions to determine which scale to use for minor
Downloads:
Download: chords.py 2 KB
Download: gen.py 675 B
Download: keys.py 3 KB
Download: list_methods.py 2 KB
Download: music.zip 17 KB
Download: protos.py 1 KB
Download: scales.py 1 KB
Please login or Click Here to register for downloads
Music Intelligence by Dan Lynch
is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
Based on a work at www.3daet.com
Permissions beyond the scope of this license may be available at http://www.3daet.com
