Forums > MaxMSP

Bjorklund algorithm


Oct 14 2011 | 10:20 am

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

Oct 14 2011 | 12:49 pm

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

Oct 14 2011 | 1:09 pm

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 :-)

Oct 14 2011 | 2:00 pm

@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!

Oct 20 2012 | 3:31 am

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?

Oct 20 2012 | 3:48 am

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"

Mar 06 2013 | 6:29 am

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.

Mar 06 2013 | 8:27 pm

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

Attachments:
  1. bjorklund.maxpat
Mar 06 2013 | 8:39 pm

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

Mar 06 2013 | 8:58 pm

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

Mar 06 2013 | 9:33 pm

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

Mar 07 2013 | 5:13 am

thanks for the remake!

Mar 07 2013 | 5:41 am

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….

Mar 07 2013 | 5:54 pm

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…

Mar 07 2013 | 6:21 pm

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. --

Mar 07 2013 | 6:44 pm

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.

Mar 07 2013 | 6:52 pm

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.

Mar 07 2013 | 7:01 pm

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…

Mar 07 2013 | 7:28 pm

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.

Mar 07 2013 | 7:50 pm

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);
	}
}
Mar 07 2013 | 9:12 pm

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.

Mar 07 2013 | 11:01 pm

edit: SEE BELOW

Mar 07 2013 | 11:32 pm

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
Mar 08 2013 | 4:49 am

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.

Mar 08 2013 | 9:42 am

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
Mar 08 2013 | 6:35 pm

thank you very much timo !

Mar 09 2013 | 8:35 am

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 :)

Apr 01 2013 | 12:58 pm

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

Nov 28 2013 | 12:49 pm

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

Viewing 29 posts - 1 through 29 (of 29 total)

Forums > MaxMSP