The problem with fades (and buffers)

After some very promising early tests applying fluid.bufhpss~ to a real-time granulator patch I’ve decided to completely rebuild it, incorporating HPSS into the core process and exposing it as a timbre control, so you can hear more of the harmonic or percussive material being granulated. Awesome!

NOW

The problem comes in trying to make this as lightweight as possible.

In my old version, I had a record~ @loop 1 @append 1 in there doing most of the heavy lifting where I would just keep adding tiny bits of audio to this circular buffer, manually fading in/out the edges to avoid clicks.

My first test version just took this rolling buffer and would feed it to fluid.bufhpss~ each bang, which works perfect but this creates tons of duplicate work since in order to analyze a new >100ms chunk of audio, I’m (re)analyzing the whole buffer.

So I want to switch to a rolling JIT buffer approach (ala the onset descriptors patch, and most of my “realtime” descriptor analysis) where I’m constantly recording into a buffer, but when I detect an onset I will analyze the relevant bit of audio, and move it over into another buffer, which will serve as the source for the granularization.

That’s totally possible, and easy by @startframe+@numframes and fluid.bufcompose~-ing the results into the playback buffer.

The problem I’m running into is windowing/fades.

In my original version, I manually applied fades when recording to remove clicks from the “middle” of properly windowed grains later on. But in this approach I can’t really do that because it’s all buffer-based.

This is somewhere where @fadein and @fadeout messages to fluid.bufcompose~ would save the day since I can just apply those fades as I’m moving bits of audio around, but alas those do not exist.

Another option would have been to create a window buffer and peek~ and *~ each chunk of audio through it, but my chunks will be of pseudo-arbitrary size. (not to mention I think manually peek~-ing every sample of each grain, each time I record a new grain, would probably offset any cpu improvements I’d gain by not fluid.bufhpss~-ing the “whole” buffer).

So this is mainly a question about this paradigm within the fluid.verse, where you want to process and move around small grains, which may potentially need windowing during the process. It’s not always possible to window the problematic bits at playback.

Any thoughts/suggestions?

(edit: while searching on the forum I came across @tutschku’s early request for fades, and @tremblap’s response of “use the HIRT” tools, which I suppose is a possibility. This just seems like it could fall within the set of use cases native to the FluCoMa project)

Here’s a quick test patch showing a stripped back version of what I mean:


----------begin_max5_patcher----------
3832.3oc0c08iqhaE+4Y9qvJO1N2H+EXnOss8gc2pV0JcqTU0tUiHDmLrWBD
AjYtytZm+1q+.HPBj3.Xl6LR2Y3Zv3y424Cer4X6e696VrJ8q77Ef+D3m.2c
2uc+c2oJRVvck++6VrK3qgwA4pGawNdddvV9hGz2qf+0BU44EAYEaxB1wATJ
5APxgcp+WNfB8ce.rlmWz3YfO.VEjr8APixPPLsYEwPp2YUT+1j0shDhiR3g
oGRTzAtrPwaIJIlWj2rv8AEgOEkr8wLdXglocwKEjhKzQ9GBko9i3+.9eGeQ
oGJpdSnxR0EU75dt90rXQcEhVqvizU+xmbXKjk862eu7WOXHBGltaGWvMmhv
oqdNJ8Pd7qfeDDFj.dIJYc5KffBPwSbPQj.bR2.1GG75pfvuHvnCEhm7kn3X
vJt3+sQ7h2mly+j.A.woE4xGOOZWTbPFHmuU1n4fnjhTP.PT1VdlrVa3YO.B
RVW+l0ux8oEhmOJHVPO46EjytCwEQ6i4fedwSQE4+7hNkOjtjOnKHebPJADi
pjLXe4ejhodDPvNjBNSoTftDDGkK3cf.mJdRfmfv3nvujW8jaREvXzupTLHv
kvKwvxmMQnUqdy+.O9YdQTXvhqBGTGENPHZ8U2qBGxFZSPHuYi2DhHSIDQVB
9g+0m+r.cD5l4BkgYAZn9ZMEO4uwT+IBYvSIxDrMHJQXMIM6NDGTDklrTXwA
x3AwQEuJPrnbvKoGhWKMYCj99Byh1Wjl8o07Bdl.m3qAgOcH4KRiWkMenvLO
U9uMJ+.+se7eWZ0Zt+Qz07O5TpuQIZ0tax7CMkHHdIHTfVEbPdpf4yiS2uWf
aYQ6lICPMdfgJyPHcZzxn9SIF0qB09CwwB8mMYo6DdzAAwuD7Zt3YCSyVK6T
Xh0cPTEX44szQXQhX2ttC0aH3xKAOy2jls6sEcQvNWS3xPpfAvNtJ+IzdIX2
9BFXSbZfPrbwKjchH+6w.GzHes1nTmdGe8hNPkA4sNg+hnxmorrI9Pz5kGiN
3Mv2kmdHKTZfo9y2IC.KJQ4rBbBQcadQbKcJq0Dv3dAVRe.qNruFnXmgcQwS
H9nkJuMRN2yUZC3StBiiupFkBA5joGjaVQLhEoICioJ4FZ0uu0Pl6mUfGc.K
i4Wzw2i7jfUwpZBmNYaAXE.MLlGQzBVjx21.jnUpxQReqc.BDuITIdOHefBY
jqaka6Kxm8Jkyi1lDD2MKRa0QqnWGMiUxYhdMih4OyyxEddZzF2sHX+9FEeW
ipHgieIU8h7dntnnDcQn5hx3OGUUeXcoAYBPnPf.Gxz9f+paEIJeMoqEtmOD
odS5BEBlRRRIBj9tEiER2MuRRUc6ivJQYuvTdBQdN5vIPvi.qPDuMNM7K70M
ItEo64IQI6y34ht7UNiac607MAhAf8XyfeP3kcd+p.Q57l08+7myDCtqlA1l
EsNMQRDsjDxhqZNQG9pNNQNMYF0SjDruiJKzADvRO2TLj+hC4qBxjBpRSeb0
MKRSiaeq55Ey2TTd68QIImfhEo66+lYQae5B0cUp3l6tz6Vcm7GOjnu6iBch
hGyEQiz94DiYtzNs8q+qAIQ6Dg1JCqWwtv5apc+8jXz.owws3W8cdti6rVni
GxeIZcwSpFpoxfdXEkJQKpkxqi1J5rucYEAayaWRdwqZPuQQGVUZC+XAe2dw
PaN4AZMOSMMXa5QqU4WxyVauaguFFKhaAI9o486ZJf5cviXGoibhdziL3od6
52imQd8NqGN2EUkqbvW5KwBPibpIdqWTAcYTA4o8RobRQQVFTH3YBT9CBckk
zgppvzcHVNQLXaCJvYBTxedya.ODT5mvoWrgbErAoiFDq5HviX.3PM.bd3hW
0Gzg8mK8IAlMbOOT1RGeeelKT+C1UXxcbhnGm1kdbC8gPykWn+HfBgKmVDh4
LM1eWFgPnYBhxBRVmtS1k+zBS5IphMZEolCS4LPBOiFZP3fM0HD0n0Pktt8s
rpCY1rtfKYiESz8wS7rLl37gwbpBXvrYv.hMSvxd4muCtzGIB.B7IgZC.JBa
FputWjx0HjBC0io0czAO2eO5yUvPgGxdl+1PiBpBPzceSYFfGXyhBp0TlcF5
f9HDuCRzyjteJ4uj+vjyl1rDuCiMatjQjgGvS2PjqVahZYHx6CiG5tgIzLDv
Cy+iQ.OddTUeXzYIfGFc9rtVNZLgMKA7vl4.dHC2bpBXPyP.OL24MfGQ7N0g
63nC2w0cnw6TAT95YGygYs3cboeHh2oDPJm0mYKdGWmYa9BG7bEVNeXtD8Do
5e5WKbhmsP24ZLmIoQ47AOuxkvR0DK6Z44P0cVmehA2yDlhWxbpCF11SsE16
CwvEDCmzY1Ff.dFGffyHFfPIn3hligDf+3LoMU.ChX+XXvy2rm6sbz9TzeXS
BxxpJjOLpJ0HyrnqPmy3cIXWjHRWHfhf.GYvtNJKCP4L80+m2y2jO8IpLwuP
T6MQe3Yy1hfQvw8ofqbC6Y0oH1edsrPvwhJjYvtBMowvzJYHu8jkPmuvkynv
YYE4sx1WbnOnVCds2rjz9ZKEfUCdP.5zq1uAbgsEbQ+1ejh5AA4oG7LiY4gD
gl2ujBvCN3TJQCL5H+coyzbKLWiMRm5ZiToQO6BTGKqyLoCCP23iy2AwSu7a
fU+9BLNrm.MZRAUqmllItn54SVy+Zir9cR..Eu1K+CuB+qi.ywX1eD9NGMBc
LWfkqlndRBTESJue2PmdsnTRukjEnMC2XYpz74n5GzHI2MSDPCoBBzlTA1Pp
v0lDAwTAhiMoBpoTw4XVZ1Z8JP.+NSZr9IMx6Lo40Oo499RZXZ+jF8clzb6m
zbdeIMxELCXuujF6BnF5clz76mzf1gzbLUWypcz39MQmtLSoBhMoBOSoBeaR
E9lpWfsHUfMMLHLxlTgwgDJIWjsnBSCFyylPA4VTKX1hJLtCRqhEN2BV3ZKp
vTWmXlMwBScchsYP5XScchsoCbrz0I1jQMYSpfXrqSaRD3uEFFqys391VDgq
oPA1lcq6R9VPf3Zp+aWa5sv0T8BEnYqt0YFO1.ahELiwBaF.Nyz9xXVkJLsu
LlMitf4cKRDpsnBSGF.ylQWXJTXSKDp62D8hXJQXywCgP2xbFzsp4wotWsmO
zyb2ebKC4v5nzOq13Nd7evSNb7SDTsEizMsuZ6ln33vz3zrFOPim3tEUethE
5m5gF2ptd+D.tD6SQHOAiujfHL4RfUbk3BGGUmCmUOTUEoNTeHV93TWLi5nt
xCSbHxqfcTU7w1Dh70sDz2CR0WIJBIZySqZPx1xMyD1wcjCs.NKceZV8N6xR
heq5cnHcaVv5nxu+R8DMcTdcb6nQmT.x8yyy1pNjeGJ4N0Yy2QWpa0B0+9g5
MDuqJHCBCEMZKABAK.VEhPcDni5JltrSvlE7X9tSqNyy0koDFdPjmm9JwaBi
Ou9q11pp9PJhoZZOeGJioqJ1W+5bbaU2la8MB6h+4ddB3yAI4fOy2EsJMdc6
OPVtfVCkhp1DKF5pYQjKCqUb7fPD8bZU9EfU08wnD4dYDuVYh3iQJkIbsFIl
4QImqL0VymxbPDEqg8IBNV+JPBJpKjxbCtZktKXycC5+ss57ps07XPGOO8Uc
xsmZ04VoN4J+gouR+193az8k73n07r+ib6nxTiuFxDUBo05WMcuaA5cWvWca
reWM.+DZQesxOqTS5h13mvlx7bzHaL0yV8q4AbN4y8arjTXWK5CB62zuozg.
0AMWjd6c76qR72.pO4djZ3Woxmv4WcE+JLOYu9Oz4UcW0OTwAbtk5sqQbZx6
bCZyJ4eiXsD3DweNzj0Ig0eI9.uYJsb6gyfXtTcmM0LgurHzLxDYoujLJt3H
s6T6SgLybwe80fwwDPrHrNcmELBAqswwHDhLeLw2mw4ijKTRAh7GcfixPhlO
F3+xiiSewbNn49K4Oo1gIc7gPuV9x6p2cQjnLsmTjGR0GfiP54LKL5gcq3Ye
uHF9QInjlGPk5liHHEGE2fZ5c2pLQlNfPIWX9npuM5uuAV3RccI9kVWrxwQI
jc9yhc1Q91tRu93deHCAUOtOg5B8KGEICMc5tkuipWvB4NF55G06NpOFTTjE
s5PgdxWZvn21t3413zUAwk6Qm0faGaxm2eLThIZ6nGUuk8G.1D7kxCHjimOH
yv90e4ZywehNtLH3YdaoWm165y.k268k987rvC44QOy6Xqoub6pbtQFH9aAj
4ofrcoIQgcfKX+2gCx.hduK68FVJmY5N.kAsEmewCfpE25w+jdu.zQiTD7P2
ky6b+MGSd24OldOX0R72fbCx+00AguMPFwE4dbstPctkyRDzjtg5GG75afyc
EZ5lqekbQuSS66MzyEhdVNScro4MKRopSqK8RCdPRI1jKkN0s7MdziUIifVT
FUt.EmkCuixyIKDFaoiuCYd2NKGeG0GcMOsOO+34VS4I0B36pD70Z.fu6nE6
HLdqPP8QiA8pdUG4wYiuENMaFMyi0qyYwPir2QZimEX7g5Lnhs0QZ56aOtdJ
c.pOZudCzNDrtV9s8GEYY3id9V3DfgZAIboW.m5Mvfa7DuA6qO3afVTF25rZ
R8.sWajZX3zL9nDLtxZuqmr7nQ9JdFdaZC4vLngn3InkZuVbLZkxcxxCZFZZ
z4MMbTMc6ERgQKBuohqMuomdtFaPS2bgMM7VxDCklKdoA2RDSThljFpsHwxM
z03HxTzRTSTEIdm0RZ+nmb1fIajSNSvN47.67yBr9OGvN8L.SMksmjabZl8J
4D2IyecITzwGAuZxd6N+2FRtuMv7daf47V2em69+F2878sqlP5Gtu+oWu8Tq
2TyqibYqaAvfyeswj6ZCMu0tgbVaT4q1nyUsAkmZFYLbZlfLr7wXf4j1vxGs
usLHNOOy51vvfbKazzRqLSwX6yqm2XllyX2Z9hMILbi7B6pHuY4B1jPVslD5
tIraNOuFgE8MmWWCLmtFn+i4vjts0gYRwl4okAZWWK2rFsl044fk4cCaRdWM
UDXy7qxXJznbpZhnvl4NkwDnQ4K0DQfsxKJyovqjKTSDw0Nmm5l5tRdNMvbb
Z7LvY4xjwfqQ4uznIvyxSo9FoyPxNmAjWRilgNO+ilNDuKtxn7M513J8.i64
Dp99e+9+OOLqzv.
-----------end_max5_patcher-----------

my suggestion would be to split and record in realtime the 2 things separate :wink:

If I record in realtime, I have the problem of analyzing the the correct chunk. I guess I can just take the @sync out of record~ and do maths to set@startframe/@deststartframe for fluid.bufhpss~.

May be easier I guess.

(also, can’t figure out what the appropriate message to irtrimnorm~ to just apply fades to the ends (trim sine off off 100 100 sure isn’t it!))

you can set trim’s units in sample (there is an attribute) and the message order is then in the helpfile… but what you want is crop not trim

crop bufname start end fadeindur fadeoutdur

It wasn’t clear from the helpfile that crop (instead of trim) is what I wanted.

crop sine -1 -1 1 10 saves the day.

So your gut feeling is that realtime record+fade will be better (CPU-wise?) than isolating snippets and chain/buffer processing them?

I don’t trust my gut feeling anymore. What I do is to code, and recode, like my mentor @groma showed me to do. That way, I usually discover a lot on the way too!

I’ll give both a spin and see. With things like this I never really know how to compare as all the fluid.buf-stuff doesn’t show up as CPU load at all, so even though I can compare processing time, not sure that’s the full picture either.

I know… and even with other processes that ‘show’ in the Max load… it is such a bad measure that I don’t trust it anymore anyways. My 2 goto load measurements now are 1) activity monitor and 2) stress tests with latency super low and/or many instances loaded (but nothing really further than real-life test, just a push to see if gig ready stable)

1 Like

maybe @weefuzzy and @a.harker can share their best practice of assessing load…

I’d defer to @a.harker on what constitutes best practices. Personally, I don’t tend to get too hung up on particular numbers, but (on the ocassions where I really care) pay more attention to the patterns of usage, or what what seems to be hogging time, if I think there’s a problem.

The CPU monitor in Max (and SC, possibly PD) are only looking at the real-time audio thread, so (unless you’re using scheduler in audio interrupt ), aren’t going to register any non-audio objects’ contribution to CPU load.

Activity Monitor on OS X can do some neat stuff besides giving you just a list of stuff. You can visualise the load across your cores (show CPU Usage / History), which can be useful for seeing if anything spikes. You can also ‘sample’ a process, which gives you output similar to what you’d get from a profiler; it tends to be a bit of an information flood, but allows you to look thread by thread at what’s taking time.

1 Like

Yeah I’ll do some testing/comparison.

So far it’s a nice/chunky series of buffer-based processes to get at what I need:


I could probably skip the final fluid.bufcompose~ “combination” step there, and instead fluid.bufcompose~ it in series/place to the destination buffer, but this reads more easily.

I need to work out the maths to then paste each individual onset serially in the final buffer (in a looping/appending way), but this works out pretty well.

I have to say I’m really enjoying @a.harker’s trick for using irstats~ to get a time centroid. Using the derivative of loudness from fluid.bufloudness~->fluid.bufstats~ gives a nice impression of what’s going on, but the time centroid is much more severe.

Is there no ‘native’ way to get to a similar figure? Seems like a very useful omission.

again, in the list #3. The idea to compute a centroid on any buffer (not spectral) needs some sort of histogram to be able to be computed too. All of these are on the mid-term radar, so using what is available out there is very useful to think/reflect on interfaces (and how they mix, which is the whole idea of why we do a toolbox to extend current possibilities, not replace them)

So keep on blending and merging and exploring and posting and this is very useful to all - users and developers alike.

For max processes my preferred measure is cputimer which is normally the only thing one really cares about (when does this get done in relation for when I asked for it). You can learn different things with Shark, but I wouldn’t prefer Activity Monitor as it is giving you a general picture, not a specific picture of a particular part of the patch.

1 Like