Bjorklund algorithm

Oct 14, 2011 at 10:20am

Bjorklund algorithm

Hi all,

I implemented Bjorklunds algorithm to Javascript for use in Max and thought I would share.

http://gist.github.com/1286731

I know there exists some other implementations for various languages around the web but I found that most were broken for more than 16 steps so I fairly closely ported the original c implementation.

Hopefully someone will find it useful

#59302
Oct 14, 2011 at 12:49pm

Thanks – I can’t look at it right now, because the network police have banned me from using Max at work (really!), but thought you might be interested in this post, if you hadn’t already seen it:

http://www.cycling74.com/forums/topic.php?id=16979

There was also a js Max implementation – I have the patch here, but can’t open it of course, and I can’t find it on the forum, though I think it may have been by Axiom-Crux ?
cheers
Roger

#213219
Oct 14, 2011 at 1:09pm

haha, I also made an implementation of this bjorklund algorithm (in java) and I plan to share that later too, but you beat me to it :-)

#213220
Oct 14, 2011 at 2:00pm

@roger.carruthers Thanks for the linkage. That ruby code looks very similar to a lot of the other implementations that I found to not work with more than 16 steps (although for 16 or less steps they work fine and are more efficient).

A few of the options are listed here http://createdigitalmusic.com/2011/03/circles-and-euclidian-rhythms-off-the-grid-a-few-music-makers-that-go-round-and-round/

most look to be based on the same logical implementation (across different languages), but whatever was used as the base implementation that has subsequently been ported does not follow Bjorklunds original c version. That is, as far as I can tell, I am by no means an algorithm expert or particularly at maths! But as I said I have noticed funny results when trying to create patterns greater that 16 steps with all but my version.

@Timo Rozendal

If you have some java code please make it available, I was possibly going to make an mxj to see if it performs much better, although I am hoping that the new Javascript engine in Max 6 might solve that issue for me!

#213221
Oct 20, 2012 at 3:31am

Downloaded this as the other implementations have errors in them…How do you use this in max? I saved the file in the folder I’m working in and used [js bjorklund.js] … According to the source it’s one function (bjorklund) that takes 2 arguments (steps, pulses) and returns an array…I’ve tried sending a message “bjorklund 8 3″ to the object but nothing comes out the outlet. Any ideas?

#213222
Oct 20, 2012 at 3:48am

Nevermind… I had to:

1) initiate the object such as [js bjorklund 8 3]

2) edit the .js and at the end instead of returning the value send it to outlet 0

3) call the function as: “bjorklund 8 3″

#213223
Mar 6, 2013 at 6:29am

I’m having trouble getting this to work in max and Marcos instructions leave me confused. new to the js object and javascript coding in general.

#213224
Mar 6, 2013 at 8:27pm

I updated the bjorklund example and made it a little more user friendly…

Attachments:
  1. bjorklund.maxpat
#213225
Mar 6, 2013 at 8:39pm

I’m getting ‘js:no function generatePattern’ in the Max window,
Cheers
Roger

#213226
Mar 6, 2013 at 8:58pm

Are you loading the bjorklund.js I up loaded? generatePattern is definitely there…

#213227
Mar 6, 2013 at 9:33pm

Woops, yes the old one was still in my search path!
Cheers
Roger

#213228
Mar 7, 2013 at 5:13am

thanks for the remake!

#213229
Mar 7, 2013 at 5:41am

weird, the fix either breaks the code or there is something wrong with the original
the code’s output is offset for certain pulse values. for “generatePattern 16 5″ i get
[ . x . . x . . x . . x . . x . . ] when the article says the expected result is
[ x . . x . . x . . x . . x . . . ] “generatePattern 8 5″ causes the same offset.
weirdly, the starting example of “generatePattern 8 3″ works but “generatePattern 16 3″ does not
i went back to withakay’s original code
replaced only “return pattern.reverse();” on line 63 with “outlet(0, pattern.reverse());”
the error remained the same. going to fiddle around with it and see what’s happening.

i’ve used the java code from http://doc.gold.ac.uk/~ma801dp/blog/?p=40 in the past
might go back to that for now if a few test values come back correct.

edit: jurgen schmitz’s m4l device works while using this code because the js ends with
———————————-
build(level);

pattern = pattern.reverse();

// make sure pattern starts with a ’1′
for(s = 0; pattern[s] != 1; s++);
pattern = rotate(pattern, -s);

return pattern;
———————————-
but was designed to work specifically with his device, as just copying out the original portion gives “js: bjorklundFIX2.js: Javascript ReferenceError: rotate is not defined, line 75″
the fiddling continues….

#213230
Mar 7, 2013 at 5:54pm

jurgen’s idea about rotating the list until it starts with a 1 is great, simple and efficient.
isn’t it strange the rotate function doesn’t work in js ? there should be a way…

#213231
Mar 7, 2013 at 6:21pm

Actually, I have been looking a little more closely at the output. It seems to be doing
exactly what I would expect. Given the following sequence of input, you get the following
output…

8 beats 3 pulses
output: 1 0 0 1 0 0 1 0

16 beats 3 pulses
output: 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0

8 beats 4 pulses
output: 1 0 1 0 1 0 1 0

So what this is really doing, is taking a pattern of beats and evenly distributing
another pattern within it.

I have updated the helper patch to allow for easier control of pattern lengths
and note division. By adding two separate clicks you can really hear the difference.

– Pasted Max Patch, click to expand. –
#213232
Mar 7, 2013 at 6:44pm

when using more than one generator at the same time, it’s nice to have a synchronisation point, which is the start of each loop.
if every loop start with 1, it feels more musical, and rotating the list doesn’t change the evenly distribution.
it’s a kind of normalisation.

#213233
Mar 7, 2013 at 6:52pm

bertrandfraysse, not so fast. it seems jurgen’s code is flawed as well.
for example E(5, 8)
[ . x x . x x . x ] = bjorklund code output
[ x x . x x . x . ] = jurgen’s rotate fix (from ADesso ERG v2.3)
[ x . x x . x x . ] = expected result (from Toussaint’s paper)

but for an example like E(5, 16) the pattern from the m4l device is correct.
so for some pulse values the array needs to be rotated positively, others negatively.

#213234
Mar 7, 2013 at 7:01pm

maybe it feels more natural to have 1 0 as a beginning than 1 1.
so we need to make our algorithm to try and find the right rotation to find 0 after 1 if it can…
just an idea…

#213235
Mar 7, 2013 at 7:28pm

i feel like i’m overcomplicating this, especially as i’m only planning to use the algorithm for generating quick drum loops to be refined later. going to stick to the current code and put a zl.rot at the end to adjust the pattern as i like. thanks again for the help, anthony.

#213236
Mar 7, 2013 at 7:50pm

Try this code,that I wrote it for my euklid-sequencer m4l-device http://www.maxforlive.com/library/device.php?id=993 . The outcoming list always starts with a 1. I’m not an experienced js-coder, so there are probably smarter ways to compute this list, but it works ;-).

inlets = 1;
outlets = 1;

function bjorklund(pulses, steps)
{
	if (steps >= pulses && steps > 1)
	{
		var pauses = steps - pulses;
		var rythm = new Array();
		var colSizes = new Array();

		//build arrays
		for (var i = 0; i < pulses; i++)
		{
			rythm.push(1);
			colSizes.push(1);
		}
		for (var i = 0; i < pauses; i++)
		{
			rythm.push(0);
			colSizes.push(1);
		}

		//actual algorithm
		while ( !((pauses==1 && pulses==1) || (pauses==0 || pulses==0)) )
		{
			var counter = 0;

			if (pauses>pulses)
			{
				counter = pulses;
				pauses -= pulses;
			}
			else
			{
				counter = pauses;
				pulses -= pauses;
			}

			var writePosition = 0;

			var level = colSizes[colSizes.length - 1];

			for (var i = 0; i < counter; i++)
			{
				writePosition += colSizes[i];

				var readPosition = rythm.length - level;
				var elementsToMove = rythm.splice(readPosition, level);

				for (var j = 0; j < elementsToMove.length; j++)
				{
					rythm.splice(writePosition, 0, elementsToMove[j]);
					writePosition ++;
				}
				colSizes[i] += level;
				colSizes.pop();
			}
		}
		outlet(0, rythm);
	}
}
#213237
Mar 7, 2013 at 9:12pm

sorry david but your results are coming back out of order.

example (3, 8)
[ x . . x . x . . ] = your code
[ x . . x . . x . ] = Bjorklund code & Toussaint’s paper

example (5, 8)
[ x . x x . x . x ] = your code
[ . x x . x x . x ] = bjorklund code
[ x . x x . x x . ] = Toussaint’s paper

same for most other values i tried. wish i could learn js code quicker so i could offer something useful other than criticism. sorry.

#213238
Mar 7, 2013 at 11:01pm

edit: SEE BELOW

#213239
Mar 7, 2013 at 11:32pm

well i’ve almost cracked it. this new code accounts for the list rotation (either positively or negatively).

so far the only example error i’ve found is E(5,13)
[ x . x . . x . x . . x . . ] = my code
[ x . . x . x . . x . x . . ] = toussaint’s paper

if anyone finds another let me know. not sure how to go about correcting that but for my use it won’t be an issue.

save the new bjorklund.js file i’ve attached and use the below patch for testing

– Pasted Max Patch, click to expand. –
Attachments:
  1. bjorklund.js
#213240
Mar 8, 2013 at 4:49am

Yes, I think you are overcomplicating this a bit ;-). The output of all three algorithms are valid as they evenly distribute the events over the number of steps. They are all just rotations of each other, and I would always include some kind of rotation-parameter in a device anyway.
For beats I just find it much easier, if the list always starts with a 1 and not a 0, which is the reason why I wrote my code.

#213241
Mar 8, 2013 at 9:42am

and here is my quick and dirty (string manipulating) way in java

– Pasted Max Patch, click to expand. –

I like how with verbose on you see the process in the max window :-)
I should have posted this a year ago, but I forgot, these recent messages in this forum reminded me of this

Attachments:
  1. bjorklund.class
#213242
Mar 8, 2013 at 6:35pm

thank you very much timo !

#213243
Mar 9, 2013 at 8:35am

I use the original Bjorklund method, and I find the placement of beats nice and serendipitous, which is why I use it in the first place :)

#213244
Apr 1, 2013 at 12:58pm

Thanks a lot for sharing this! Here’s a little m4l device in which I used the algorithm (cudnylon’s version):

http://www.maxforlive.com/library/device/1562/8-knob-sequencer

#213245
Nov 28, 2013 at 12:49pm

This topic seems pretty well addressed at this point but I thought I would add a method to accomplish this with standard max objects. I found this implementation in acreil’s algo-acid PD patch (found here: ) Simply feed it with a counter and it will bang on the beats that are in the E-rhythm. Here is a max version.

– Pasted Max Patch, click to expand. –

Cheers and happy Turkey day

-X

#274072

You must be logged in to reply to this topic.