Convenient way for plotting pattern's audio

Hello Synths,

Is there a simple way for plotting the audio resulted by patterns ? (Also, any plans from the dev comunity to write a .plot method for patterns ?)

What I am currently doing is recording the audio into a buffer then plotting it. But this has the inconvenient of loading a buffer into a float array in order to plot two buffers simultaneously.

Here is my SynthDef, which I is basically a version of Alberto de Campo for Wavesets Quark.

w = Wavesets.from(Platform.resourceDir +/+ "sounds/a11wlk01.wav");
~bufferOriginal = Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav");
~bufferTransformed = Buffer.alloc(s, 44100 * 4.0, 1); // a four second 1 channel Buffer

(
	// A wavesets loads the file into a buffer by default.
		b = w.buffer;
	// Wavesets.prepareSynthDefs loads this synthdef:
		SynthDef(\wvst0, { arg out = 0, buf = 0, start = 0, length = 441, playRate = 1, sustain = 1, amp=0.2, pan;
	        var recbuf;
			var phasor = Phasor.ar(0, BufRateScale.ir(buf) * playRate, 0, length) + start;
			var env = EnvGen.ar(Env([amp, amp, 0], [sustain, 0]), doneAction: Done.freeSelf);
			var snd = BufRd.ar(1, buf, phasor) * env;

	BufWr.ar(snd, ~bufferTransformed.bufnum, Phasor.ar(0, BufRateScale.kr(0) * playRate)); //recording

			OffsetOut.ar(out, Pan2.ar(snd, pan)); 
		}, \ir.dup(8)).add;
)

Moreover this is not working properly, the recording signal is sounding degraded even when I playback the original file through a pattern:

(
Pbindef(\ws1).clear;
Pbindef(\ws1,
	\instrument, \wvst0,
	\startWs, Pn(Pseries(0, 1, 3000), 1),
	\numWs, 1, 
	\playRate, 1,
	\bufnum, b.bufnum,
	\repeats, 1, 
	\amp, 0.4,
	[\start, \length, \sustain], Pfunc({ |ev|
		var start, length, wsDur;

		#start, length, wsDur = w.frameFor(ev[\startWs], ev[\numWs]);
		[start, length, wsDur * ev[\repeats] / ev[\playRate].abs]
	}),
	\dur, Pkey(\sustain)
).play;
)

Is it also possible to rewrite this code using RecordBuf instead of BufWr ? While I was trying this, only a really small portion of the buffer was recorded, probably due to env’s doneaction, but I couldnt manage the problem…

After this I plotting using the following:

~bufferTransformed.loadToFloatArray(action: {arg array; a = array});
~bufferTransformed.loadToFloatArray(action: {arg array; c = array});
[a,c].plot

Any ideas on improvements or simplifications ?

A quick way would be defining a Function that reads from a bus:

(
p = { In.ar(b = Bus.audio(s, 2), 2) }.plot(1);

Pbind(
	\out, b,
	\legato, 0.1,
	\dur, 0.5,
	\note, Pseq([-12, -24])
).play
)

Note that plot writes data to disk and loads it into an array, so you can already analyse it:

p.data[0].plot

p.data[0][10000..10050]

3 Likes

@dkmayer, thanks!

But when I am running the following code, I am getting the tons of

Buffer UGen: no buffer data

messages on the post window with a blank graphic window. Moreover, the buffer seems to get corrupted after the process, because when I try to plot it I get

File ‘C:\Users\somesupercollideruser\AppData\Local\SuperCollider-1825032951’ could not be opened: Format not recognised.
ERROR: Message ‘-’ not understood.

Am I doing something wrong or can this be a bug in the Waveset Quark or SC ? I have tried changing Pbindef with Pbind, changing the [key, value] pairs order, evaluating In and Bus in other contexts, but nothing seems to work.

w = Wavesets.from(Platform.resourceDir +/+ "sounds/a11wlk01.wav");

(
	// A wavesets loads the file into a buffer by default.
		b = w.buffer;
	// Wavesets.prepareSynthDefs loads this synthdef:
		SynthDef(\wvst0, { arg out = 0, buf = 0, start = 0, length = 441, playRate = 1, sustain = 1, amp=0.2, pan;
			var phasor = Phasor.ar(0, BufRateScale.ir(buf) * playRate, 0, length) + start;
			var env = EnvGen.ar(Env([amp, amp, 0], [sustain, 0]), doneAction: 2);
			var snd = BufRd.ar(1, buf, phasor) * env;

			OffsetOut.ar(out, Pan2.ar(snd, pan));
		}, \ir.dup(8)).add;
)

(
p = { In.ar(c = Bus.audio(s, 1), 1) }.plot(0.5);

Pbindef(\ws1).clear;
Pbindef(\ws1,
	\out, c, 
	\instrument, \wvst0,
	\startWs, Pn(Pseries(0, 1, 3000), 1),
	\numWs, 1,
	\playRate, 1,
	\bufnum, b.bufnum,
	\repeats, 1,
	\amp, 0.4,
	[\start, \length, \sustain], Pfunc({ |ev|
		var start, length, wsDur;

		#start, length, wsDur = w.frameFor(ev[\startWs], ev[\numWs]);
		[start, length, wsDur * ev[\repeats] / ev[\playRate].abs]
	}),
	\dur, Pkey(\sustain)
).play;
)

Try this
w = Wavesets.from(Platform.resourceDir +/+ "sounds/a11wlk01.wav", "test", true, s);

1 Like

Thanks! Now it works!

It is possibly a problem regarding how the Waveset Quark loads buffers, right?

There is still a small problem. When I am plotting like this, there is always a small initial portion of silence in the plot, possibly due to server latency. What would be an precise solution for not having this?

When I set s.latency = 0.0 the whole audio file gets damaged with many blank spaces along the waveform.

The only way would be by manually chopping through things like p.data[0][10000..10050] ???

Drop the zeros:

x = [0, 0, 1, 2, 3]  // your array
x = x.drop(x.detectIndex(_!=0))
2 Likes

Thanks you all !!!