Norns: ideas

Great idea. I used to think about that sort of thing quite a bit. I just wanted to mention that this also reminds me a bit of the Björk: Biophilia interactive album app, which was a fantastic concept!

1 Like

Not sure if it belongs here but wanted to ask about a couple of usability improvements. I feel this changes would do good experience of using norns even better and more immediate.

  • Would be awesome if Pset loading option was before saving in the menu. Might seem counter intuitive but I use loading all the time and saving just occasionally.
  • Also not sure if Pset needs its owns menu with submenus. I thing options that are there would be better on the top level.
  • Would be cool if script options in params would go before other system params, same reason as before I mostly don’t use them and would prefer not to have to scroll through them all the time.
  • Some dB levels can not be set precisely or zeroed. Compressor post gain for example, even while holding K3. It’s not obvious why dB params change in such strange intervals.

This might seem like nitpicking and I guess it really is. But it comes from a fan of the platform :slight_smile:

3 Likes

i can speak the last point a little (with apologies for tediousness.)

i agree it would be better if the parameter value were quantized to nearest decibel.

i think there is no design reason for the present behavior, just expedience:

  • these are parameters of type control. this means they map a “raw” value in [0, 1] to an arbitrary range, quantum, &c, as defined in a ControlSpec. for example, the output range for compressor post-gain is [-20db, +60db]. (here.)

  • the :delta method for control params accepts an incoming number, scales it by 1/100, adds to the raw value, and updates the scaled value. (here.)

  • the output of the raw->ranged mapping is optionally quantized (according to the ControlSpec.) the audio parameter specs do not declare quantization values. (see first link.) so you could try simply changing the line

local cs_POSTGAIN = cs.new(-20,60,'db',0,9,'dB')

to

local cs_POSTGAIN = cs.new(-20,60,'db',1,9,'dB')

[norns/lua/core/audio.lua, line 450]

to round to 1db, and see how that feels.

  • however, the other factor is the input to the :delta function. this is an integer corresponding to the number of positions the encoder moved on the last tick. in fine adjustment mode, the encoder movement is scaled by 1/20.

so, it might feel a little weird to round the scaled parameter values to 1db when changing the raw values by multiples of 0.01 (since encoder movements are integers) - in the case of postgain you will be moving the value in increments of 0.8db that are then rounded to 1db, producing a funky jitter, but maybe that is OK. “fine adjustment” mode will probably feel better. the encoder scaling in “coarse” mode could be made smaller.


more generally, i’ve had this fleeting thought before, which writing this has “crystallized”: i think it would be good if a ControlSpec could define the :delta step (iow, the input quantization) as well as the output quantization. otherwise, its often not a very usable abstraction for sensitive parameters, and the solution so far has been to manually fiddle with the input scaling (iow, encoder sensitivity). it would be cleaner to make this an optional property of the parameter (or its spec, i dunno.)


i don’t have much of an opinion about the other points.

2 Likes

I was just thinking it would be useful to have a simple visual envelope generator available in the parameter menu (like text entry, or file select).

Maybe something like enc 1 being a “rise” and enc 2 being a “fall” with key 1 acting as a shift key to transitions from log -> linear -> exponential for rise/fall. A simple visualization could fit on the screen.

I’d like to do something like this for crow utility, but I think it could work well in different formats too.

Are there any granular effects floating around for Norns? Looking for something like Clouds or Arbhar or Nebulae, but in Norns form!

1 Like

You can use clouds on norns, thanks to @okyeron! Check out Mi-engines. Its also been added to Pedalboard: Chainable FX for norns (v1.5.1).

I think all the other granular scripts I’m aware of don’t work with live input, but there is also easygrain, glut, angl, mangl and langl :slight_smile:

4 Likes

Yes, I’ve looked at all of the non live granular scripts. They look great, just not what I need ATM! Amazing re: clouds!

Sway does granular on live input https://github.com/carltesta/sway

3 Likes

adding live input to the Glut granular engine would be really pretty easy. not a bad first exercise in supercollider

9 Likes

oh wow, i’ve been wanting to be able to do this since i got my fates. thank you

would i just add this to the original Glut script somewhere? or is it more involved than that

1 Like

That’s the Glut code already, unmodified. You’d want to edit it to fill the buffers it creates with live sound, likely via a synthdef using RecordBuf, rather than that code as-is which fills the buffers with sound from the filesystem.

I don’t know much at all about supercollider (yet) but I’m hoping to take a look at this this weekend!

you would add something (loosely) like this to the engine class

/// add a variable to hold a single recording synth
var recSynth;

...

//// add a class method to record
// live record
recordToBuf { arg bufIndex=0, inChannel=0;
	if(buffers[bufIndex].notNil, {
		recSynth = { 
			RecordBuf.ar(
				SoundIn.ar(inChannel),   // capture requested chnanel...
				buffers[bufIndex].bufnum, // to requested buffer
				doneAction:2 // free the synth automatically at buffer end (if not already freed)
			);
		}.play(Crone.server);
	});
}

//// a method to stop recording
// stop recording
stopRecord { 
	if (recSynth.notNil, { recSynth.free; });
}



/// and command glue for lua

this.addCommand("startRecord", "ii", { arg msg;
	recordToBuf(msg[0], msg[1]);
}

this.addCommand("stopRecord", "", { arg msg;
	stopRecord);
}

as written, the recording function is basic and crude:

  • no control over start position
  • can record into multiple buffers at once, each recording will proceed to the end of the buffer,
  • but, can only stop the most recently started recording without more bookkeeping (not a big deal but see elsewhere, like a polysynth, for how to manage multiple running synth instances with an associative collection.)

easy to add overdub / fadein / fadeout options as well. (use recLevel and preLevel fields of RecordBuf, optionally with envelopes)

2 Likes

this exists in the norns library thanks to @markeats

2 Likes

Do you know of any good resources for Supercollider studies? Preferably for people with more programming knowledge than DSP knowledge.

I enjoyed https://ccrma.stanford.edu/~ruviaro/texts/A_Gentle_Introduction_To_SuperCollider.pdf

6 Likes

Thanks @21echoes I will check this out!

Had another idea for a more utility focused Norns script—a multisampler. Theoretically it shouldn’t be terribly difficult—output a series of MIDI notes from the Norns, and record each note in series on to the SD card and name correctly. Think this would be doable?

If I wanted to build a simple paginated script for Norns to change the active script on a Crow where might be a good start for a copy and paste bad coder such as myself? i am thinking menu to change between mult, clock divider etc

2 Likes

maybe check out this example for building the UI (the ScrollingList in particular might be useful) - https://github.com/monome/we/blob/master/demos/ui.lua

You could copy some scripts from Bowery: a crow collection to your script directory on norns and try running something like crow.send("r filename.lua") when you select a new list item.

3 Likes

I don’t think this works, the r <filename> and u <filename> shortcuts are just handled by druid. Seems maybe nice to have a crow.run helper function that would allow executing a crow script as part of setup for a norns script though? I think that since the C function for sending data to crow adds a \n\0 terminator that you currently could not implement this in Lua the way druid does it.

(I also notice that since this function uses strcpy / strcat rather than strncpy / strncat that this function can corrupt memory. Indeed sending a very long line such as crow.send(some_512_byte_string) will crash matron. PR incoming!)

3 Likes