Writing classes: beginner question

Hello! I have a bit af a trouble wrapping my head around how to properly build classes. I want to make a simple recorder class for live performance. How should I use and control the Ugens in the class? Spontaneously creating a SynthDef inside a class seems ugly to me, is there a best practice for this?

This is what I have tried to do so far, but it does not work.

SimpleRecorder { //relies on booted server
	var <>server;
	var <running=0, <resetTrig=0;
	var sigIn, <>sigInBus;
	var <ptr;
	var <recBuf;
	var <bufLenght;


	*new { |serverIn, sigBus|
		^super.new.server_(serverIn).sigInBus_(sigBus).init;
	}

	init {
		bufLenght = server.sampleRate;
		recBuf = Buffer.alloc(server, numFrames: bufLenght);
		ptr = Phasor.ar(resetTrig, running, 1, bufLenght);
		sigIn = SinOsc.ar(440);//In.ar(sigInBus);
		BufWr.ar(sigIn, recBuf, ptr);
	}

	rec { //To-do: build using synth
		running = 1;
		resetTrig=0;
		this.changed(\running, running);  // broadcast event
	}


	pause {
		running = 0;
		this.changed(\running, running);
	}

	reset {
		running = 0;
		resetTrig=1;
		this.changed(\running, running);
	}
}

All thoughts appreciated!

hmmm

your init method doesn’t return anything or store your BufWr anywhere!

maybe your init method should store a function recFunc = { { BufWr.ar(sigIn, recBuf, ptr) }.play }

and then call the func in your rec method storing the result in synth in order to reach it later… (for your pause or reset methods etc)

synth = recFunc.value

(you have to add vars recFunc and synth for this to work)

1 Like

you could look at the source for the Recorder object for inspiration. (Recorder | SuperCollider 3.14.0 Help) It does in fact create its own temporary SynthDef.

1 Like

TBH the intended usage of this class isn’t clear to me.

If init is meant to return unit generators, it suggests usage within a SynthDef.

But a Buffer should not be allocated inside a SynthDef. You can get away with it once, but if you try to reuse a SynthDef containing your SimpleRecorder, each instance will try to use the same Buffer… which is bad.

So, could you say a little more about the interface you intend? That is, what are the object’s inputs and outputs? What’s the context where you want to use the object? I think this needs to be a bit more clear before throwing code at the wall and hoping it sticks.

My guesses would be that it’s either for live-sampling (in-memory only – in this case the Phasor output needs to be made available elsewhere, and also use more than 1 second of storage), or to write to disk (in which case you’d need DiskOut, not BufWr). Either way there’s more stuff going on than is present in the first sketch.

IMO spontaneously creating a SynthDef inside a class is a good practice :wink:

SynthDefs are resources, to be created and discarded when needed. SynthDef itself is a complex class because its job is complex, but it’s also a fairly direct language-side representation of a GraphDef in the server. As such, it’s actually a low level object! There’s no need to avoid creating SynthDefs (and in fact, with SC’s design, it’s often impossible to do things without creating SynthDefs).

hjh

1 Like

Thank for the replies, figured it out now!