Live Looping in 2026 - Object suggestions for a novice
Hi all,
I am attempting to create a live audio looper device for my personal use. Ideally this looper has provisions for:
one button operation, i.e., recording audio and instantly playing it back in a loop without intermediate actions by the user
sample-accurate timing of recording (and overdubbing) and playback
sync, for multiple loopers in parallel, and
2ch buffers
I have explored the following objects/externals with mixed results:
karma~ - a lot of people mentioned this one, but it lacks provisions for sync and frankly I could never coax an artifact-free recording/overdub from it.
rez~ - mostly works for what I need except it lacks some features such as resetting the play/rec position when stopped. This is a blocker for me given my use case.
softcut~ - clean sounding loops and playback but not sample accurate, and only supports 1ch buffers.
Eric Lyon's Potpurri (el.sarec~) w/ groove~ - showing promise, wonderful documentation, but I don't see a way of recording in a loop. So the initial record -> playback action is fine, but overdubbing is problematic given there is no sample-accurate way of looping the record head from the end of the buffer to the beginning. I'm probably missing something here.
Live looping seems to be a rather ubiquitous performance technique these days. I am a novice with MaxMSP, so I feel like I'm probably missing some obvious solution to my problem (as is often the case with Max!)
Can anyone suggest some reading material and/or example patchers and/or objects to explore? I have read mention of the xsample~ externals, so I plan on having a look at those.
Thanks!
you can do all that with plain max objects.
easiest part is getting audio record and playback to work,
most work is to get arround loop states and logic arround it.
Thanks for chiming in. I've seen your contributions to the various looping threads and they have been very helpful!
Which "plain max objects" would you suggest I look into? I have seen mention of poke~ and index~ but have yet to dive into them. Any others?
Thanks in advance!
P.S. are you the "SOURCE AUDIO" responsible for the pedals? Love your work if so.
this book will be released for free soon

Thanks for that, I had a look at Jeff K's website and I believe a version of this text is available for free there.
I did read it over and worked through the examples . That said, I did not dig into the gen~ stuff because I am limited to Max4Live where the gen~ environment is not included. His MSP Looper examples unfortunately do not take into account sample-accurate control. They were a great entry point into the concept of recording into a buffer and playing it back though.
Came across this tutorial and have worked through it:
It has illuminated one way of achieving sample accurate looping use vanilla MSP objects, namely poke~ and index~ driven by a count~. I quite like the simplicity and can already imagine how I could implement overdubbing, and perhaps even some rudimentary de-clicking. However, I do not see any way I can control the rate or direction of the count~ and thus the playback (a la varispeed.) And in googling that I am learning index~ is not really suitable for such a task anyway, given the lack of interpolation.
I'm thinking playback using another object (like play~) is necessary here, but this necessitates the use of phasor~ which really does my head in... scaling it, using it to dynamically loop only a portion of the buffer, and so on, confuses me greatly.
If anyone has any suggestions on where to direct my research it would be greatly appreciated. The hard part about MaxMSP is that it is so flexible it is difficult to know where to even start!
EDIT: the more I google the more I realize this is all very well-trodden ground. Thanks in advance for your patience with my skill level!
yes, that´s how it is: index~ based solutions are superb - as long as you do not need to change pitch.
the floating point equivalent to count~/index~ would be line~/play~.
objects like play~, groove~ or wave~ perform a value interpolation for you already internally in the object.
to learn (and to transform the count/index stuff you already have to a "float version"), start with play~.
no, I am not associated with the pedals company.
it just happened that they picked same name as my nickname here...
I was involved in development of hardware loopers from early days of looping,
and developed many max based looping devices in last decades.
If I can suggest, first list all you want from a looper.
that will route you to objects that could satisfy your needs
without gen~ objects.
something like reversed, speed changed overdubbing
in synced multitrack looping ...
as soon as you want that, you are in a trouble.
interpolation, out of sync etc etc
I was never interested in that, just plain , clean looping
with as many synced tracks of different lengths, undo, redo and so on.
synced polyrhythmic delays and such things.
in one or the other way you will hit the wall if you want both.
None of looping objects you mentioned satisfied very basic looping
needs for me, like latency compensated overdubbing,
crossfaded loop start-end and synced multiple tracks.
without that it simply does not work for serious live looping.
.......
sample count needed for index or poke can be converted from range
or miliseconds outlet of other objects using mstosamps~ for example.
......
I used xsample~ buffer based recording and playback objects quite often
becasue they offered sample based sync between play/recording heads
and made construction easier then having to use several max objects
for same task.
there are updated versions, help files are really outdated ...
p.s.
if you find solutions based on that book:
maybe you can port it to rnbo~ and compile your own external(s)
Thank you both for your insights!
@roman
I was having a look at play~ last night and can immediately see how it is more appropriate for playback where a rate change is required. However, it is hard to wrap my head around what will be necessary in order to have a playback "head" and record "head" (currently driven by count~ into poke~) that remain in sync with one another when play~ is employed. It's easy with a count~ driven patch since the count~ controls both "heads" simultaneously. But since play~ expects milliseconds and count~ outputs samples, I either need to do a unit conversion (which apparently is error-prone due to rounding) or find an alternative method of sync'ing the "heads."
It would seem my predecessors conclude that using phasor~ is the most appropriate clocking method. But that raises some questions in my novice brain:
would I need to substitute poke~ for another buffer writing object, considering poke expects a sample index, and not a 0-1 signal? I suppose there's a way (with math) to convert that 0-1 to samples if the sample rate is known...
many example patches I've looked at employ some kind of math on the phasor~ output presumably for this reason, but the values used in the math are not obvious to me. For example, many people include [+~ 0.5] and I have no idea why.
there's also the use of trunc~ whose purpose is not obvious to me.
phasor~ seems to be a free running thing, whereas a clock (or tape transport) can start, stop, pause, and be reset. I'm sure there's logic that can be built to allow for this kind of behaviour. Perhaps sample and holds?
on the bright side, perhaps a phasor~ driven approach will allow for an easier time recording in a loop.
Right now, with count~ and poke~ I'm doing some hacky edge~ detection to restart poke as the counter~ loops back to 0. It doesn't sound great.
(I know these are not exactly "new" obstacles; most other people going down this path wind up at the same place. I'm personally more inclined to solve the issues independently rather than simply borrowing others' solutions, for education's sake.)
@source audio:
Thanks for your insights. It is reassuring to know that some of the obstacles I'm facing (conceptual or otherwise) are in fact fundamental to the objects available to us in MaxMSP, and not entirely a consequence of my inexperience. I think we have similar requirements for what we want from a looper, particularly artifact-free, distortion-free operation. Unfortunately, the features you've identified as problematic are also features I would like. I'm not looking for anything crazy in terms of buffer manipulations mind you, but I do need:
the ability to press a button, start playing, press the button again and have immediate looping playback.
the ability to then overdub upon this loop, in perfect sync with what I'm hearing
the ability to change the playback rate/direction...
and then overdub more material that plays back at the rate it was performed, like a tape machine.
the ability to sync between multiple loopers
less important, but would be nice, is undo/redo
As you say, it might be a bit of a tall order using what is available to us in MaxMSP. Thanks for suggesting xsample~ - it was on my radar and I will direct my attention toward it next.
Apologies for the long post; it is helpful for me to write this stuff down so I can identify what needs to be attacked next.
Thank you!
You are absolutely right to postulate on all options,
because it could become very time consuming to develop something in wrong direction.
my advice: DO NOT USE PHASOR.
overdubbing in other then original speed
will require either karma~ or gen/rnbo work.
all the rest can be done easily.
well, if you know exactly what and how you want to
manage multilooper tracks, their dependencies etc
if you slow down one looper then others must follow,
to stay in sync.
Another thing is - how is that going to work in Live ?
you want to completely ignore Live's transport ?
Do not use phasor~, duly noted, hehe.
karma~ was the target of my initial explorations, but I could not coax artifact-free recording out of it when used within Live. Not to mention there's no provisions for sync (by design.)
I will dig into xsample~ this evening, which will undoubtedly illuminate more gaps in knowledge that need filling.
As for how it will work within Live, yes, I want to completely ignore Live's transport for this looper. That is actually the motivation behind this entire experiment-- needing a looper that does not respond to the transport.
And speaking of which, I actually quite like Live's built in Looper device and use it extensively (although it isn't perfectly artifact-free). The ultimate goal would be to build something like the Looper device in terms of functionality, but that is not bound to Live's transport.
Thanks again. I'm sure I'll be back with more questions!
I went back to Jeff Kaiser's tutorials on loopers, this time also reading the section on his gen~ based patches, despite not having access to gen~ myself. Very informative stuff. It also gave me a new appreciation for what goes into creating an artifact-free, varispeed looper; I had no idea how complex it can get! It's given me some new ideas to explore.
@source audio: I meant to ask you, if you recommend against using phasor~ as a master sync, what would you recommend in its place?
Been digging into xsample~ this evening. It seems like a nice set of tools for the task at hand. Focusing currently on xrecord~ and xgroove~ (because I want varispeed.)
It is not immediately obvious to me how I should work to sync record and play heads. The head position out of both xrecord~ and xplay~ are signals (representing sample address in my current case) yet they expect float numbers as inputs if one wishes to specify a position for the head.
Is snapshot~ a viable way of converting the signal to a float without introducing sampling error (e.g., clicks?)
Currently I am feeding the position of the record head directly to the "end point" position input on xgroove~ so that when I stop recording the end point of xgroove~'s loop should be exactly where i stopped recording, thus representing "the same" region in both xrecord~ and xgroove~.
I feel like this is a misinformed approach. Is it?
you need to check all options for units in xsample.
varispeed overdub will not work I guess,
but I never tried that as no interest.
but you can combine karma with xsample and plain max objects etc.
@source audio,
Thanks again for the continued support. I'm having a look at the options for units in xsample~ and xgroove~ and while we have a few options - samples, buffer size, ms, s - they are all formatted as float numbers, whereas the positional info that xrecord~ and xgroove~ (and xplay~) output is formatted as a signal. This necessitates some kind of format translation in order to have xrecord~ and xgroove~ infom one another of their "head" position. (At least I think it does...)
So my question is what is the most viable way to translate the signal to a float, while maintaining sample accuracy?
Currently I am employing sah~ and snapshot~ to "capture" the positional info when the recording is stopped, and thus representing the loop size.
What do you think?
you should not use signal <> data conversion for audio sync tasks.
your main and only problem is overdub/playback with varispeed and direction.
I can't make more suggestions without detailed infos about relation
between master and synced loop tracks.
@source audio
Thanks for confirming. I suspected signal <> data conversion was not a good approach.
To elaborate/clarify... my question pertained to exactly the problem of overdub/playback. Using objects like xsample~ or groove~, I cannot see how to sync the record head to the playhead for overdub tasks, i.e., punching in new material (record head) in sync with what you're hearing (playback head). Sync output from these objects is a signal (0 -> 1) whereas the inputs of these objects to specify a location of the record/playhead is a float number. Thus I am at a loss as to how to make sure the record object starts recording at the moment in the buffer that I am hearing. How would you approach the problem of having the record and play heads in sync during overdub duties?
To me, this is the beauty of the master clock driven approach to the looper, be it count~ or phasor~ or whatever -- the heads are always in sync. Most likely there is some approach here that I am as of yet unaware of.
As for relation between master and sync'd tracks, I'm not even thinking about that yet since I haven't even figured out a way to overdub with varispeed-compatible objects.
I've also gone back and read Jeff Kaiser's loopers in gen~ tutorial and it illuminated some other techniques that could be employed for this purpose. Still trying to wrap my head around what Graham W. has done in his GenExpr example in said tutorial.
I also came across this old thread: https://cycling74.com/forums/sample-and-loop
Andrew Benson makes a beautifully simple looper using gen~ which sheds light on the approach of using an accumulator [+=] and modulo [%] for creating the "master clock" from which all future playback and overdub actions are driven. This approach makes a lot of sense in my brain.
Anyway, thinking out loud here for any future newbies (like myself) who come across this thread.
for example xrecord~ is overdubing in itself, depending on signal inlet that
mixes new input to allready recorded.
sync signal outlet controls xplay~ or index~ .
to start recording clear buffer, reset loop points, hit record, fade input,
to stop recording get current position and feed it to loop end inlet,
fade input out , enable overdub , disable overdub after crossfade time.
that adjusts loop length.
to get latency right you feed sync signal (sample count) to +~ and %~
to listen latency compensated.
but again, xsample objects will not give you varispeed.
and varispeed won't let you sync loop tracks, unless they are all same length
and follow same speed.
but again, xsample objects will not give you varispeed.
I think this is the crux of the issue. All of the steps you've outlined above make perfect sense to me, and I could whip something up easily I think, that is, if I use xplay~/index~ or some other buffer read object that accepts a signal input for sync purposes. I would seem that then if I want to create something in the MSP environment, I need to choose either sample-accurate sync, or varispeed functions -- we can't have both.
I need to delve into the gen~ environment stuff because it would seem that one can have both sample accurate sync (of record and play heads) and varispeed functionality in there.
More reading/research/experimentation to come. Thanks for the help, @source audio.
I am a big fan of Karma, which is a dynamic-length, varispeed looper/sampler external for Max, created by Rodrigo Costanzo. I believe the karma package is available in the package manager.
https://rodrigoconstanzo.com/2015/05/karma/
@anthony
Thanks for the suggestion. I mentioned karma~ in my original post as being the first thing I investigated.
Unfortunately it does not behave well in the M4L environment; lots of clicks and artifacts. It also does not have any concessions for sync'ing up with other loops. I read this is by design.
And thus I started on the path to attempt to learn how to make my own looper!
My apologies, I did not read the full message. But I would like to add another suggestion...
Catch is a simple monophonic performance sampler that allows live audio to be captured for instant playback and manipulation. This instrument was designed for performance.
https://www.novelmusic.org/m4l/catch
just out of curiosity I tested karma in live 11.3.26.
128 samples buffer. only 1 track with test looper inserted.
no artifacts or clicks .
also synced few other tracks using poke~ / index~ combo.
no problem, but all tracks follow same sync outlet of karma~
Thank you both for the suggestions.
@source audio, thanks for investigating on my behalf. I will go back and try again, but in Live 12 (on Windows) I could not get artifact free performance. I think recording the initial loop was okay, but then every overdub - whether there was an input or not - resulted in strange clunks and dropouts. I'll go back and check it out again. I could try it on Mac to see if there's a difference.
In the meantime I am going to continue digging into gen~. It seems like a great environment for creating a looper (for someone who doesn't know C/C++ that is.) The tutorials have also been great at exploring some techniques that are equally applicable to Max and MSP.
In the meantime I am going to continue digging into gen~
☝️as the person who wrote the initial version of code(in C) to help Rodrigo Constanzo implement his beautiful vision and design of karma~(and having had trouble implementing my own sample-accurately-synced version of a looper, 'rez~', mostly due to life-stuff that makes me hone down more on visual environs rather than coding ones because my mind can handle those better than 'coding' when under great stress), this would be my personal advice. To that end, and furthermore, i'd highly recommend getting into the 'GO' book to learn gen~ at as advanced or intermediate a level as you'd prefer.
Thanks Raja, I appreciate your perspective. And thanks for the book suggestion; I will definitely check it out!