Norns: development

Crone talk time! In the PolySub engine I’m seeing a comment that doneAction is busted. The script instead uses freeSelf and detectSilence for freeing a voice. In Engine_Ack, however, doneAction: Done.freeSelf is used for the same purpose.

I’m sure I’ll discover for myself soon, but is there currently known issues with doneAction or not? I don’t see any open issues relating to it.

So i ran SuperCollider 3.91 and it boots the server

see the full log

compiling class library…
Found 731 primitives.
Compiling directory ‘/usr/local/share/SuperCollider/SCClassLibrary’
Compiling directory ‘/usr/local/share/SuperCollider/Extensions’
Compiling directory ‘/home/shree/.local/share/SuperCollider/Extensions’
Compiling directory ‘/home/shree/.local/share/SuperCollider/downloaded-quarks/Vowel’
Compiling directory ‘/home/shree/.local/share/SuperCollider/downloaded-quarks/Dirt-Samples’
Compiling directory ‘/home/shree/.local/share/SuperCollider/downloaded-quarks/SuperDirt’
Compiling directory ‘/home/shree/.local/share/SuperCollider/downloaded-quarks/BatLib’
Open ended symbol started on line 35 of file ‘/home/shree/.local/share/SuperCollider/downloaded-quarks/BatLib/LessKeys.sc’
Compiling directory ‘/home/shree/.local/share/SuperCollider/downloaded-quarks/FoxDot’
Compiling directory ‘/home/shree/.local/share/SuperCollider/downloaded-quarks/TabbedView’
Compiling directory ‘/home/shree/Skoarcery’
numentries = 1300516 / 21562800 = 0.06
6040 method selectors, 3570 classes
method table size 20823960 bytes, big table size 172502400
Number of Symbols 15759
Byte Code Size 470193
compiled 505 files in 2.74 seconds

Info: 4 methods are currently overwritten by extensions. To see which, execute:
MethodOverride.printAll

compile done
localhost : setting clientID to 0.
internal : setting clientID to 0.
Class tree inited in 0.18 seconds
ERROR: Class not defined.
in interpreted text
line 44 char 8:

m = CCIn.new;


softcutvoice startup


Crone startup

OSC rx port: 57120
OSC tx port: 8888

*** Welcome to SuperCollider 3.9.1. *** For help press Ctrl-D.
booting server ‘localhost’ on address: 127.0.0.1:57110
SCDoc: Indexing help-files…
Faust: supercollider.cpp: sc_api_version = 3
Faust: FaustCompressor numControls=6
PluginLoad(SoftCutHead)
Faust: supercollider.cpp: sc_api_version = 3
Faust: FaustZitaVerbLight numControls=5
Found 399 LADSPA plugins
Faust: supercollider.cpp: sc_api_version = 3
Faust: FaustZitaRev numControls=11
Faust: supercollider.cpp: sc_api_version = 3
Faust: FaustCompressor numControls=6
PluginLoad(SoftCutHead)
Faust: supercollider.cpp: sc_api_version = 3
Faust: FaustZitaVerbLight numControls=5
Faust: supercollider.cpp: sc_api_version = 3
Faust: FaustZitaRev numControls=11
JackDriver: client name is ‘SuperCollider’
SC_AudioDriver: sample rate = 44100.000000, driver’s block size = 256
JackDriver: connected system:capture_1 to SuperCollider:in_1
JackDriver: connected system:capture_2 to SuperCollider:in_2
JackDriver: connected SuperCollider:out_1 to system:playback_1
JackDriver: connected SuperCollider:out_2 to system:playback_2
SuperCollider 3 server ready.
JackDriver: max output latency 17.4 ms
SCDoc: Indexed 2015 documents in 4.71 seconds
Requested notification messages from server ‘localhost’
localhost: server process’s maxLogins (1) matches with my options.
localhost: keeping clientID (0) as confirmed by server process.
Shared memory server interface initialized
CroneDefs: sending defs
play_fade
patch_mono
patch_mono_fb
patch_stereo
patch_pan
rec_smooth
adc
amp_env
pitch
soft_cut_voice
polySub
quant_trig
patch_mono_gate_pause
patch_mono_gate_pause_fb
AudioContext: in_b[0] index: 4
AudioContext: in_b[1] index: 5
AudioContext: out_b index (stereo): 6
AudioContext: initPolls
Faust[FaustCompressor]:
Inputs: 8
Outputs: 2
Callback: zero-copy
Faust[FaustZitaVerbLight]:
Inputs: 7
Outputs: 2
Callback: zero-copy

Then i go to ~/norns/build/matron
and run

shree@shree-linux2:~/norns/build/matron$ sclang & ./matron
and i get

[1] 5690
MATRON
norns version: 0.0.0
git hash: 09a5cb6

ERROR (screen) cannot open framebuffer deviceERROR (keys) fail!!
ERROR (enc) didn’t work
BATTERY: FAIL.
ERROR (i2c) failed to open bus
*** WARNING *** The program ‘matron’ uses the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see http://0pointer.de/avahi-compat?s=libdns_sd&e=matron
OSC rx port: 8888
OSC tx port: 57120
waiting for crone…
compiling class library…
Found 731 primitives.
Compiling directory ‘/usr/local/share/SuperCollider/SCClassLibrary’
Compiling directory ‘/usr/local/share/SuperCollider/Extensions’
Compiling directory ‘/home/shree/.local/share/SuperCollider/Extensions’
Compiling directory ‘/home/shree/.local/share/SuperCollider/downloaded-quarks/Vowel’
Compiling directory ‘/home/shree/.local/share/SuperCollider/downloaded-quarks/Dirt-Samples’
Compiling directory ‘/home/shree/.local/share/SuperCollider/downloaded-quarks/SuperDirt’
Compiling directory ‘/home/shree/.local/share/SuperCollider/downloaded-quarks/BatLib’
Open ended symbol started on line 35 of file ‘/home/shree/.local/share/SuperCollider/downloaded-quarks/BatLib/LessKeys.sc’
Compiling directory ‘/home/shree/.local/share/SuperCollider/downloaded-quarks/FoxDot’
Compiling directory ‘/home/shree/.local/share/SuperCollider/downloaded-quarks/TabbedView’
Compiling directory ‘/home/shree/Skoarcery’
numentries = 1299198 / 21246228 = 0.061
5958 method selectors, 3566 classes
method table size 20605008 bytes, big table size 169969824
Number of Symbols 15611
Byte Code Size 466123
compiled 504 files in 0.41 seconds

Info: 4 methods are currently overwritten by extensions. To see which, execute:
MethodOverride.printAll

compile done
localhost : setting clientID to 0.
internal : setting clientID to 0.
starting lua vm
running lua config file: dofile(’/home/shree/norns/lua/config.lua’)
Class tree inited in 0.17 seconds
ERROR: Class not defined.
in interpreted text
line 44 char 8:

m = CCIn.new;


script clear

ERROR (i2c) failed to acquire bus access and/or talk to slave
last file loaded: tehn/awake.lua

script load

cleanup

script clear

script run

loading engine; name: PolyPerc
failed to open hid device: /dev/input/event3
dev_list_add: error allocating device data
failed to open hid device: /dev/input/event16
dev_list_add: error allocating device data
failed to open hid device: /dev/input/event4
dev_list_add: error allocating device data
failed to open hid device: /dev/input/event5
dev_list_add: error allocating device data
Engine.register_commands; count: 6
— engine commands —
amp (f)
cutoff (f)
gain (f)
hz (f)
pw (f)
release (f)

— polls —
amp_in_l
amp_in_r
amp_out_l
amp_out_r
cpu_avg
cpu_peak
pitch_in_l
pitch_in_r
tape_play_pos
tape_rec_dur

script init

grid/seek
reconnecting grid…
grid.reconnect (default)
reconnecting midi…
midi added: 1 AudioBox USB
midi added: 2 Moog Sub 37
midi added: 3 Moog Minitaur
softcutvoice startup


Crone startup

OSC rx port: 57121
OSC tx port: 8888

*** Welcome to SuperCollider 3.9.1. *** For help type ctrl-c ctrl-h (Emacs) or :SChelp (vim) or ctrl-U (sced/gedit).
booting server ‘localhost’ on address: 127.0.0.1:57110

And back in supercollider 3.9.1 i get

/crone/ready
/crone/ready
[ /auxfx/on ]
[ /auxfx/input/level, 0, 0 ]
[ /auxfx/input/level, 1, 0 ]
[ /auxfx/input/pan, 0, 0 ]
[ /auxfx/input/pan, 1, 0 ]
[ /auxfx/output/level, 0 ]
[ /auxfx/return/level, 0 ]
[ /auxfx/param, rev_in_delay, 60 ]
[ /auxfx/param, rev_lf_x, 200 ]
[ /auxfx/param, low_rt60, 3 ]
[ /auxfx/param, mid_rt60, 3 ]
[ /auxfx/param, hf_damping, 6000 ]
[ /insertfx/off ]
[ /insertfx/mix, 1 ]
[ /insertfx/param, level, 4 ]
[ /insertfx/param, threshold, -18 ]
[ /insertfx/param, attack, 5 ]
[ /insertfx/param, release, 50 ]
[ /insertfx/param, makeup_gain, 9 ]
a CroneAudioContext
[ CroneEngine adding command, hz, f, a Function ]
[ CroneEngine adding command, amp, f, a Function ]
[ CroneEngine adding command, pw, f, a Function ]
[ CroneEngine adding command, release, f, a Function ]
[ CroneEngine adding command, cutoff, f, a Function ]
[ CroneEngine adding command, gain, f, a Function ]


– crone: done loading engine, starting reports

engine: an Engine_PolyPerc
command entry: [ 0, hz, f ]
command entry: [ 1, amp, f ]
command entry: [ 2, pw, f ]
command entry: [ 3, release, f ]
command entry: [ 4, cutoff, f ]
command entry: [ 5, gain, f ]
cpu_peak
cpu_avg
amp_in_l
amp_in_r
amp_out_l
amp_out_r
pitch_in_l
pitch_in_r
tape_rec_dur
tape_play_pos

And tehn’s AWAKE starts playing :slight_smile:

Now i am wondering how i can tweak the lua script or send it control ?

i did not hook up the grids because it’s busy on the physical norns [physical Nornfitti] —sorry i need therapy

1 Like

There are no issues with doneAction and norns in particular.

You probably already know this, but doneAction is a way for ugens included in a SynthDef to trigger certain kinds of actions (ie. free a synth on when an envelope has been released).

The difference between PolySub and Ack is that in the former synth voice nodes are automatically freed upon audio signal silence whereas in the latter synth nodes are always explicitly freed in sclang code (here: https://github.com/monome/dust/blob/master/lib/sc/Engine_Ack.sc#L516). But as you can see from comments and todos, I eventually want to have self-freeing synth nodes in Ack.

1 Like

@shreeswifty mod edit: put your log inside a [details] tag (please use this in the future with multi-page logs so the thread stays quickly readable, thanks!)

3 Likes

I’d like to know more about the decision to use Lua rather than sclang? Understanding those motivations may give me some insight into the overall direction and method that the core team has in mind.

1 Like

3 posts were merged into an existing topic: Norns on Raspberry pi + Blokas PiSound

quick question: when using require to load a lua class from lib/lua, is it possible to force norns to re-evaluate the lib script? seems like running the main script from maiden doesn’t re-run the scripts pulled in with require, they’re cached somehow right.

its a hack, but this works

function unrequire(name) 
   package.loaded[name] = nil
   _G[name] = nil
end

maybe we should put this in lua utils

pretty sure i was running into the same issues we discussed in this thread:

like this one:

i think we’ve talked about this a bit. but in a nutshell:

  • sclang is cool, but weird, and maybe a hard / dangerous way to get into programming for the inexperienced
  • maybe more importantly, we don’t necessarily want to be wedded to scsynth. we want people to be able to implement other audio backends if they want.

ultimately this wasn’t an obvious decision to make and we went back and forth, but i think it makes sense in the end.

4 Likes

Some concern I’ve heard in “hallway conversations” amounts to a notion that it may be more difficult to create abstractions in Lua than in a more structured language (as sclang is, with its smalltalk heritage).

But I get the idea of wanting to support multiple audio engines.

It feels like Lua really is a linch-pin the norns ecosystem. We could replace other bits and it’d still be norns, but take Lua away, and it isn’t really norns any more. If this really is the case, it might be a good idea to address some of the concerns around whether it will be possible to make the kind of “composition of control” abstractions that some folks are eager to pursue.

I don’t personally have any hunches about this, nor am I taking any sides, just reporting on some observations of conversations about concerns. I haven’t written large amounts of Lua before (and certainly not in anger) so I really don’t have the same worries that I’ve heard from some other folks.

i don’t buy that. lua is like javsacvript if you substitute tables for objects, and supports all the abstractions you want. functions are first order objects and you can do functional programming. tables can be used as prototypes and you can do OOP. it has “weak” dynamic typing kinda like JS.

it’s bare bones and you have to roll your own systems for various kinds of abstraction, but it’s not particularly limited.

like i said, i like sclang. but it’s clunky in many ways, very hard to extend with C primitives when necessary, and its a big messy project. we might want to drop it altogether at some point (opinions welcome)

you’re right, it needs work to build out the lua environment that norns relies on. i have confidence that this will happen in good stead with the community here.

[rephrased, don’t wanna start a religious war]

for more experienced developers it doesn’t seem too onerous to use lua. for newcomers it seems more friendly than pretty much any other option besides javascript. (i’ll just add that this wasn’t really my decision and i am just conveying my impression of our collective reasoning.)

8 Likes

Oh, I don’t know. There are definitely some old farts with mad skills and strong language preferences in the world. I’m not one of them, but they’re around.

Confidence + Competency + Planning = Results

FWIW, is there a backlog of enhancements/bugs a PM-type like me could peer at with my PM hat on?

mod edit @shreeswifty i deleted your post above that was nearly identical to your post another thread (and that thread is the right place)

Ok, I have done some reading on the SC github discussions and it looks like this issue is going to be a constant pain (at least from the perspective of a noob): The punchline is that there is undefined behavior for doneAction when gate high and gate low occur in the same block (faster than SC server’s control rate). Since there is no guarantee that Matron will pass Crone messages at a digestible rate, we will need to account for this behavior in every SC script, i.e. don’t use doneActions in uGens with Matron-facing control signals. Or we will need some sort of message buffer…

This looks like a promising resource: Synchronous and Asynchronous Execution

Each of the repos has a healthy issue list, for example norns and maiden. In a few instances there are tags to try and quickly distinguish between bugs, enhancements, etc.

What does not currently exist is a formalized roadmap of where each of the components is heading. Additionally one area which was discussed (prior to release) but not resolved was how to best track and coordinate changes across each of the components that come together in an “update”.

Thanks for the links, I will go and peer at those repos.

As someone who has functioned as a product owner in both the commercial and non-profit worlds, I can safely say that roadmaps are better thought of as verbs than nouns. The process of sorting what should be done in the context of what must be done is always fruitful, and through that discussion all manner of things get discovered (e.g., to what extent should back-end work be done before a particular script gets added, or what scripts should be released together in order to maximize end-user happiness) that can play a role in making release decisions.

TBH right now this isn’t mission critical - there’s plenty of low-hanging fruit in the queue. But soooon.

As for tracking and coordinating changes across each of the components, that gets easier if you’ve got a plan ahead of time plus a vigorous QA process to match it.

EDIT:

A few things jump out on review of the issue list that will help with the PM side of this adventure:

  1. Amend naming of bugs and enhancements to make them more descriptive while retaining brevity
  2. Propose a controlled vocabulary around tags for functional product areas for consistency (e.g., tape, menu)
  3. Propose a format for describing releases and a tagging system to support this
  4. Consistent use of bug vs enhancement vs new feature vs research tags
  5. Adopt a way to identify show-stopper bugs vs occasional/minor bugs (e.g., a priority system)
  6. Create master list for scripts

FWIW the maiden queue seems to have a higher level of rigor around tagging than the norns queue.

6 Likes

Crone / individual engines could fix this by scheduling note end events (e.g. .set(\gate, 0) with latency rather than immediately (which is generally though not always how Synths are scheduled). This effectively becomes a minimum note duration. For example, in Engine_PolySub:

	removeVoice { arg id;
		if(true, { //voices[id].notNil, {
			s.makeBundle(s.latency, {
   				voices[id].set(\gate, 0);
			});
			//voices.removeAt(id);
		});
	}

The latency-minimizing version of this would track the note start time, and only use additional latency if the \gate=0 is within some “minimum note duration” window.
The perfect-perfect-reliability version would do something like this (e.g. don’t stop until you know it’s started):

if (voices[id].isRunning) { 
	voices[id].set(\gate) 
} { 
	voices[id].addDependant({ 
		|n, m| 
		if (m == \n_go) { voices[id].set(\gate) } 
	})
}

There’s may be one or two narrow cases of this problem that can be fixed in the server, but at the end of the day it’s represents a true ambiguity: the \gate value (or any value for that matter…) has been set to both 1 and 0 at the same logical time. Does this mean my gated envelope started and ended (and thus should e.g. free’d), or does it mean I’ve simply set my gate to zero by idempotence, and the envelope has not started at all?

3 Likes

Ha! Well that is just a quirk of history and special attention given by @ppqq - he and @jlmitch5 pitched in early so I had started to tag stuff in advance of onboarding additional folks.

2 Likes

@bobbcorr
thanks for taking a look, that is great advice. messines of norns issue list is basically on me - the dangers of spending a long time without collaborators; brian and i used it as an unstructured to-do list for too long and it is now neither well-organized, well-documented or comprehensive.

as @ngwese and @ppqq have pointed out, we need both a guide to usage for the issue page, and better use of meta-issues and milestones.

i will try and spend a little more time with a… “lead-dev?” hat on as well, making things more useful, now that the thing is public.

@scztt
thanks, that is a great tip and makes perfect sense. will clean it up. PRs also always welcome

1 Like

I’ve got a norns coming in batch 2 - I’ll probably need a solution to this in order to integrate my own synths at that point anyway, so I’d be happy to push a more generalized solution back to Crone if it hasn’t already been addressed by then.