Playing multiple buffers and manipulate them

Hello all,

I have a number of files to sync. But I would like to keep it so as I can manipulate the parameters of each file, for spatial sound purpose. So, my approach was to create an array with the buffers of the files:

~myfiles = [Buffer.read(...1...), Buffer.read(...2...), Buffer.read(...3...)];

Then I loaded each buffer to a different PlayBuf, so that:

PlayBuf.ar(2, buffer1, \trig1, \startPos1, ...);
PlayBuf.ar(2, buffer2, \trig2, \startPos2, ...);
PlayBuf.ar(2, buffer3, \trig3, \startPos3, ...);

Is there any way to improve this code by placing all files into a unique PlayBuf? I initially thought that array expansion would work in this case:

PlayBuf.ar(2, [buffer1, buffer2, buffer3], [\trig1, \trig2, \trig3], [\startPos1, \startPos2, \startPos3], ...);

But I was not able to make the code work.

You could try using even more data structures! How about…

var bufData = [
   (buf: b1, trig, \trig1, startPos: \startPos1),
   (buf: b2, trig: \trig2, startPos: \startPos2),
   ... etc
];

var playback = bufData.collect{ |b|
   Playbuf.ar(2, b.buf, b.trig, b.startPos)
};

Sounds great. Thank you Jordan! I try it now.
Just one question: if the PlayBuf is inside a SynthDef, how would you ensure synchronicity among PlayBufs?

I don’t quite know what you mean by synchronized if you are providing unique start triggers.

You could use BudRd and a phasor? Perhaps you could talk a little about your intention a little more.

Hi Jordan, you are right. I was thinking of having a unique trigger for all the buffers, but not for startPos. Sorry for the misunderstanding.

Hi, I experimented a few years ago with a pseudo-UGen which can maybe help you to do what you are looking for.

Delbuf {
	*ar { |buf, del=0, rate=1, mul=1, add=0|
		var signal;
		signal = PlayBuf.ar(1, buf, BufRateScale.kr(buf)*rate);
		signal = DelayN.ar(signal, 30, del);
		signal = signal * mul + add;
		^signal
	}
}

Sow {
	*ar { |buf, ser, sym=\sup, del=0, mul=1, add=0|
		var signal, maxAmpIndex, arr, env;
		var file = SoundFile.openRead(buf.path);
		var ar = FloatArray.newClear(file.numFrames * file.numChannels);
		file.readData(ar);
		maxAmpIndex = ar.abs.maxIndex;
		arr = ser.harmRatio(sym, maxAmpIndex, file.sampleRate, del);
		env = EnvGen.ar(Env.linen(sustainTime: file.duration/arr.flop[0].minItem, releaseTime: 0.01), doneAction: Done.freeSelf);
		signal = Mix.new(arr.collect({ |sub| Delbuf.ar(buf, sub[1], sub[0])}));
		signal = signal.tanh * env;
		signal = signal * mul + add;
		^signal
	}
}

This is part of my research called GSA: GitHub - yannics/GSA where you can find more explanation about this pseudo-UGen specifically.