# Norns: dust

#88

its not the most elegant nomenclature, but the stuff you’re looking for is in CroneAudioContext:

one of these is assigned to the context variable of the CroneEngine superclass.

so you use context.out_b for output and context.in_b for input.

note this oddity: context.in_b is an array of two mono busses. context.out_b is a single stereo bus. (this just seemed to match closer to most of the use cases. in_b indices are adjacent so you can treat them as a stereo bus if desired.)

also: context.ig is a Group conteaining input synths, context.og is a Group with output synths, and context.xg is a Group between them for your use.

(ha, i even left a FIXME in there to make the names less stupid. it is probably not quite too late to change them? no, it’s probably too late.)

#89

@boboter

so… just a heads up that recording at any speed other than 1.0 is going to cause aliasing. this would be true even if write-head interpolation was correctly implemented. (it’s not right now.) this is a deeper issue than reverting the changes i made to reduce CPU usage prior to release - those affect playback interpolation quality, and reduce speed changes to control rate. these are easier to revert but we also need to make other infrastructure changes to make the CPU headroom available - like running aux fx on a separate core (what i’m currently looking at.)

i’ll comment on the GH issue to clarify the current situation.

#90

@zebra

Thanks for the info.

I’m still ot sure if I fully understand the whole thing, as I generally don’t want to record outside of 1.0 but at another tempo than 120bpm. I would just set the tempo to e.g. 90bpm and also record in 90bpm. But as far as I understand it, the loops need to be quantized to do that.

#91

ok nvmd. i am dumb and have forgotten what “tempo” means in this context. i thought it was a rate change but maybe it just refers to patten quantization or something like that.

carry on.

#92

Thanks @zebra, I’m still not getting it to work. I’ve tried to make a simpler example. See below. What is wrong with my code? Is it the engine or the lua code?

SuperCollider CroneEngine

Engine_SimplePassThru : CroneEngine {

var amp=0;
var <synth;

// this is your constructor. the 'context' arg is a CroneAudioContext.
// it provides input and output busses and groups.
// see its implementation for details.
*new { arg context, doneCallback;
^super.new(context, doneCallback);
}

// this is called when the engine is actually loaded by a script.
// you can assume it will be called in a Routine,
//  and you can use .sync and .wait methods.
alloc {
SynthDef(\passThru, {|in, out, amp=0|
var sound = SoundIn.ar(in);
Out.ar(out, sound*amp);

context.server.sync;

synth = Synth.new(\passThru, [\in, context.in_b, \out, context.out_b, \amp, 0], context.xg);

// this is how you add "commands",
// which is how the lua interpreter controls the engine.
// the format string is analogous to an OSC message format string,
// and the 'msg' argument contains data.

msg.postln;
});

synth.set(\amp, msg[1]);
});
}

free {
// here you should free resources (e.g. Synths, Buffers &c)
// and stop processes (e.g. Routines, Tasks &c)
synth.free;
}

}


LUA Code

-- PassThru Test

engine.name = 'SimplePassThru'

function init()
print("Simple Pass Thru Test")
end

function key(n,z)
if n == 2 then
if z == 1 then
screen.text("Listen")
screen.update()
engine.amp(1.0)
elseif z == 0 then
screen.clear()
screen.update()
engine.amp(0.0)
end
end
end



#93

i think this line

synth = Synth.new(\passThru, [\in, context.in_b, \out, context.out_b, \amp, 0], context.xg);



should be

synth = Synth.new(\passThru, [\in, context.in_b[0], \out, context.out_b, \amp, 0], context.xg);


in_b is an array. i know… it’s odd.

and sorry, i was probably misleading above. i said “you can treat in_b as a stereo bus” but i meant something like (not literally, but equivalent): In.ar(in_b[0].index, 2)

if you are connected through maiden, you should be able to see errors on engine instantiation in the sc REPL tab. if i’m right there will be one of those when passing the array to the synth creation.

also, grain of salt: i’m not sitting in front of norns HW so haven’t verified.

#94

Thank You. I made that change and it sort of works. When I change the engine amplitude to 1.0 I can hear it a little, but not as much as I’d expect. I’d think that when setting the amp to 1.0 it would be at full. Also, there seems to be some audio bleed from the input to the output even when the input gain is set at zero. Have you experienced this at all?

#95

Oh, \amp seems to not be a value from 0.0-1.0? Is there a .dbamp converter somewhere in there? As I enter values greater than 1.0 I can actually start to hear it. What is the max volume?

#96

no, amp is linear (in your synthdef.)

my guess is that input level is down (menu > system > audio > inputs)

this is probably the “monitor” route. in the menu you can only take it from 0db to -60db. (we’ll change this in an update.) in your script you can disable the monitor route completely by doing

local audio = require 'audio'
audio.monitor_off()


#97

Yep! You are right it was down, but even when I turn the input gain up, a value of engine.amp(1.0) still doesn’t bring it up very loud.

You’re right about the bleed and the monitor. But when I disable the monitor then I don’t get any sound at all.

#98

hm… ok i’ll look into it

between this and the weird MLR adc assignment reports, i’m suspecting something has gotten fouled up in the lua->sc glue for input levels and routing…

#99

Maybe this is helpful, when I enter audio into Matron in the REPL I get nil and audio.restart() doesn’t seem to work.

#100

you need audio = require 'audio', it’s not globally included by default

though, also, this functionality is WIP. honestly it’s painful but easiest right now to just power-cycle, re-enable wifi.

or, if you are doing a lot of development, ssh in and manually stop/start processes.

#101

@carltesta

ok, i dunno about you, but the norns unit i’m looking at has very different hardware gain settings for each channel, and one of them is very quiet.

try typing into lua (through maiden, or on the terminal:)

gain_in(50, 1)
gain_in(50, 2)


that fixes input levels for me.
(@tehn: opened GH issue)

then, a couple changes to the engine fixed things for me.

• don’t use SoundIn. i mean, you can if you want, but it goes straight for the ADC input instead of taking it from the context bus. so the correct arguments would be 0 or 1.
• i know it’s probably not necessary but i am in the long habit of passing bus indices explicitly.

now it works fine with monitor disabled.
also be aware that input can be routed through the aux bus (reverb)

here’s a gist

#102

5 posts were merged into an existing topic: Norns: Development

#104

Yes! This all works. Thanks so much for this example. This makes things a lot clearer for me. I think I can make some headway with my more complicated example I’ve been working on now.

I can’t tell if my gain_in levels are different now after running those two lines, but everything is working as expected

#107

hey carl, i commented on the git issue but the gain_in stuff is deprecated (the input gain hardware isn’t actually there on production units). so i expect that it’s the new scripts that made it work (?)

#108

@artfwo

really enjoying glut! I was wondering if it is possible to delete one of the “loop buffers” (i.e. right hand side of the top row). So that you can record something different in that buffer slot)

I ran into the issue @rbxbx mentioned as well (recordings are tapes from external in + awake sequences). They are below:

awake_elem_2.aif (1.5 MB)

awake_elem_1.aif (1.3 MB)

I’m not sure if these introduce DC offset as mentioned, but would a way to fix that be run things through high-pass filter (and mono-ify)?

as @rbxbx mentioned, reducing grain size helps, as does lowering the volume of the samples.

#109

thanks! yes, hold the rightmost button in row1 (the “alt” button) to clear the slots.

#110

i’m live sampling drones into mlr and i keep getting a click sound at whatever point in the loop i am at when i hit the button to stop recording. is there a way i can work around this for now or is that something that needs to be remedied within the code?

if i cut the section of the loop out where the click is recorded it gets rid of it but that creates some hoops to jump creatively, and doesn’t really stop it from happening the first time around if i’m playing/recording live.