Circular-buffer-based 'real time' NMF~

used as panner!


----------begin_max5_patcher----------
2227.3oc0bs0bqhiD94jeEpbUyK653RRHtMOrUl4g8sc+CL0VoDfrMSv.CHx
IdmZ7u8UW.GrMFqDKb7dpbbv.Rc+0WT2pkT9yGeXVTw6r5YfeF7afGd3Oe7g
GT2RdiGZ+9Cy1PeONiVqdsYwEa1vx4ylqeFm8NWc+erlxAo0f0zxRVdZ9peF
PAwoUwMYzJPTyxkrJ4ySJDOS7nkzWYfJFMCvS2v.OAXuwp1JZd1RPMKtHOYN
HkKtLOoV95UTwawK.QLPYUQLiUyRDcK3e+u9m6lK5n+ngUykcsCnhl+Z8Bvu
xhoM0LYuHnq3lIEax1J5QVhnohuBxKDDnnhyDzhulAv5lBnUL0yVw3ptrNcS
pDEUr5lLdMfQiWqX64f0r7XlpwZB.Jo4cxlrzbAPZxUBHm1aVy2lwTRrtWKu
YSQCOiwUBXX6cKo730Bh+REKlqUPdtAKfyAAPe4ubIP4uHhu.9OsMJMQ0yEQ
+9Sdnd8eZdW2ij26ud7Q4GyuRUdMmVwEBk3mJynainwuN65AIB5nPomq7Sjq
BjX3vfzMb5AIKSvaBKv5hlJgpVZ2HgqEfpOJTgQrIH02ZHUBsnFNuXugpfu3
G.gKAJmQLRC7TVmcf4HHkwVQi2JYg3hrhJEFNEsDuN5trHmmKb8UO5WpREiW
7qEYIcOtR3dI7lkO0SRrN1RNZAmU8BKmFoQR2yznfusjo4WAB0+WIC5XyRgq
tvZfxSKx6abhQJf4f8OC9N.Y+F.tvgDBwyG3BTeE8p7BAUxREtP8jHGppO1x
buCdzpdTDIYI3B+f.riq7JhOzMHnkd2clKHHDtPvm3P0meYClv6VCFk6fi64
v2MzfAeaLXVlUH3CSsMvm21.qGYzCpjZAZWNbOovxhpMT0K6MvHl68O9zZ2H
Z9pOTsW8.t4reHXnShrHSfnxdhIWekXx4TwTe+DxryAbgZSHKk11Cibr8P9O
sCPHBOeSAO57f2w0Q5X454+QRCmE7NmE70BGJZ1zi75xJwvFK0ovVWCRyKa3
feJQ7iEDFdNpLB0AmPtgiILv3yJLldwPpXL322IymdaNeMZgiE.eHJXgeHAK
rF7ZSrB5MlDv462b3X4.1Bxg.n6BykAj6NY.xFNBgjOgLv8NSFfsh+fqu+mz
e.c2IGrg+.w6yXK.+1kA+8cBtC5ZyfisynFMZ7.xcm1GYOQfYZej+2tLfCp4
Ekf3LF0F4Fhft5pK.CThgQSI.4cd3KXJYtgZ9ZxSMVU0rc.n0RSLvSKFHpDD
EQGFSL3dOLFfsQtO9xiAf99GCnr3U1NcZwVnBaANZCdjJwXemQAuyfUXy4dE
a9teBrgmZrkPi2YAPQHp5jHyg8hykc3Jh9UrEOr7VWgyFR3eIC3hzLNo6yAm
MZvYc1tM0e3usSV1GnuMxwRuVDdg5UlX7TrBtCBxlBhrQkWZWBlVqU3n4Wc9
YaJKj3sqpSfH.1FX2c+zKvXM9GMpJAMt49wETcJwOxB32QGPE63X.1g2GXuq
5SsYXG0r+RqT9oN2AhNiCuwCIE7Yq+zWQPDoXyOJy5aore7VZcZTZVJeae7T
rbYMqEHOozlO4zeYHJhekkjTQWUGWUjk0ONlpL770UEMqV2+95pMu9zFneva
m9fnUaJRNn9zQEUIrp92YX0AsZU6x3O6YQezHzgyAev9CtPc5wqzKLgd9QAg
mYLar4iY2s1KIrME0xUaYgPiTR4CFsFZwrqnwuJPrXvH6TX4V+ac5yAiZKiC
9FqkpB2pJFXMriESZrar81oO.GuXx9eiBfZVlUFQuaoHamqrynYwfub3LKhb
dwpURO5qOA0VL5opQ73InhB+RKf1MIRFKYEamMhhGnDAn.WcjqQiXcYU9sIE
NqAd7m.7v6Dv+OjkG00NkGsU46htboQB+1mzh.3VJxFtOrIAiA6u+4po24fs
kMAfglKBFcndb6n65cYFbzBM3c40L+1X6WVjssSdzUkbKHM70vmfTkJGgBGX
iVjyqS+up9WsaCNMCwYe0MTQG+Seik7hnqDr0KTNuJMpgq2ZpOrWJIRcdSjd
26nxbTKWmNoqMRqn25vcURXL7++EwKyZRSVHDx4aVtC7rb21Bb.O+izbI1At
HL340Ekpufc8.OuboRpHcXI1q9bDgJQkgG4KnGPWaY6TugZyAezFuVwvx6en
fUuwSaoQWoj.n8DJQswmU67rdujbm9.N2F3xXJgOXVjCSIjMHjuADpiatNJE
bqnDAYBk7sAkflPo.agoKY5orOsBltITpqSF2H2FROTvMxcJzD5XCBYDff1v
bfX.kbsAjHlXN3bnu8GEo6FPZ3vjFM8jF4OLowWEocLwHxeJ.swTFYaMsbOm
YJluNBYheiiMFbywwbg40QHiRJwYJbPMiz3IwVEcqDuvakEC1DaShUBwaRZK
xs+jcnzEsPbsQxDlDjGaiHhH+azfUJMvkTSd1hP2FsjICzGN7.FtSOkCFlx9
SOkOJB3dRStAjlLEowXFomjvRFQZ7YPs2zSZDYJhHZFowCm9ly0QZhoofbsQ
iQlDOgXiYXgLItOwJwSLgPAShIiITlb4D90kviVV9Fqpts4JhNaC820GrR+4
pullq+p5HvNqhI27I522UcGZU75TNKl2Toqo46d5BcNStSPpxaRaQs.tO1V6
yiJa39cbwF56dxxxp3bA5VRax3GJQ1eZSeIMWx6rtScp5Lf18Q+SZJMNlke3
ITMP9ZANgXjm5jiBCCfjCa0omvzO9.tvsy.Zdq1qRPhiKq6rMBtOsSx2Wae.
fU0XcLHe.qSvNt3P0gp0G6RTWg8ItnCNtqVfs1vpqoqX1UWDsZYZV1d.0un8
ckgd1pJZR5G+gLnE+n85NOw+7mO3U8HUayvcM6iSG7oWcZy5ZENDhBU1HNs1
HxqD2BcTqn4qzBYr+9Cks7LUWTVT04dJZZ392ugWrGnmrRECq9Nz6vLsntD+
FacozYD2tysMQfYAO+UsrDs4ud7+A5lP9hA
-----------end_max5_patcher-----------
1 Like

and a supercollider version for @spluta

// set the buffers and synths
(
b = Buffer.alloc(s,s.sampleRate * 2);
c = Buffer.new(s,0,3);
d = Buffer.new(s,0,3);
e = Buffer.read(s,"/Users/pa/Documents/documents@hudd/research/projects/fluid corpus navigation/research/fluid_decomposition/AudioFiles/Nicol-LoopE-M.wav");
g = Bus.audio(s,1);

SynthDef(\becauseIcan,{arg bufnum = 0, nmfa = 0, nmfb = 0, input = 0, env = 0;
	var head, duration, audioin;
	duration = BufFrames.kr(bufnum) / 2;
	head = Phasor.ar(0,1,0,duration);


	// circular buffer writer
	audioin = In.ar(input,1);
	BufWr.ar(audioin,bufnum,head,0);
	BufWr.ar(audioin,bufnum,head+duration,0);

	// cue the calculations via the language
	SendReply.ar(head > 500, '/processplease',2);
	SendReply.ar(head > ((duration / 2) +500), '/processplease',1);

	// read the 2 buffers
	Out.ar(0, Splay.ar(BufRd.ar(3,nmfa,head,0,1)) + Splay.ar(BufRd.ar(3,nmfb,(head - 22050),0,1)));
}).add;

SynthDef(\playa, { arg output = 0, bufnum = 0;
	Out.ar(output,PlayBuf.ar(1,bufnum,loop:1));
}).add;
)

// start these synths in the right order
x = Synth(\playa,[\output, g.index, \bufnum, e.bufnum]);
y = Synth(\becauseIcan,[\bufnum, b.bufnum, \nmfa, c.bufnum, \nmfb, d.bufnum, \input, g.index], x, 'addAfter');

// start the responder
(
w = OSCFunc({ arg msg;
			if(msg[3]== 1, {
			FluidBufNMF.process(s,b.bufnum,0,22500,dstBufNum:c.bufnum,rank:3,fftSize:1024, winSize:512, hopSize:256);
	}, {
			FluidBufNMF.process(s,b.bufnum,22050,22500,dstBufNum:d.bufnum,rank:3,fftSize:1024, winSize:512, hopSize:256);
	});}, '/processplease', s.addr);
)

// kill all once tired
b.free;c.free;d.free;e.free;f.free;g.free;w.clear;x.free; y.free;

It looks like this patch isn’t happy with polybuffer~. Did something change around buffer~ vs polybuffer~ from alpha01 to alpha02?

we stop supporting them, as written in the log :wink:

You should port this patch to Max6+ 64bit :wink:

2 Likes

Alas, trying to support buffer and polybuffer and make it essentially transparent in Max was an overreach on my part: it was just too gnarly to have that and have stable behaviour.

The tricky thing is that, when all you have is a symbol and the patch hasn’t finished building, it’s pretty hard to work out whether you have a buffer or a polybuffer to deal with.

If people feel that they really miss this, I see two possibilities we could explore in the future. First, bring them back, but without trying to make in transparent in Max (that way the code knows what it’s meant to be doing). Or, when I implement array attributes (mostly to try and tame BufCompose!), then some mapping from polybuffer to array of buffer might be possible.

I don’t know that it’s generally useful for this kind of thing. I guess here it’s just a case where you’re shooting an arbitrary amount of files at a single reference, which is outside the typical use cases of fluid stuff.

for arbitrary amount of files, you can iterate through a polybuffer using the dot notation and that is accepted as ‘normal’ buffer by all our buf* objects :wink: