it would be straightforward for a script to generate a parameter list programatically given the output of engine.commands.

We can facilitate interconnection by making norns programs use a common discovery API. If synths (and effects, etc) are self-describing, that other programs can discover their various parameters. If each synth provided a method that enumerates its parameters (and their units, ranges, etc) then a user of that synth could automatically populate a UI (for example).

3 Likes

I’m very much in favor of such an approach. This closely resembles SuperCollider’s SynthDescLib in which each added SynthDefs’ arguments is spec’ed and can be looked up in a dictionary, and reused ie for its Pattern framework (such as Pbind).

Something along these lines (self-describing engines, engine parameters) has also been discussed prior to release.

It should also be noted that currently engine commands and metadata are only retrievable after an engine has been loaded. Ideally, I would want to be able to view an engine’s “schema” (so to speak) without having to load it.

3 Likes

whilst forking norns, for some dev work on macOS,
Ive noticed someone has a ‘case’ issue… master has both doc/modules/Log.html and doc/modules/log.html committed.
this will cause issues on platforms that are case-insensitive (windows) or case-preserving (mac os)

on my fork, Ive just removed docs/modules/Log.html (its the older of the two) , and that resolves the issue.

perhaps @tehn as you have access, you could delete Log.html directly on GitHub.com.

2 Likes

ok, so Ive now gone thru the norns/matron code base in more detail, and have a pretty good understanding go how it ticks…but, im back to struggling with issues around abstraction,

screen

I dont think doing this via a pre-processor flag is the best way (though perhaps easy)
I think it should be possible to have alternative ‘screen implementations’ co-exist, and even potentially have multiple screens. (perhaps one marked as ‘primary’ to help make app dev easier)

grid

these also seem to be, to some extent, hard-coded, since weaver calls thru the dev_monome_*
I think a grid should be an abstract concept, again where different implementations can co-exist


so Im wondering, how is it intended for norns to have new devices added/supported?
(excluding midi, which i know could be done in the lua/script layer, though that has its own issues)

having been thru the whole matron stack, its strikes me there are two directions:

  • more abstraction, looser coupling
    my preferred direction, but needs a bit of careful consideration about abstraction/interfaces.
  • adding more specific devices/events
    not a good direction in my opinion, currently doing this means touching lots of ‘core’ code, and would potentially make norns unwieldy mid-term (if many devices were added)

so I guess im asking, whats the thoughts of the dev team? is anyone actively working in this area?

p.s. sorry, I’m being ‘coy’ about what im actually doing, but thats because im not ready to ‘announce’ it in a public forum - I prefer to only announce once ive got something working, rather than vapourware/promises.
(Id be willing to privately talk to someone about this, if you want more details, and I could walk thru in more details the ‘issues’ i see in norns)

alsa raw midi: how does this handle midi devices with multiple midi ports? tested?
it seems to me that only one raw device file is created (/dev/snd/midiCnD0) is created even if devices has multiple ports, so you only have access to one port - whereas the alsa api (as say used by amidi -l ) includes sub-devices.

vid/pid for usb devices: it would be useful to have vid/pid available, and perhaps use this to help drive ‘device type’, or at least allow you to ‘override’ the default handling e.g. something might be usb midi class compliant, but you want to have specific handling.

btw: if no one is working in this area of the matron code (abstraction/device identification) , Im thinking of having a bit of a play -perhaps just getting a little more flexibility in there e.g. single device override, that we can then look to extend later ? of course if you don’t like it, you can always reject a PR.

1 Like

we started with an alsaseq-based implementation, but changed that to rawmidi later because rawmidi can be used with matron device manager out of the box (and it’s much better to have a single device manager than having 2 subsystems for notifying scripts about new devices).

i have a device with 2 sequencer ports myself and apparently it just works with norns/rawmidi.

right, we currently provide device name (as reported by udev) for that as well.

1 Like

i think that is what we are talking about, no?

and we are just working out the best place to put it right now.

i think imposing a descriptor format on every engine command, and pushing those descriptors through OSC, and into lua, is a lot of extra infrastructure that is brittle (in ways we might not foresee right now) and doesn’t accommodate a lot of more experimental structures.

(i’m emphatically not interested in recreating Audio Units, for example - way too prescriptive. if you try to accommodate a broader range of musical control structures you end up with something like LV2 - which has a lot of neat ideas and is super flexible, but also pretty inaccessible. an alternative version of norns would just be an LV2 host, solving many of these questions but requiring tons more work to implement DSP engines.)

what @jah has already done with the ack engine seems like a good template for an immediate pragmatic solution - the “discovery/descriptor” part is implemented in lua, alongside the engine, and just provides defaults for the existing parameter system in lua. it’s not as architecturally elegant as doing everything automagically in the engine API, and it requires the .sc and .lua components to be synchronized, but it’s a lot less work and more flexible - e.g. scripts can easily override or ignore the boilerplate as desired.


ok… well, this isn’t really compelling for me at this point. we want to work on cleaning up, extending and improving the core features for the norns device - not making it into a video synth (just yet), and not making the software work on hypothetical alternative hardware or on someone else’s product. if you want to do that it’s fine. if you want to, say, use a second screen for development (presumably with a usb-vga adapter), then i don’t see how that relates to supporting other outputs with the cairo drawing commands available to norns scripts.

sure. this sounds like its better done on the lua side to me. but it’s also a little vague what we’re talking about.

i’m assuming you want to say something like - “this script is designed to be used with a grid controller of at least MxN size - but it should work either with a monome TTY device or a MIDI device, and should seamlessly connect to one or the other when plugged.” ok cool - this sounds like a job for a (simple) adapter class in lua, and of course we would welcome such a contribution.

the matron C stack is about providing lower level connections. it’s simple. libevdev for hid, rawmidi for midi (and yes, as far as we can tell this supports multi-port devices just fine), libmonome for monome, OSC for whatever else.

the only device class that’s missing, in my opinion, is alternative TTY-based protocols. but this is such a vague category that i’m waiting for some actual use case to appear before worrying about it.

if it would be useful to pass more descriptor data to lua for each device class , that’s simple enough to do and doesn’t require some huge restructuring.

if you want to make the C device layer super smart and have the weaver layer be more abstracted, i guess i’d be curious to see what you come up with, but not sure i see the engineering advantages.

5 Likes

Apologies if I was just restating the obvious with my comment. I think having a discovery method at the lua level would be sufficient, it needn’t be plumbed through to sc. Maybe I’m naive to some of the potential challenges/applications though.

i tried this and i get this

ERROR: Message ‘lookup’ not understood.
RECEIVER:
nil
ARGS:
Float 0.000000 00000000 00000000
CALL STACK:
DoesNotUnderstandError:reportError
arg this =
Nil:handleError
arg this = nil
arg error =
Thread:handleError
arg this =
arg error =
Thread:handleError
arg this =
arg error =
Object:throw
arg this =
Object:doesNotUnderstand
arg this = nil
arg selector = ‘lookup’
arg args = [*1]
CroneAudioContext:buildVuBlob
arg this =
var ret =
< FunctionDef in Method Meta_Crone:initVu > (no arguments or variables)
Float:do
arg this = inf
arg function =
var i = 0
Routine:prStart
arg this =
arg inval = 3.970006393
^^ The preceding error dump is for ERROR: Message ‘lookup’ not understood.
RECEIVER: nil

but the rest continues on to the

Faust[FaustCompressor]:
Inputs: 8
Outputs: 2
Callback: zero-copy
Faust[FaustZitaVerbLight]:
Inputs: 7
Outputs: 2
Callback: zero-copy

similar errors anyone?

sorry it’s related to this
Execution warning: Class ‘ReverseAudioTaper’ not found
ERROR: Message ‘lookup’ not understood.

so it’s missing AudioTaper.sc which is currently living in dust/lib/sc/abstractions. it should get copied by the sc install script

(sorry this could all use a little tidying up for general use. like the symlinking procedure is very weird just to avoid some issues i was having during development with editor backups and other non-.sc files.)

i don’t see it in there i dont actually see anything in dust/abs except for
/emb Engine_Ack.sc Engine_Glut.sc Engine_PolyPerc.sc Engine_TestSine.sc Engine_Why.sc

needed a pull
i think i grabbed dust last week! LOL

240px-Page_004_(Faust%2C_1925)

aha faust! now i am seeing this magical plan unfold

3 Likes

That’s not the case. I appreciate your input on this.

It should be noted that lib/lua/jah/ack.lua as of now isn’t really made for discovery as it doesn’t really contain metadata for the ack engine. It’s purpose is simply to provide a convenient way for scripts to add ack parameters to the global paramset with one function call Ack.add_params(). Metadata is available (controlspecs in Ack.specs) but these describe common lua side UI parameters, not the engine.

That said, I believe a similar approach could be used to declare engine metadata based on the osc protocol: commands, polls, et cetera. which could be used for autogeneration of UI, bindings, et cetera.

Such an engine metadata file might even be possible to extract/generate from the sc engine code, I dunno.

EDIT: uh, actually lib/lua/jah/ack.lua specs are actually a subset of engine specs. but they’re do not cover all engine parameters, only the ones relevant to menu > parameters.

2 Likes

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