Advanced Looper (question(s))

Rodrigo's icon

So I've been rebuilding the core parts of my main performance max patch slowly and I've finally come to the gnarliest part of my code, that needs the most amount of reworking. The main looper/sampler.

I've been using a groove/poke combo for a few years now as the main looper and it kind of does what I want, but it's not perfect and adding some new features puts me into new territory for me, so I decided to ask the forum for help here.

First, what the basic spec is:
-a varispeed dynamically sized looper than can overdub
-can change speed/direction while recording
-can jump arbitrarily while recording

So my looper does that now, though it doesn't declick all of those things.

Things I want to add, and have no idea how to approach:
-undo layers
-oversampled (so halfspeed still sounds crisp)
-play "past zero" (as in play forward from 0.9 to 0.1 in a loop)
-not click anywhere (at start/end, while jumping/recording)

-The undo layers I have literally now idea how to go about that. I'm presuming you record to separate buffers and have them playback simultaneously but that seems quite messy and hard to sync.

-Oversampling I kind of understand, just stick it in a poly~, but where I'm fuzzy about is the math. In my looper below I'm driving poke via groove's sync outlet by multiplying it by the total samples in the buffer. When oversampling, do you put the buffer inside the poly~ and adjust the math so it's twice as much? (ie a 1sec buffer would have 88200 samples in it?).

-The "play past zero" thing has kicked my butt for a bit as groove does not work that way at all, which leads me to believe that I need a different playback/interpolator. But which?

-The 'declicking' is a multilayered problem, so no clear answer here.

Any help/suggestions in terms of objects/approaches would be welcome.

Max Patch
Copy patch and select New From Clipboard in Max.

Here's a basic version of the looper I use. This is quite old and the code has changed a bit since then, but it's so entangled with other bits of code it's easier to just put this isolated code here.

Rodrigo's icon

Thanks for that!

I was thinking, after making the post, about using something like polybuffer and a poly-based playback object. A bit memory expensive, but not so big a deal nowadays. So recording 4 layers and playing back 4 layers would be 4 individual playback objects going at once (via poly). I didn't think to mix/bounce as I went.

That makes more sense than having a single long buffer to play non-linear bits from.

And thinking of declicking for recording and playback stages independently is a good idea. There will have to be declicking at both as jumping arbitrarily will happen at both (without quantization). There will be some mlr-style 8 slice jumping, but most of it won't be that.

For most of this stuff I will likely have to be in gen as I'll need tight sample control to declick all the jumping around. I'm getting better at straight code now too (learning a lot of js/ruby lately) so that isn't as scary as it once appeared.

vichug's icon

ye ! with bpolybuffer you can add remove buffer easily, and keep one buffer to write the sum of the other buffers in polybuffer ! maybe the first polybuffer's buffer - it's possible that no poly~ based playback is needed ; even so you cna add poly voices on the fly, this might be not a so good idea though because the totality of poly voices need be reconstructed when one does that iirc. i'm also trying to create a similar mechanism so this topic is welcome :)
for oversampling : math is right afaik, one second at 88200 would allow twice the quality in case of a slowing down. an "up 2" argument will do hte trick. Then i don't know however, if you play htat back form your main patcher, you buffer will have 88200 samples so you will have to play it at twice the speed to have normal speed... i think... this needs testing...

Rodrigo's icon

So in that scenario, every time an undo layer is peeled away it would require instantly re-summing all other layers to the 'playback' buffer?

I tried doing some testing with the upsampling thing a while back but didn't manage to figure out. My poly knowledge was shittier then, so I wasn't able to determine wether I was fucking up or it wasn't working like I thought (ie buffer outside of the poly).

Igneous Rock's icon

Hey Rodrigo, how's the progress going with this? I'm determined to make my own looper/live-sampler for performances with acoustic instruments, and I'm learning more about Max (I'm novice) to this end. I came across your trusty old looper last year, on the thread you posted when you originally made it, and it was an inspiration. I'm looking forward to seeing what you come up with now in 2014.

Here are some ideas i've been thinking about for the last few months: a workstation that will allow me to control the pich/speed/size/amplitude/etc parameters of ~3 separate loopers, with each looper capable of overdubbing. This is so the loopers can each be seperate sizes, relating to one another in ratios (or not). This way the rhythms and pitches in the seperate loop banks interact in interesting ways (e.g. evolving counterpoint) over time. Also, I think it'd be great if a looper was able to start playback while it was still recording, e.g. in Bach's canons when halfway through the exposition of a melody, another permutation of it is looped under the original, but at a different pitch. Last, I'd like to make minute real-time adjustments to the pitch of my loopers, for example raise the pitch of the sample in a looper up by a semitone for a second so that it temporarily changes how it harmonizes with another loop, and then have the option of saving my parameter changes to the loops or making them temporary.

Any thoughts on this?

Rodrigo's icon

I've started some work on it, but it will be slow going for the time being. Going to have to do a lot in gen, for all the driving stuff, and have to figure out the logic for it all before anything else.

Igneous Rock's icon

Good luck!

Igneous Rock's icon

Any progress in this? I've been studying gen~ and have found a bunch of gen~ looper examples on the forums, and would be interested in how you are organizing yours to achieve this high-quality timestretching and de-clicking.

Rodrigo's icon

Not really. At the moment I'm commissioning something to build something like what I want as an external (or gen patch), as quite a bit of it is beyond my knowledge (and definitely my free time!).

I will share what I have when it's done too either way.

Igneous Rock's icon

Wow that's really generous of you--thank you.