Posted: Apr 21, 2016 8:49 pm
by John Platko
It's probably getting near time for a review of where I am but I'll just give a brief summary and push on in this post.

At this point I can start with a few blues licks and mutate them. I can create independent regions where counter-factuals control which licks can exist in a given region. To make this a bit more concrete. I took the founder licks and mutated them into a set of about 2000 licks, then I loaded that set into regions with varied counter-factuals. The regions are as follows:

spacenames = ['angels','scratch', '1bar_Maj_bs','2bar_Maj_bs','2bar_min_bs','2bar_turns']

This python code. the [] define a list, so the list spacenames has elements:

"angels" - which is a region where licks that can't survive the counter-factual of the region they would otherwise be in end up if there is room. At this point I don't use angel space for much but it is useful for giving an indication of where the density of licks is overflowing a region. And I'm trying to get used to the concept of angels.

"scratch" - this is a wild west region without a lot of counter-factual restrictions that I can used to create new licks on the fly as they might be needed for a song. I also can store licks that I specifically want to use here.

'1bar_Maj_bs' - This regions is set up to only allow licks that are 1 bar in length and match up pretty well with Major blues scale.

'2bar_Maj_bs', - This regions is set up to only allow licks that are 2 bar in length and match up pretty well with Major blues scale.

'2bar_min_bs',- This regions is set up to only allow licks that are 2 bar in length and match up pretty well with minor blues scale.

'2bar_turns'-This regions is set up to only allow licks that are 2 bar in length and is for turnarounds.

I loaded the 2000 general licks into each region and they were filtered appropriately, then each region went through 5-10 generations of mutations to populate that regions lick space. All in all I ended up with about 4000 licks.

Next I need a language to pick licks from those spaces to create a song- which I'm doing mostly to test my lick metrics but there are other motivations too.

What follows is a description of the song writing language that I have so far and an example. I'm using python friendly constructs- the dictionary and list.

bsdic={} defines a dictionary named bsdic (curly brackets instead of straight brackets for a list)

entries in bsdic point to lists of descriptions of groups of lick specifications that play in order one after the other.

For example:

bsdic['bs_intro']= [ ['name','intro_0','scratch']]

puts an entry into bsdic which describes a list of a single lick specifier, that being: ['name','intro_0','scratch']]
the first element of the lick specifier is the operation code - "name" means get the lick with a specific name,
the next element of the lick specifier is the name of the lick - in this case: 'intro_0'
the next element of this lick specifier is the region where that lick can be found. In this case, the "scratch" region.

Basically, I'm defining the intro lick of my song.

Next I specify a 12 bar lick pattern. 12 bars is a common blues chunk of music, but I could have broken this into smaller chunks but 12 bars is what I'm using here:

bsdic['bs_12b_0']=[
means I'm adding a new list of lick specifiers to the dictionary and this list is called " bs_12b_0"

Now I'll going through the various lick specifiers for the 12 bars.

bsdic['bs_12b_0']=[ ['plick','e_1bar_Maj_bs'],

adds a "plick" operation code which means, use lick pointer, "e_1bar_Maj_bs" to pick a lick. "e_1bar_Maj_bs" is set up to point to licks in region '1bar_Maj_bs' using an entropy pointer as I described in my last comment.

bsdic['bs_12b_0']=[ ['plick','e_1bar_Maj_bs'], ['match_n','bs_12b_0',0],

next I add a lick specification that has a "match_n" operation code, this is saying, find a lick that best matches the notes (but isnt' the same lick) of, in this case, the previous lick but you specifiy the dictionary entry name and position so it can be for any previously assigned lick.

Notice I'm not saying exactly what lick to pick but just giving general guidelines. Match_n using the pattern matching software that I describe here to determine what chord a lick was lick but in this case that software is being used to find another a lick that uses similar notes to a given lick.

bsdic['bs_12b_0']=[ ['plick','e_1bar_Maj_bs'], ['match_n','bs_12b_0',0], ['alt','bs_12b_0',0],

"alt" adds a lick specifer that says, pick a lick in the same way that you did for the first specifier in the list. I could have just used the same command ['plick','e_1bar_Maj_bs'], but I'm trying to build some structure into the song language so that repeated memes are more obvious.

bsdic['bs_12b_0']=[ ['plick','e_1bar_Maj_bs'], ['match_n','bs_12b_0',0], ['alt','bs_12b_0',0], ['match_n','bs_12b_0',2,'rentropy'],

Next antother "match_n" command, but this one, besides asking for similar notes is also specifying similar rhythm entropy.

And that's four single bar licks being specified.

bsdic['bs_12b_0']=[ ['plick','e_1bar_Maj_bs'], ['match_n','bs_12b_0',0], ['alt','bs_12b_0',0], ['match_n','bs_12b_0',2,'rentropy'],
['plick','sour_2bar_min_bs'],

Next I specifiy a 2 bar lick using a pick pointer that I set up in sweet-n-sour-n-tension space that's not too sour - this is a very happy major sounding blues song.

bsdic['bs_12b_0']=[ ['plick','e_1bar_Maj_bs'], ['match_n','bs_12b_0',0], ['alt','bs_12b_0',0], ['match_n','bs_12b_0',2,'rentropy'],
['plick','sour_2bar_min_bs'],
['posit','bs_12b_0',0,12],['posit','bs_12b_0',3 ,14],

The next two lick specifiers request that two licks already played be replayed and moved up an octave or so. That command used the lick position transpose software that I explained here

bsdic['bs_12b_0']=[ ['plick','e_1bar_Maj_bs'], ['match_n','bs_12b_0',0], ['alt','bs_12b_0',0], ['match_n','bs_12b_0',2,'rentropy'],
['plick','sour_2bar_min_bs'],
['posit','bs_12b_0',0,12],['posit','bs_12b_0',3 ,14],
['chordit','bs_12b_0',0,7,'7','scratch'],['chordit','bs_12b_0',1,5,'7'],

Next the "chordit" command is used to take two licks that have been previously played and change the notes to use those in a V dominant seventh chord and a !V dominant seventh chord. So B7 and A7. The software that does this was described here

bsdic['bs_12b_0']=[ ['plick','e_1bar_Maj_bs'], ['match_n','bs_12b_0',0], ['alt','bs_12b_0',0], ['match_n','bs_12b_0',2,'rentropy'],
['plick','sour_2bar_min_bs'],
['posit','bs_12b_0',0,12],['posit','bs_12b_0',3 ,14],
['chordit','bs_12b_0',0,7,'7','scratch'],['chordit','bs_12b_0',1,5,'7'],
['plick','e_2bar_turns'] ]

Finally I specifiy a 2 bar turnaround be selected using an entropy pick pointer.


Since this is my first song I'm going to keep it simple and use the same template for most of the song.

bsdic['bs_12b_1']= [['altbs','bs_12b_0']]
bsdic['bs_12b_2']= [['altbs','bs_12b_0']]
bsdic['bs_12b_3']= [['altbs','bs_12b_0',[0,10]]]

adds 3 more lists to the dictionary and they are specifying that 'bs_12b_0" be used as the template

bsdic['bs_12b_4']=[['rep','bs_12b_1',[5,7]],['rep','bs_12b_2',[0,2]],['rep','bs_12b_3',[3,8]], ['name','fin','scratch'] ]

Uses the 'rep' repeat command which specifices that the exact licks used at specific points be used again, and it wraps things up with a "name" command specifying the final lick.

All that's left is to define a structure that describes which lists of licks from bsdic should be used in the song and in what order.
A simple list does that:

score=['bs_intro',
'bs_12b_0',
'bs_12b_1',
'bs_12b_2',
'reset_bar',
'bs_12b_3',
'bs_12b_4'
]

I added a command to reset the entropy bar pointer in the middle - and that's how you specify a song. I'll just repeat it without interrupt:

bsdic['bs_intro']=[ ['name','intro_0','scratch']]

bsdic['bs_12b_0']=[ ['plick','e_1bar_Maj_bs'], ['match_n','bs_12b_0',0], ['alt','bs_12b_0',0], ['match_n','bs_12b_0',2,'rentropy'],
['plick','sour_2bar_min_bs'],
['posit','bs_12b_0',0,12],['posit','bs_12b_0',3 ,14],
['chordit','bs_12b_0',0,7,'7','scratch'],['chordit','bs_12b_0',1,5,'7'],
['plick','e_2bar_turns']
]


bsdic['bs_12b_1']= [['altbs','bs_12b_0']]
bsdic['bs_12b_2']= [['altbs','bs_12b_0']]
bsdic['bs_12b_3']= [['altbs','bs_12b_0',[0,10]]]


bsdic['bs_12b_4']=[['rep','bs_12b_1',[5,7]],['rep','bs_12b_2',[0,2]],['rep','bs_12b_3',[3,8]], ['name','fin','scratch'] ]

score=['bs_intro',
'bs_12b_0',
'bs_12b_1',
'bs_12b_2',
'reset_bar',
'bs_12b_3',
'bs_12b_4'
]

It's very basic at this point with only a few regions etc. but it's a start. I won't post the lillypond score unless someone wants to see that but you can hear the results here.

Any questions?