thanks for the swift reply! sounds like great future plans!
@lazzarello you can use arrays and array arguments in synthdefs, though there are some limitations. see the help files for SynthDef
, Mulltichannel Expansion
, Mix
, &c.
here’s an example with 3 sinewaves in a phase-modulation loop. (feedback provided by LocalIn
/LocalOut
.)
demonstrates:
- array arguments (for freq, mod index, and delay time)
- building and using arrays of ugens programatically in the synthdef
note the use of the array literal notation (#[]
)
(warning: gets noisy)
Routine {
SynthDef.new(\fm3, {
arg out=0, amp=0.05,
freqs = #[110, 220, 330],
mods = #[0.1, 0,1, 0.1],
delays = #[0.001, 0.001, 0.001],
freqlag = 0.1, modlag=0.1, delaylag=0.1;
var mod_in;
var mod_out;
var sins;
mod_in = LocalIn.ar(3);
sins = freqs.collect({ arg f, i;
SinOsc.ar(Lag.kr(freqs[i], freqlag), mod_in[(i+1)%3] * Lag.kr(mods[i], modlag))
});
mod_out = sins.collect({ arg sin, i;
DelayC.ar(sin, 0.2, Lag.kr(delays[i], delaylag))
});
LocalOut.ar(mod_out);
Out.ar(out, amp * Mix.new(sins));
}).send(s);
s.sync;
x = Synth.new(\fm3);
// command-period to stop!
inf.do ({
(1 + 1.0.rand).wait;
x.set(\freqs, Array.fill(3, {200 + 200.rand}).postln);
x.set(\mods, Array.fill(3, { 2.0.rand}).postln);
x.set(\delays, Array.fill(3, {0.1.rand}).postln);
})
}.play;
Weird Lua syntax stuff in my FM7 adventure.
I’m referencing the lib/mark_eats/mollythepoly.lu
a library. I didn’t recognize a syntax for adding key/value pairs to a table. It looks like this
params:add{type = "control", id = "pulse_width_mod", name = "Pulse Width Mod", controlspec = specs.PW_MOD, action = engine.pwMod}
I got the same results with two lines I recognized from some tutorials, like so
params:add_control("pulse_width_mod","Pulse Width Mod", controlspec.new(0, 1, "lin", 0, 0.2, ""))
params:set_action("pulse_width_mod", function(x) engine.pwMod(x) end)
I thought I’d test what I think are the semantics so I did this and got an exception on the first try.
foo = {}
<ok>
foo{type = "control", id = "wtf?"}
lua: stdin:1: attempt to call a table value (global 'foo')
stack traceback:
stdin:1: in main chunk
Do tables get an add
method by default? It appears not. What’s going on here?
foo:add{type = "control", id = "wtf?"}
lua: stdin:1: attempt to call a nil value (method 'add')
stack traceback:
stdin:1: in main chunk
because that’s not what that is. :add
is a method of the paramset
class (in paramset.lua
) of which the global params
is an instance.
this would work if foo
was a function with a single argument (a table). in lua, you can omit the parens in a fn call if the fn has only one argument
Woah, h4x. That’s pretty clever, though in no way intuitive. It def cuts down on the number of lines for UI stuff.
see here re params syntax: Norns: update 181002
furthermore:
some_function({element1=345, ish="whatever"})
is the same as
some_function{element1=345, ish="whatever"}
fancy lua-jazz
I changed the code in a library. How do I reload Lua libraries in the path lib/lua/mydir/foo.lua
?
I tried loading a new script and reloading the one that requires this library. The code changes are not on the device (they expose new params). I restarted the audio engine. Still no change. I loaded the code from a script through Maiden. No new params. I rebooted…new params.
Any way to force reload libraries without rebooting?
you have to muck with the package cache directly. i did this enough a while back that i stuck it in a util:
using this you could reload your lib like this:
local my_lib = reload('my_lib')
(note this won’t follow transitive dependencies so you need to explicitly reload everything that’s changed.)
I did it!
FM7 is a Norns interface for the FM7 UGen, a phase modulation oscillator matrix. This is an MVP release. The engine is a 16 voice polyphonic synthesizer.
Notable features.
- Device UI displays 6x6 modulation matrix and which of the 6 operators are output to audio
- Key 2 for random modulation matrix + carrier output
- Key 3 for random note event
- Encoders 1 - 3 change operator 1 frequency multiplier, phase, amplitude (pre output)
- Grid in Earthsea sequencer mode
- All params exposed via PARAMETERS menu
- MIDI!
- OSC for all params should “just work” as of norns v1.1.0
Thanks to @catfact , @tehn , @markwheeler , @pq and @junklight for Norns/Lua/SC help.
Special thanks to Stefan Kersten who made the FM7 UGen over 10 years ago.
just having a play - this is really cool
obviously I now want changes: needs operator envelops and midi pitch bend
is there any way of editing the mod matrix? or do we just get to cycle around random things?
All those niggles apart this is an amazing basis - I’m going to use this as a basis for my multi-timbral project and it will help with the FM idea I had (more of an experiment - no idea if it will make anything musically useful but I’ll share it if it does)
(edit - nowhere near as noisy as my old FM7 (that I sadly lost in a house move) though… )
you can edit the deeper params in the PARAMETERS menu
enjoyed a quick run with the engine, sounds great! curious to come up with more UI ideas for config
yeah spotted that
does sound wonderful - just basically sitting playing it at the moment …
I wanna make a preset system next, which would make it easy to add the 32 “official” algorithms from the DX7. A second page for the UI that shows the graphics could be a cool addition.
you’re in luck! a “preset” system is built-in to the parameter system.
hold KEY1 when in the param menu. you can save/load pset files. they’re human-readable, so you could potentially make a quick text-scrub script to convert the factory presets
Apologies for the newbie question, how would i install this FM7 engine into norns?
oh my, that seems almost too easy.
I think operator envelopes would be a good next thing along with presets.
Depends if you want to get your hands dirty with Linux stuff. If you do, you can track the master branch on the device.
- enable wifi
- ssh to the device
ssh we@norns.local
passwordsleep
- backup dust folder
mv ~/dust ~/dust.bak
- clone git repo
git clone https://github.com/monome/dust.git
- reboot device
sudo halt
followed by long press to turn on
If you aren’t comfortable doing this, you can wait for an update to the device and use the built-in update system.
this has the drawback of removing any custom work you’ve done through the Maiden IDE. You will have to move those files back by hand. I don’t really know a way around this until the OS on the device is updated to not save artifacts like audio recordings and presets to the folder tracked by git.
ya - and if you want “classic” dx7ish behavior then you want a pitch envelope which can be arbitrarily applied to each osc.
Oops, looks like I labeled the phase mod params backwards. Currently the param that says “Osc1 Phase Mod Osc6” actually sends oscillator 6 to modulate oscillator 1.
There’s some cruft in there from my repo getting out of sync with master…I’ll help get this in order if someone can review the diff.
Thanks - need to get a little more comfortable first - still getting used to code structure, lua in general