Live Looping

Jun 6, 2010 at 5:32pm

Live Looping

Hello all,

I’m about to build a live audio looping patch with control from a midi foot controller. I was just wondering if there are any helpful objects members could tell me about or any information about how the patch is best to be structured. Also, if anyone knows of any examples on the web that would be extremely helpful. Just need a bit of information to get going really.

Thanks,

Rob

#50759
Jun 6, 2010 at 6:41pm

You don’t mention what your level of experience with Max is, so forgive me if i assume no experience. For audio in/out you’ll need [adc~], [dac~] and [gain~], for midi in, you’ll need either [ctlin] and [notein~] or [midiin] and [midiparse]; for looping you’ll need [groove~] or [play~] plus a [buffer~] to read from; you can record into a [buffer~] using [poke~] plus [count~] (i’ve attached an example of this). As far as specific patches, you could get 20 different version from this forum, each as viable as the other but achieving different things, so i won’t include a full patch; you will have much more fun and learn much more building a looper that’s perfect for you.

fill a buffer example patch

– Pasted Max Patch, click to expand. –

Brendan

ps the object helpfiles have little examples of how to use them, and the MSP tutorials 13-18 are particularly relevant here; remember to let us all see your results

#182150
Jun 7, 2010 at 2:09am

Thanks Brendan, that patch is a real help. I am quite a novice, not a total beginner but no where near proficient yet. I’ll be working my way through those tutorials tonight.

Is there any way to use the initial recording length (samples or ms) to determine the length of subsequent recordings. I’m still deciding whether to use a number of separate buffers (possibly 8 or 10) for the subsequent layers or whether to simply feed playback into my record element again. The latter would be simpler but has less control at the end.

Thanks again.

#182151
Jun 7, 2010 at 3:55am

Actually would it be possible for someone to look at my recording set up as I can seem to get anything to record into the buffer as of yet. I’ve cleaned up my patch and put a few notes in there to show whats going on. I can’t figure out how to set up the record~ object. Followed the help file but it hasn’t worked.

{
“patcher” : {
“fileversion” : 1,
“rect” : [ 0.0, 44.0, 628.0, 641.0 ],
“bglocked” : 0,
“defrect” : [ 0.0, 44.0, 628.0, 641.0 ],
“openrect” : [ 0.0, 0.0, 0.0, 0.0 ],
“openinpresentation” : 0,
“default_fontsize” : 12.0,
“default_fontface” : 0,
“default_fontname” : “Arial”,
“gridonopen” : 0,
“gridsize” : [ 15.0, 15.0 ],
“gridsnaponopen” : 0,
“toolbarvisible” : 1,
“boxanimatetime” : 200,
“imprint” : 0,
“enablehscroll” : 1,
“enablevscroll” : 1,
“devicewidth” : 0.0,
“boxes” : [ {
"box" : {
"maxclass" : "comment",
"text" : "compiled playback information for play~. once the sample has played through the buffer bangs and triggers the play~ again. looping",
"linecount" : 6,
"patching_rect" : [ 374.0, 370.0, 157.0, 89.0 ],
“id” : “obj-27″,
“fontname” : “Arial”,
“numinlets” : 1,
“fontsize” : 12.0,
“numoutlets” : 0
}

}
, {
“box” : {
“maxclass” : “comment”,
“text” : “timer used to capture inital recording left and output as new buffer size for subsequent loops”,
“linecount” : 4,
“patching_rect” : [ 455.0, 108.0, 160.0, 62.0 ],
“id” : “obj-25″,
“fontname” : “Arial”,
“numinlets” : 1,
“fontsize” : 12.0,
“numoutlets” : 0
}

}
, {
“box” : {
“maxclass” : “comment”,
“text” : “sets initial buffer size”,
“patching_rect” : [ 228.0, 46.0, 154.0, 20.0 ],
“id” : “obj-22″,
“fontname” : “Arial”,
“numinlets” : 1,
“fontsize” : 12.0,
“numoutlets” : 0
}

}
, {
“box” : {
“maxclass” : “comment”,
“text” : “Record Start/Stop”,
“patching_rect” : [ 99.0, 14.0, 107.0, 20.0 ],
“id” : “obj-18″,
“fontname” : “Arial”,
“numinlets” : 1,
“fontsize” : 12.0,
“numoutlets” : 0
}

}
, {
“box” : {
“maxclass” : “comment”,
“text” : “BASIC LIVE LOOPER”,
“patching_rect” : [ 283.0, 6.0, 150.0, 20.0 ],
“id” : “obj-16″,
“fontname” : “Arial”,
“numinlets” : 1,
“fontsize” : 12.0,
“numoutlets” : 0
}

}
, {
“box” : {
“maxclass” : “newobj”,
“text” : “loadbang”,
“patching_rect” : [ 169.0, 45.0, 60.0, 20.0 ],
“id” : “obj-29″,
“fontname” : “Arial”,
“numinlets” : 1,
“fontsize” : 12.0,
“numoutlets” : 1,
“outlettype” : [ "bang" ]
}

}
, {
“box” : {
“maxclass” : “message”,
“text” : “60000″,
“patching_rect” : [ 203.0, 92.0, 44.0, 18.0 ],
“id” : “obj-21″,
“fontname” : “Arial”,
“numinlets” : 2,
“fontsize” : 12.0,
“numoutlets” : 1,
“outlettype” : [ "" ]
}

}
, {
“box” : {
“maxclass” : “message”,
“text” : “0″,
“patching_rect” : [ 169.0, 92.0, 32.5, 18.0 ],
“id” : “obj-20″,
“fontname” : “Arial”,
“numinlets” : 2,
“fontsize” : 12.0,
“numoutlets” : 1,
“outlettype” : [ "" ]
}

}
, {
“box” : {
“maxclass” : “newobj”,
“text” : “loadmess 127″,
“patching_rect” : [ 74.0, 233.0, 85.0, 20.0 ],
“id” : “obj-10″,
“fontname” : “Arial”,
“numinlets” : 1,
“fontsize” : 12.0,
“numoutlets” : 1,
“outlettype” : [ "" ]
}

}
, {
“box” : {
“maxclass” : “meter~”,
“patching_rect” : [ 289.0, 542.0, 34.0, 90.0 ],
“id” : “obj-50″,
“numinlets” : 1,
“numoutlets” : 1,
“outlettype” : [ "float" ]
}

}
, {
“box” : {
“maxclass” : “message”,
“text” : “3408″,
“patching_rect” : [ 306.0, 402.0, 50.0, 18.0 ],
“id” : “obj-48″,
“fontname” : “Arial”,
“numinlets” : 2,
“fontsize” : 12.0,
“numoutlets” : 1,
“outlettype” : [ "" ]
}

}
, {
“box” : {
“maxclass” : “newobj”,
“text” : “pack”,
“patching_rect” : [ 289.0, 438.0, 36.0, 20.0 ],
“id” : “obj-47″,
“fontname” : “Arial”,
“numinlets” : 2,
“fontsize” : 12.0,
“numoutlets” : 1,
“outlettype” : [ "" ]
}

}
, {
“box” : {
“maxclass” : “message”,
“text” : “3408″,
“patching_rect” : [ 289.0, 321.0, 50.0, 18.0 ],
“id” : “obj-45″,
“fontname” : “Arial”,
“numinlets” : 2,
“fontsize” : 12.0,
“numoutlets” : 1,
“outlettype” : [ "" ]
}

}
, {
“box” : {
“maxclass” : “newobj”,
“text” : “prepend 0\,”,
“patching_rect” : [ 289.0, 469.0, 71.0, 20.0 ],
“id” : “obj-35″,
“fontname” : “Arial”,
“numinlets” : 1,
“fontsize” : 12.0,
“numoutlets” : 1,
“outlettype” : [ "" ]
}

}
, {
“box” : {
“maxclass” : “number”,
“patching_rect” : [ 378.0, 167.0, 71.0, 20.0 ],
“id” : “obj-23″,
“fontname” : “Arial”,
“numinlets” : 1,
“fontsize” : 12.0,
“numoutlets” : 2,
“outlettype” : [ "int", "bang" ]
}

}
, {
“box” : {
“maxclass” : “newobj”,
“text” : “select 0″,
“patching_rect” : [ 433.0, 82.0, 52.0, 20.0 ],
“id” : “obj-3″,
“fontname” : “Arial”,
“numinlets” : 2,
“fontsize” : 12.0,
“numoutlets” : 2,
“outlettype” : [ "bang", "" ]
}

}
, {
“box” : {
“maxclass” : “newobj”,
“text” : “select 1″,
“patching_rect” : [ 378.0, 83.0, 52.0, 20.0 ],
“id” : “obj-2″,
“fontname” : “Arial”,
“numinlets” : 2,
“fontsize” : 12.0,
“numoutlets” : 2,
“outlettype” : [ "bang", "" ]
}

}
, {
“box” : {
“maxclass” : “newobj”,
“text” : “timer”,
“patching_rect” : [ 378.0, 124.0, 37.0, 20.0 ],
“id” : “obj-1″,
“fontname” : “Arial”,
“numinlets” : 2,
“fontsize” : 12.0,
“numoutlets” : 2,
“outlettype” : [ "float", "" ]
}

}
, {
“box” : {
“maxclass” : “newobj”,
“text” : “prepend size”,
“patching_rect” : [ 378.0, 234.0, 79.0, 20.0 ],
“id” : “obj-4″,
“fontname” : “Arial”,
“numinlets” : 1,
“fontsize” : 12.0,
“numoutlets” : 1,
“outlettype” : [ "" ]
}

}
, {
“box” : {
“maxclass” : “newobj”,
“text” : “play~ rec1 1″,
“patching_rect” : [ 289.0, 504.0, 76.0, 20.0 ],
“id” : “obj-13″,
“fontname” : “Arial”,
“numinlets” : 1,
“fontsize” : 12.0,
“numoutlets” : 1,
“outlettype” : [ "signal" ]
}

}
, {
“box” : {
“maxclass” : “toggle”,
“patching_rect” : [ 134.0, 36.0, 20.0, 20.0 ],
“id” : “obj-12″,
“numinlets” : 1,
“numoutlets” : 1,
“outlettype” : [ "int" ]
}

}
, {
“box” : {
“maxclass” : “newobj”,
“text” : “record~ rec1 1″,
“patching_rect” : [ 134.0, 125.0, 88.0, 20.0 ],
“id” : “obj-11″,
“fontname” : “Arial”,
“numinlets” : 3,
“fontsize” : 12.0,
“numoutlets” : 1,
“outlettype” : [ "signal" ]
}

}
, {
“box” : {
“maxclass” : “newobj”,
“text” : “buffer~ rec1 60000 1″,
“patching_rect” : [ 378.0, 270.0, 121.0, 20.0 ],
“id” : “obj-9″,
“fontname” : “Arial”,
“numinlets” : 1,
“fontsize” : 12.0,
“numoutlets” : 2,
“outlettype” : [ "float", "bang" ]
}

}
, {
“box” : {
“maxclass” : “meter~”,
“patching_rect” : [ 36.0, 503.0, 21.0, 85.0 ],
“id” : “obj-8″,
“numinlets” : 1,
“numoutlets” : 1,
“outlettype” : [ "float" ]
}

}
, {
“box” : {
“maxclass” : “ezdac~”,
“patching_rect” : [ 101.0, 546.0, 45.0, 45.0 ],
“id” : “obj-7″,
“numinlets” : 2,
“numoutlets” : 0
}

}
, {
“box” : {
“maxclass” : “gain~”,
“patching_rect” : [ 48.0, 275.0, 108.0, 140.0 ],
“id” : “obj-6″,
“numinlets” : 2,
“numoutlets” : 2,
“outlettype” : [ "signal", "int" ]
}

}
, {
“box” : {
“maxclass” : “ezadc~”,
“patching_rect” : [ 48.0, 38.0, 45.0, 45.0 ],
“id” : “obj-5″,
“numinlets” : 1,
“numoutlets” : 2,
“outlettype” : [ "signal", "signal" ]
}

}
],
“lines” : [ {
"patchline" : {
"source" : [ "obj-23", 0 ],
“destination” : [ "obj-48", 1 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-10", 0 ],
“destination” : [ "obj-6", 0 ],
“hidden” : 0,
“midpoints” : [ 83.5, 262.0, 57.5, 262.0 ]
}

}
, {
“patchline” : {
“source” : [ "obj-5", 0 ],
“destination” : [ "obj-6", 0 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-13", 0 ],
“destination” : [ "obj-50", 0 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-35", 0 ],
“destination” : [ "obj-13", 0 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-47", 0 ],
“destination” : [ "obj-35", 0 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-23", 0 ],
“destination” : [ "obj-45", 0 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-23", 0 ],
“destination” : [ "obj-48", 0 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-23", 0 ],
“destination” : [ "obj-45", 1 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-48", 0 ],
“destination” : [ "obj-47", 1 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-45", 0 ],
“destination” : [ "obj-47", 0 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-13", 0 ],
“destination” : [ "obj-7", 0 ],
“hidden” : 0,
“midpoints” : [ 298.5, 535.0, 156.0, 535.0, 156.0, 531.0, 110.5, 531.0 ]
}

}
, {
“patchline” : {
“source” : [ "obj-13", 0 ],
“destination” : [ "obj-7", 1 ],
“hidden” : 0,
“midpoints” : [ 298.5, 528.0, 156.0, 528.0, 156.0, 543.0, 136.5, 543.0 ]
}

}
, {
“patchline” : {
“source” : [ "obj-4", 0 ],
“destination” : [ "obj-9", 0 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-23", 0 ],
“destination” : [ "obj-4", 0 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-12", 0 ],
“destination” : [ "obj-3", 0 ],
“hidden” : 0,
“midpoints” : [ 143.5, 73.0, 442.5, 73.0 ]
}

}
, {
“patchline” : {
“source” : [ "obj-12", 0 ],
“destination” : [ "obj-2", 0 ],
“hidden” : 0,
“midpoints” : [ 143.5, 73.0, 387.5, 73.0 ]
}

}
, {
“patchline” : {
“source” : [ "obj-1", 0 ],
“destination” : [ "obj-23", 0 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-3", 0 ],
“destination” : [ "obj-1", 1 ],
“hidden” : 0,
“midpoints” : [ 442.5, 120.0, 405.5, 120.0 ]
}

}
, {
“patchline” : {
“source” : [ "obj-2", 0 ],
“destination” : [ "obj-1", 0 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-12", 0 ],
“destination” : [ "obj-11", 0 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-6", 0 ],
“destination” : [ "obj-8", 0 ],
“hidden” : 0,
“midpoints” : [ 57.5, 489.0, 45.5, 489.0 ]
}

}
, {
“patchline” : {
“source” : [ "obj-6", 0 ],
“destination” : [ "obj-7", 1 ],
“hidden” : 0,
“midpoints” : [ 57.5, 489.0, 136.5, 489.0 ]
}

}
, {
“patchline” : {
“source” : [ "obj-6", 0 ],
“destination” : [ "obj-7", 0 ],
“hidden” : 0,
“midpoints” : [ 57.5, 489.0, 110.5, 489.0 ]
}

}
, {
“patchline” : {
“source” : [ "obj-5", 0 ],
“destination” : [ "obj-11", 0 ],
“hidden” : 0,
“midpoints” : [ 57.5, 111.0, 143.5, 111.0 ]
}

}
, {
“patchline” : {
“source” : [ "obj-9", 1 ],
“destination” : [ "obj-48", 0 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-9", 1 ],
“destination” : [ "obj-45", 0 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-20", 0 ],
“destination” : [ "obj-11", 1 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-21", 0 ],
“destination” : [ "obj-11", 2 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-29", 0 ],
“destination” : [ "obj-20", 0 ],
“hidden” : 0,
“midpoints” : [ ]
}

}
, {
“patchline” : {
“source” : [ "obj-29", 0 ],
“destination” : [ "obj-21", 0 ],
“hidden” : 0,
“midpoints” : [ 178.5, 82.0, 212.5, 82.0 ]
}

}
]
}

}

Also, how do you post a patch as text in the smaller size like above? The ‘Copy Compressed’ option in Edit is greyed out for me. Thanks again.

#182152
Jun 7, 2010 at 9:06am

hmm very strange about it being greyed out. it might be that you did not select [highlight] all the patch parts which need posting, maybe.
the copy compressed does not become active if nothing is selected.

#182153
Jun 7, 2010 at 9:09am

hi kite!

There are three little misunderstandings in your patch.
Here’s why it doesnt work:

1. When sending a “size” message to the buffer~ it (unfortunately) looses its contents. But there isn’t any need to resize the buffer. Just play the portion, that got recorded.

2. buffers~’s bang outlet only reports, when reading of a _soundfile_ is finished. That has nothing to do with playing the buffer.

3. play~ always needs an audio signal with the playback position. You probably forgot to insert a [line~] object. In the case of looping, I’d rather use a [phasor~], which will repeat the loop sample-accurate.

I’ve also added a [selector~] to mute the playback, while recording.

PS: For the “copy compressed” command you need to be in edit-mode and have the objects, you want to copy, selected.

here you go:

– Pasted Max Patch, click to expand. –
#182154
Jun 7, 2010 at 9:13am

oooh, actually. just had a thought balloon pop up to help. have you looked at mr. englefeldt’s ‘almost live’ patch? that can be something to build upon for a live looper.

#182155
Jun 7, 2010 at 11:14pm

Thanks so much Mudang. That’s really helped me out. Think I’m getting to grips with this now. It works and I’m understanding it and building on it so that’s great.

And yes you were right, I wasn’t actually selecting my objects, simply the text. Lesson learned.

Thanks for the tip Lewis, where can I find that patch? Is it on this site?

#182156
Jun 8, 2010 at 6:46am
#182157
Jun 8, 2010 at 11:58pm

Thanks for the link Brenden. After looking at the way this one works which is to a set BPM I’ve decided to go that way instead.

Here’s what I’ve constructed today. For some reason, when recording stops and playback (and looping) starts it’s playing back from the middle of the sample instead of the beginning. It’s probably a simple rookie mistake I’ve made. If anyone has a few seconds free to have a look I would be most grateful.

Thanks.

– Pasted Max Patch, click to expand. –
#182158
Jun 9, 2010 at 12:47am

It looks like you need to reset phasor~ to 0 every time your recording stops. To do that you just need to send a 0 to its right inlet.

#182159
Jun 9, 2010 at 3:22am

Thanks Tim, that’s solved it. Excellent.

#182160
Jun 10, 2010 at 11:30pm

I’ve finished it. Thanks to everyone.

http://rapidshare.com/files/397625103/FCB_Looper.zip.html

Does anyone know how to save it as a standalone app?

#182161
Jun 10, 2010 at 11:56pm

There are many threads on the forum about the ins and outs of this etc. which you should look for.

Basically, you just go to the menu file/build collective/application, include the patcher you want to build into an app, and hit build. Then name it and make sure you select application (not collective) in the drop-down menu.

You can also add a picture to use as the application’s icon if you click include file, choose a pic, and then in the build script, change the word “include” to “appicon”, then finish the build process. This works for me on OSX, not sure about windows.

You’ll want to search the forum further for info about how to exclude the max window from your app, and disallow resizing of the window etc……check out the thispatcher object.

#182162

You must be logged in to reply to this topic.