^^ crow: druid scripts

Sorry if this is stupid but will you be adding this to the Bowery collection?


Sure, I could do that, but I think I’d still like to refine it some and add some other parameters. For instance it would be nice to select (maybe per-output) whether the samples should be the same as bin values (more useful for pitch CV) or should be sampled randomly from the range of values that fall in that bin. Of course, it’s easy to update a script on Bowery, but I feel like I’m still experimenting with the idea a bit. If you want to try out this version you can click the “Raw” button on the GitHub page to get a version you can copy-paste, or equivalently right-click this link and select some option like “download link” in most web browsers.

1 Like

this seems super interesting. hope to get the chance to give it a try…thinking about feeding the input a sequence from Bloom, then slowly mutating the input sequence over time…:metal:

1 Like

Getting a [string "eval"]:1: <eof> expected near 'end' User script evaluation failed. error with the following simple code. is there something i’m missing here?

--- simple tuner/buff mult app. put a voltage into input 1, stream the value to druid and send voltage to all outputs
-- in1: tuning voltage
-- out1-4: duplicates of in1 voltage

function init()
	input[1].mode('stream', 0.01)

input[1].stream = function(volts)
	output[1].volts = input[1].volts
	output[2].volts = input[1].volts
	output[3].volts = input[1].volts
	output[4].volts = input[1].volts

I have the following set in sublime for tab size. Does crow expect a certain tab size?

// The number of spaces a tab is considered equal to
    "tab_size": 4,

Make sure you have a newline after the last line. It seems that it sometimes has a problem loading scripts if not. Also, I think it’s still better to set your editor’s newline setting for the file to be carriage-return/line-feed (if you’re on a Mac or Linux it will default to just line-feed, I believe PC already should be set to cr-lf). There was some talk of this being addressed in a Druid update, but I’m not sure this has happened or if it’s completely addressed the issue.

Also, sometimes a reset of Crow (^^r) before uploading the script can help.

Assuming your "translate_tabs_to_spaces" setting is false, it doesn’t matter. That just sets how tabs are displayed in Sublime. If it’s set to true it also doesn’t matter as far as Crow is concerned, but once you start writing longer scripts you may find all those extra spaces are pushing your script over the 8kb limit for script upload.

1 Like

Ah ok thanks for info!

I no longer believe line endings make a difference and tabs shouldn’t matter, but missing a line ending at the end of the file might. Personally I am most suspicious of the very long comment in the first line of the script causing some kind of problem, I will experiment with this script some and see what I can find. Certainly none of the above should be a problem but it may require some changes to druid.

I just copy+pasted your posted script into a text file & had no problem uploading it to my crow.

What version of crow firmware are you on? You can check by typing ^^v in druid. Also, what version of druid are you on? You can check by typing druid --version in Terminal.

I believe we fixed all the issues regarding long lines & carriage-return/newlines in the latest crow&druid. Tabs vs spaces doesn’t matter, and whether there’s a newline at the end of the script doesn’t matter.

This is beside the error message you’re seeing, but i don’t think the script will work due to using the argument name volts to the input[1].stream function. This argument will mask the existing behaviour of the input & output tables when using the key ‘volts’, instead trying to index into those tables using the actual voltage on the input jack. Something like this should do it:

input[1].stream = function(v)
  for n=1,4 do
    output[n].volts = v -- because v == input[1].volts

OK thanks all for detailed and thoughtful info as always. It seems I was on an older dev version of druid, I’ve updated to druid, version 0.2.1. crow is ^^version(‘v1.0.1’).

With this config, If I upload the script without the final carriage return, I get:

[string "eval"]:13: 'end' expected (to close 'function' at line 11) near <eof>

If i add the final carriage return, the script loads successfully, but only after I run ^^c.

on another note - in the below updated script, only input[2] streams to druid, how can i make input[1] stream to druid and the outputs?

--- simple buff mult. put a voltage into input 1, stream the value to druid and send voltage to all outputs
-- in1: tuning voltage
-- out1-4: duplicates of in1 voltage

input[1].stream = function(v)
	for n=1,4 do
    output[n].volts = v -- because v == input[1].volts

function init()
	input[1].mode('stream', 0.01)
	input[2].mode('stream', 0.01)

anyway. this works pretty well for what I wanted to do - compare v/oct tuning between various oscillators.

Thanks for the details! I’ll try and reproduce again. Which OS are you running? To clarify, when you say “add the final carriage return” does that mean you’ve added a blank line at the end of your text file?

re: streaming to druid
This works by using the default event for input[n].stream. When you redefine input[1].stream that stops sending the value to druid, instead using the value in your script. You can work around this by adding the default action from the input library to your event:

input[1].stream = function(v)
  crow.tell('stream',1,v) -- sends the voltage to druid
  for n=1,4 do
    output[n].volts = v -- because v == input[1].volts

Or you could use a metro instead and leave the input event untouched:

function set_outs()
  for n=1,4 do
    output[n].volts = input[1].volts -- need to query the input lib again

function init()
  input[1].mode('stream', 0.01)
  input[2].mode('stream', 0.01)
  m = metro.init(set_outs, 0.01)

:slight_smile: I’m on window 10. Yes - I’ve added the final blank line.


Thanks for stream details.

1 Like

this is a very simple chord voicing script for crow. trying to understand lua and what is possible. also my math might be off :confused:

--- generate a chord from a single input 
-- in1: gate in
-- in2: chord root quantized to v/oct 
-- out1: chord root
-- out2-4: chord degrees from root
--3 note chords also have an octave below root on out4.

maj = {1,4,7,-12}
min = {1,3,7,-12} 
dim = {1,3,6,-12}
maj7 = {1,4,7,11}
min7 = {1,3,7,10}
dom7 = {1,4,7,10}
sus2 = {1,2,7,-12}
sus4 = {1,5,7,-12}
aug = {1,4,8,-12}

--set the chord to play. also change this from druid.
chord = min7

--clock in
function init()
	input[1]{mode = 'change', direction = 'rising'}

--build the chord
input[1].change = function()
	--get the voltage from input 2
	v = input[2].volts
	--get the chord degrees, /12 to get semitones in v/oct
	ii = chord[2]/12
	iii = chord[3]/12
	iv = chord[4]/12
	--output the chord
	output[1].volts = v
	output[2].volts = (v + ii)
	output[3].volts = (v + iii)
	output[4].volts = (v + iv)

chord.lua (942 Bytes)


I’ve not tried it yet but I’m reading through the Boids script and it’s blowing my mind. This module is so exciting.

I was messing around making a Krell patch (I’ll share that later…) where I wanted some more control over the weight of the randomness than a simple exponential curve. I figured other people might find the curve function useful so I put together a simple example script. In addition to the min/max value settings, the method has three parameters that control how the randomness is weighted, each an integer value 1 -6:

  • curveLevel - higher values make a steeper curve favoring one end
  • bellFactor - higher values focus the curve more sharply in the middle
  • direction - which end the curve favors - up or down

Here’s a chart that will hopefully help make sense out of how the curveLevel and bellFactor interact.

Click to see chart

Here’s the example script. It doesn’t do anything interesting, it just has a metro sending random voltage out of output 1 based on the settings. Connect output 1 to an oscillators pitch and you can hear how the curve sounds as you adjust the values (curveLevel, bellFactor, and curveDirection) via druid.

curvedrandom.lua (1.1 KB)


I made another little utility. I’m always finding myself befuddled about the CV range a given input wants to see. The main function of this script is to take CV into input 1 OR input 2 and scale it out the outputs.

  • If it sees voltage at input 1, it sends a separately scaled voltage out each output
  • If it sees voltage in input 2, it sends the same scaled voltage out of every output

You can also send it a message in order to just send an arbitrary fixed voltage out each of the outputs, or a different fixed voltage out of each.

Hopefully the comments in the script will make usage clear. Let me know if something doesn’t make sense.

vults.lua (3.1 KB)



I’m not lua or music theory wiz, but i think the major chord should be {0, 4, 7, -12} (or if 0 doesn’t work {1, 5, 8, -11}).

So all the starting notes (or following notes) are off by 1.

Ah yes I think that is correct. Heh. I’ll have another look, thanks! Haven’t had time to look at crow in the last few weeks, must get back to it.

Here’s my take on the Krell patch. If you are unfamiliar with this idea, find info here:


My Crow version outputs envelope and pitch plus two other user selectable CV values. I hope that between the comments in the script and the sensibly (?) named variables, the use of this patch should be fairly clear (though perhaps not simple…but if we have to wait for me to write a more thorough manual, we’re all going to grow old and die). Of course, feel free to ask questions if anything is unclear.

krowll.lua (4.9 KB)

Here’s an example of the patch in use:


I’ve been working on this script off and on and wanted to share something I thought might be useful to others.

Here’s the script: jfInt.lua (1.3 KB)

In short it plays notes from an array of arrays using integers for rhythmic information.

All the variables used for incrementing live in single-entry arrays because Lua passes arrays by reference (and passes numbers/strings by value), which is useful for maintaining global state while also allowing me to cut down the amount of repeated code.