Since 2005, I’ve been putting all of my sequencing into “musical process” objects: in the ddwChucklib quark, PR defines a “process prototype” and BP (“bound process”) binds the prototype to concrete data. Basically, PR is like a class and BP is like an instance, except they can be defined and redefined at runtime.
Then, the process is responsible for all of the persistent resources that it needs.
The process will play onto a bus? The process’s ~prep function creates the bus, and its ~freeCleanup function releases the bus.
It needs a buffer? ~prep loads it, ~freeCleanup frees it.
Once this is coded into the process object correctly, then I don’t have to think about it:
PR(\myDrumProcess) => BP(\kick) loads buffers, allocates buses etc, and
BP(\kick).free drops them. The musical processes take care of the details by themselves.
IMO the root of the “stuff piles up in the background, buffers hanging around in memory, nodes and groups you don’t want” problem is that patterns/Ndefs/Tdefs often rely on resources external to themselves – so, tracking the state of a pattern/Ndef/Tdef is not sufficient to manage resources. scztt is getting at this when he recommends Pproto, Pgroup, Pbus etc.
Once I solved that problem for myself, it stopped being an issue – for the last 15 years (that = confidence in the architecture).