Hello!

Here is some article explaining the algorithmic logic used to produce the chunk of code located below this paragraph.

For starters, I do have a problem with creating efficient and melodic music patterns. This process of thought always slows me down when I need to improvise an exciting music. FoxDot has some tools to generate melodic rythms, such as PDur or PRhythm. Nevertheless, these appear a bit simple to me in the case of melody crafting.

My problem was, I could not take the best of FoxDot tools, nor could I ask my audience to have the patience to bear the same repetitive music all the while I was coding some super-melody.

So I came out with a quick fix to my lack of knowledge, and I’m offering it to you today.

This is a duration pattern generator available on FoxDot. I say duration Pattern : Pattern is a FoxDot class allowing matrix manipulations on lists, and duration is a player property setting, well, the duration of each note pitch.

This solution comes as a function that returns a list in which you can find your final duration pattern, as well as the number of members in this pattern. It is fully customizable, so feel free to take it and make it fit to your needs.

The algorithm

First, I define some global variables I’ll need. The argument target is the number of beats I want, and the following variables stand for :

  • indexes : number of iterations to add an item to my list.
  • standards : standard duration values in the score notation system (in time signature 4/4).
  • dividers : an array of dividers to use. Mostly it’s one but you can custom it to your preferred fashion.
  • list : an empty list, that I wish to fill with duration values.

Then I start an iteration. I came with some conditions and generated random numbers, divided by a random choice in my dividers list. Here, you see that I put more 1s in it, hence increasing my chances to get integers.

In this iteration, I must check that the next item to add in the list does not excel the target value, so I translate this in a bunch of conditions : here, you can create your own.

After the iteration process, I am left with a list of durations that’s still not equaling my target total duration.

It’s only there I use my standards values… But eventually you could ease the process of using them only.

The calculation for these last results checks whether the last item is a standard value or not, and if not, I cut away the surplus.

Then comes the return. Here, I made it a simple list because I needed different informations. Of course the most important information is the generated pattern. Each use of this function produces a random duration pattern that you can try out in your songs.

Cheers!

You can find my other works on my github.

 

def DurShaperSc(target):
    from random import randint
    sr = random.SystemRandom()
    indexes = random.randint(1,target+4)
    standards = [0.25,0.375,0.75,0.5,1,2,3,4] # standard dur values found in scores
    dividers = [1,1,1,2] # skip 1/4 and 1/8 (comes after) - fully customizable
    list=[]
    for i in range(0,indexes):
        if target%2 == 0:
            a = random.randint(1,target/2)/sr.choice(dividers)
        else:
            a = random.randint(1,(target-1)/2)/sr.choice(dividers)
        # conditions are fully customizable as well if you want to raise or reduce the occurence of getting low durations
        if sum(list)+a < target/4:
            list.append(a)
        if sum(list)+a/2 < target/2:
            list.append(a/2)
        if sum(list)+a < target:
            list.append(a)
        if sum(list)+a/4 < target:
            list.append(a/4)
    # this stands for the last numbers remaining to sum up to target total duration
    if sum(list) < target:
        # so we close the chapter with taking special care about our durations being standard
        for i in range(0,len(standards)):
            if target-sum(list)%standards[i] != 0 and standards[i] < target-sum(list):
                list.append(standards[i])
        if sum(list) < target:
            list.append(target-sum(list))                                 
    return [P[list].shuffle(),len(list)] # always return a list of durations with total duration equals target