rezer~ (looper w/ sample-accuracy)-...replaced by rez~

πŸ‘½'tWβˆ†s βˆ†lienzπŸ‘½'s icon

[Latest News: October 18th, 2020 - the rezer~ object is deprecated to make way for the 'rez~' object, a much simpler, more-efficient sample-accurate looper, see my post dated 'October 18th' below for more info. and keep on the lookout for a new thread for "rez~" coming soon ]

historical-archive-only of rezer~ description:

Hello and a beautiful day to you all! πŸ€— (after stepping away from Max for 2 years due to life stuff a few years back, didn't think i'd get my chops back, but lately seems perhaps improving... so this is quite a lucky thing that i created this... hope you'll all be patient with me as this work was very unexpected and flowed out of me as though from somewhere else...)

feature list:

  • it's free πŸ˜‹

  • sample-accurate stopping/starting/retriggering

  • built-in de-clicking fades at all starts, stops, loop-points, and retriggers(as well as when play and record positions cross; at loop-points and retriggers, the de-clicking is a tight crossfade from where the playback was into where the playback skips to), plus the same on the recording end(with a clever bit added to incorporate fading/crossfading previously-recorded material around an overdub amount)

  • different modes for styles of sequencing(things can be triggered right away, or they can wait til a loop-point is crossed before responding to signal changes/triggers at inlets)

  • can only do 1x or -1x recording speed - this leaves the object much easier to use efficiently CPU-wise as well as manage ongoing development(but years down the line, if you're still craving this object with varispeed recording, let me know, i'll think about it then...)

  • playback employs 'hermetic bicubic'(also just known as a form of 'cubic') interpolation at all times for high-quality varispeed playback, and the interface allows you to control the record-head separately from the playhead(each has their own independent start/stop, loop-start/end signal-inlets for specific control).... (this also means there is an additional de-clicking to take care of whenever the playhead crosses the recordhead; it will duck out the playhead smoothly momentarily until they are safely apart from each other(at a distance of 'fade' * 2))

  • additional 'virtual' playback boundaries - so you can limit playback controls to one part of a buffer~ while recording can go all over

  • 'overdub' amount(for recording) is controlled by signal - allows for side-chain driven modulation or precise mixing

  • helpfile shows how to make it MC-compatible - so you can have as many playheads and recordheads all independently controlled as you'd like πŸ˜ƒ

  • currently only 'mono' and 'stereo' modes available - the way mono/stereo works is you have to instantiate the object with a 2nd argument for the type you want and then the object will always only play/record in that channel-setup.. for example, a rezer~ instantiated as "rezer~ bufname 1" is only capable of addressing mono-buffer~s, and you can't send a message to it to suddenly change it to address stereo buffer~s; if you want to switch between stereo and mono buffer~s, use a stereo form of rezer~(no 2nd argument defaults to stereo, so just instantiate like so: "rezer~ bufname") and then create your own switching mechanism at the output of rezer~ to send the left channel out to both channels when the buffer~ is mono

Sounds like a perpetual remix machine πŸ˜„πŸ»

daddymax's icon

Thanks Raja - your work on Karma was legendary, and this has the features I've been really keen to get. Greatly appreciate your sharing this.

Claudio Bellini's icon
alfonso santimone's icon

Great! Thanks! So is karma~ considered obsolete?

Rodrigo's icon

Awesome!

Looking forward to having a good play with this. That's one of the biggest things people will message me about for karma~, is how to sync up multiple instances.

@Alfonso
karma~ is still going (there's a v1.5 on github that isn't terribly well documented yet), with some nice plans for a 2.0 build in the future.

πŸ‘½'tWβˆ†s βˆ†lienzπŸ‘½'s icon

MAJOR UPDATE! - v.008 - released May 15th, 2019
(it's the 2nd/last attachment to the top/original post, you'll see it labelled 'v008'
- again, the .mxo for Mac, the .mxe64 for PC, plus a new helpfile - all attached there)

For a more easy experience getting it to work like karma~ where you can use the recording length to set the window duration, i've added a "Mode 3"! The helpfile tab 'mode3' will show you how this is done(in addition will show you how to append using mode 0).
Detailed list:

  • Added mode3 for setting playback duration by recording length

  • optimized interpolation(whole number speeds don't need interpolation so it's skipped in such cases)

  • forced inline functions(a small compiler-specific consideration, not a huge difference, but just in case it helps optimize further)

  • removed some unnecessary constraints

  • extra code for varying buffer~ sample-rates

  • removed unnecessary things like unused messages, etc.

  • added safer checks for reworking buffer~-access boundaries whenever 't_max_err' notifications are received/requested upon buffer~-modifications made by sources outside the external

  • reworked boundaries/constraints.

  • updated Github with the v.008 code

  • created another tab to explain mode 3 in the helpfile

  • some known issues:

  1. there's a possible crash if you leave rezer~ with playback or recording on while rapidly resizing the buffer~ it's referring to(i generally get this crash if i attempt to constantly switch the files in the buffer~ at a constant rate and more rapidly than once every 100ms, while i am recording/playing in a later part of a bigger buffer~ and suddenly replace the buffer~'s file with a shorter file thus resizing it much smaller, leaving playback/recording in a dangerous area), to avoid the crash altogether, you can turn off playback and recording temporarily for a short instant before you resize-buffer~/load-another-file, and then turn it back on after the resizing/loading is completed

This will be the last major push for awhile, and because there is so much here now, i can't say i've thoroughly tested it all, so have a go, and enjoy. πŸ‘Š

Thanks, All! I truly appreciate everyone checking it out so farπŸ™

[Edit: @Alfonso - karma~ is still alive, these two objects will serve different purposes in different ways and exist nicely in the same ecosystem πŸ‘]

alfonso santimone's icon
yaniki's icon

"control the record-head separately from the playhead"!!!

Roel Peters's icon

Awesome, super fun playing with the MC version :-)

πŸ‘½'tWβˆ†s βˆ†lienzπŸ‘½'s icon

The... (whaddaya call it? πŸ€”.. πŸ’‘!) "Life sityeeashun" has crept up on me again, but never fear!
I will extend beta-test to 2/19/2019,... no wait.. sorry extended to 19/2/2019... no wait, sorry, ...
ah yes: 10/29/2019 (and if ya don't hear from me then, perhaps til 12/9/2019... but beyond that and we're all screwed πŸ€·β€β™‚οΈ ...just kiddin 😜
...but besides, are these euro-format dates or american? who cares: i heard it's all based on the bible, anyways, and have you read that thing lately?! 😭)
I'll get around to testing this properly soon meself πŸ˜‹ And anyone else feel free, but no worries if not, too, this is my own amateur-design-weirdness πŸ§Ÿβ€β™‚οΈ(<-dang, looks just like me too)... karma~ is still out there, let's all stay in touch and revolve around each other like... i dunno...
something infinitely intimately cyclical πŸ’ƒ πŸ•Ί

-πŸ‘½

Jonatan Krogh's icon

I don't know how this is possible. I've been searching this forum for loopers for 4 months. I've read every thread about Karma~ and it's conception, and on all kinds of tools and methods for looping...

.... then in the end i built this, using ipoke~ and wave~ and just dropped this monster post about it. https://cycling74.com/forums/cantor-8-track-synchronised-looper

... ten minutes later i find this thread for the first time. From google. And i wasn't even searching for anything loop related.

Incredible. Ok, very excited to find this, just wish i saw it a few months back.

πŸ‘½'tWβˆ†s βˆ†lienzπŸ‘½'s icon

Ha, glad you found it :)
I've not been pushing it hard out there since it's just me working on the project(this thing is probably hard for others to grasp because it needs a better helpfile(i'm not great at making helpfiles all by myself), and i also need to isolate/fix some bugs: if you run into any problems where the object is stuck in a loop, set the 'fade' time to 0. and try again, there's one major bug where it can get stuck with very small loop times as i need to code it to better account for fade-times at ultra-short loop-lengths - other than that, it's actually quite speedy and efficient so i'll definitely get this thing more and more polished over time :D).

Thanks for checking it out! Will keep at it, Cheers!

Jonatan Krogh's icon

Here is a very basic test patch. Sounding clean and nice!

Some things that confused me:
I notice that if i change the end position, it doesn't react until i trigger the loop again. Is this by design?
The example file explains mode 0 and mode 3.. but what is mode 1 and 2?

That xtra help file is the best sounding use of the standard max sounds I've heard so far!

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

πŸ‘½'tWβˆ†s βˆ†lienzπŸ‘½'s icon

hey, sorry for my delay in response:
-that was by design- the 'start' inlet shifts loop immediately when it detects a change in value while the object is in mode0(default) - one workaround: you can use 'pak' into 'unpack' going into both 'start' and 'dur'(you have it labelled as 'end' but it's actually a 'duration' of loop, like there's a start position(0-1) and then a duration(0-1) added to that for the end of the loop, this is to help think in terms of wrap-around/circular-buffer loops, like the karma~ object by keeping the end relative to 'start' by a fixed duration at all times)... and each time you change the end/'dur', you could add a small noisy/random offset(like 0.00001) to the 'start' signal(there's another workaround too but it's a bit complex to synchronize an off/on right at the sample of changing the end... i'll have to find some time to show this in a patch in detail later, but this would be the most sample-accurately synchronized way)

-apologies, the language is a bit confusing(and the text isn't easily noticeable in the helpfile plus my helpfile design needs work, haha), mode1 and mode2 are in the explanation on the first tab of the helpfile, just above the waveform:
"in Mode 1, object waits til playback's loop-points to register changes in both playback and recording settings, and in Mode 2, object waits til playback's loop-points to register changes in playback settings and til recording's loop-points to register changes in recording settings"

basically, in Mode1, supposing you have both recording and playback on, and they're both set to different loop-points(and within a loop you make changes to 'start' and 'dur' values for both recording and playback), all changes to loop-points for both will be synchronized to whenever the playback part of the object reaches the end of its loop(this is when it will actually register the changes), whereas in mode2, the object will register changes to recording-'start'-and-'dur' when it reaches the end of a recording loop and will register changes to playback-'start'-and-'dur' when it reaches the end of a playback loop.
basically mode1 synchronizes both recording and playback changes to playback loop, and mode2 allows them to act individually, and both of these modes differ from mode0 in that they no longer register changes to 'start' inlet immediately - these are modes to help you synchronize real-time control to the exact sample-accurate duration of each loop.

That xtra help file is the best sounding use of the standard max sounds I've heard so far!

ha, thanks!

hope this helps a bit, i'm too busy this week, but i'll try and find time in the next 2 weeks to put together a better example of what the modes do, and how to sync up changes better.
in the meantime, feel free to let me know how you'd like it to work ideally and when i get a chance to look at the code again i'll see if i can implement or if not, at least find some sort of compromise, etc. eventually shaping the object to as much general usage as i can(keeping in mind, in order to de-click and keep sync at sample-accuracy, fade-time needs to be accounted for, this makes instantaneous change of everything more complicated... but i'm willing to keep at it over time).
🍻

πŸ‘½'tWβˆ†s βˆ†lienzπŸ‘½'s icon

"more excuses?" you say? πŸ˜‹ yes πŸ˜‡
have to postpone work on this for another month
working on other stuff, and... i'm depressed 😭 this pandemic sucks, the usa is and has always been a strange place to live(and today's my birthday, somebuddy hold me πŸ₯Ί).... ok, feeling better already, i do plan on working more on this, just need to move more slowly in order to maintain calm in these trying times, thanks for the patience of anyone that's interested in this(likely back on it in Sept. or Oct. - check back then) πŸ™

Wetterberg's icon

wow, just saw this - happy birthday Raja! These are terrible times indeed - virtual hugs for you.

I had completely missed this thread - been away, too. I will use the time until your no doubt triumphant return to relish this work - this is like, Karma~s more responsible, but slightly less wacky, bigger sister. This could be my "diy MLR" object. So good!

I'm legit drooling right now, thank you so much for sharing this

πŸ‘½'tWβˆ†s βˆ†lienzπŸ‘½'s icon

Thank You, Wetterberg! Good to see you, welcome back :)
Glad you like the object so far, too. Feel free to let me know any suggestions to the interface(long time ago you did so with karma~ and i was rude, sorry again about that πŸ˜…), i'm sane these days(comparatively speaking, perhaps the pandemic has caused the world to stoop to my level of crazy and so i only feel sane relative to the general insanity (?...πŸ€”)...either way it's working! 😜) so i mean it now: feel free to let me know what you'd like, i'll do my best and i am looking to make this better and more widely accessible(so i will not be an asshole this time, i promise πŸ˜‡).

Here's some things i need to think about currently just so folks in general understand things i struggle with in the design:

  • if the end position doesn't actually change unless the start does, it might not need to be controlled by a signal(can be made more efficient as events), so maybe we need a messaging system and then a signal triggering system

  • the main problem i'm trying to avoid here is having too much signal-based triggering of the declicking-fades(don't want this code to get too complicated)...

  • all while i still want to leave it open to sample-accuracy - there is actually a benefit to leaving everything as is with signals only too: when you get down to granular-synthesis rates of control, then it can be more precise to keep control in all signals than trying to work around signal-vectors of delays in event-polling... (but then again, not sure if anyone actually needs a looper that can double as a granular-synthesis engine? πŸ˜… ..i was thinking in live-performance, though, this can sound very good shifting between the two uses - and also, if you use this object at nominal speeds (not too much faster than 8x on playback side, and not constantly retriggering fades, it can actually be pretty efficient embedded within poly~ for multiple voices and such in a granular cloud - was going to make an example of this in particular soon)... i dunno, must think on these things more...

Anyways, thanks again πŸ™ I'll be back on this soon(latest by Oct.) 🍻

Wetterberg's icon

:) all water under the bridge - I am honestly just happy to see you, and being this productive too!

I will try to be thorough, but I think I'll need to live inside this external for a good while to really grok it.

the sample accuracy is definitely a big draw here.

first step for me is to see if I can sync it to a phasor~ without breaking my poor pandemic brain. Just to have a basic rig to test this from.

Playing around with the playback position, I found that "position 0.25" is the same as "position -0.25", which means you can do some fun retriggering by alternating between them. So I hope this stays in :)

I love the idea of using it for crazy things like granular synthesis!

πŸ‘½'tWβˆ†s βˆ†lienzπŸ‘½'s icon

Hello Everyone! I revisited the code here, and decided to do away with the complexity. I've coded a new object called "rez~". It is much simpler:
1) For playback, the signal-inlet controls are 'starting-phase', and 'speed':
a speed of '0' turns the object off, any other speed turns it on; changes in on/off,
starting-phase, sign of speed(negative<-to->positive), loop-point crossover,
recording-head-over-playback-head crossover, will automatically trigger
the appropriate de-clicking(fade-ins/fade-outs/crossfades)
2) For recording, the signal-inlets are for 'starting-phase',
'speed'(-1., 0., or 1.; reverse/stop/forward only),
overdub, and recording-inputs for left and right
3) For outlets, all signals: there are playback outputs(left and right),
a playback-phase outlet, and a recording-phase outlet
4)The only messages are "in", "aus"(for playback-loop 'in' and 'out' points),
"rin"/"raus"(for recording-loop 'in' and 'out' points),
"fade"(to set the fade-in/out/crossfade times in samples),
and "set"(to change buffer~s referred to).
5) Like rezer~, it has a clever crossfade for playback and recording
(in recording, the crossfade accounts for overdub amount)
6)Unlike rezer~ there are no complex modes, and no extra signal-inlets to register
changes to loop-points, and no 'virtual'-boundary b.s., etc...
but there are 'initialization-modes' which allow you to setup the object more efficiently: the object takes 3 arguments -> buffer~ name(mandatory), channel-number(optional... although mandatory if you want to enter up to three arguments), and initialization-mode(optional)
the initialization-modes allow you to access "play"-only functions, "rec"ording-only functions, or all functions at once, just give a 3rd argument of either nothing(for all functions available), "play"(for only playback functions), or "rec"(for recording-only functions). accordingly, the object will initialize to cut-out any unnecessary inlets/outlets, and internal variables/functions, etc. to give you the most efficient possible object for whatever usage you choose
(for example, creating an object like so:
[rez~ bufname 1 play], gives you a 1-channel playback-only object, where only two signal-inlets are provided(the two for playback-control only), and 1 signal-outlet for single-channel output, plus 1 signal-outlet for playback-phase..
..or creating an object like so:
[rez~ bufname 1 rec], gives you a 1-channel recording-only object, where 4 signal-inlets are given(starting-phase, rec-speed(-1/0/1), overdub, rec-inputLeft), and 1 signal-outlet for recording-phase signal..
..whereas, creating an object like so: [rez~ bufname]
gives you all signal-inlets/signal-outlets/functions(and 2-channel by default))

This object is sample-accurate, plays beautifully(all play-speeds handled by cubic-interpolation), and is quite robust! (no crashes as far as I can tell, i think i've put in place more proper thread-safety buffer~-change protections than before... coded more simply, the minimalism here amplifies the power/effectiveness of this object very naturally and allows me to keep track of the code better :D).
The only thing which isn't sample-accurate are changes in loop-points(set by messages... however, there's a way to make sure it's always within loop-points: send a different 'phase-starting-point' signal right at the same time as changing the loop-points, this achieves that ultra-fast sound of scrolling along a small loop-duration/window for time-stretchy effects).
There is also a beautiful glitch: with a small enough loop-window to cause interference with fade-times, the object enters into a fast amplitude-modulation glitch(crossfades start to interfere with each other), sounds... 'metallic' and springy :D... and you can control this effect to some extent by changing loop-duration or fade-time or both(i just had to leave it in since the fades/crossfades designed to tame the glitch of clicks/pops, ends up creating a new glitchπŸ˜‹).

Anyways, this final post is to close off this thread(hopefully no one got attached to the way rezer~ functioned so far, didn't hear much response here, so i'm hoping that will be all to the good). And to gauge interest:
would love some serious beta-testing!
Attached is a macosx-only version of the object plus it's helpfile(i could use further help on bettering the helpfile here, too).
Let me know if you'd like to beta-test the new object on windows, and I'll start a new thread for the "rez~" object soon as I can gauge enough interest(otherwise, check it out in the attachment here (for macosx only) and i'll start a new thread later as more folks trickle in with interest).

Cheers!🍻

rez~_betaMac.zip
application/zip 53.64 KB

alfonso santimone's icon

Great! I can test on Win10!

πŸ‘½'tWβˆ†s βˆ†lienzπŸ‘½'s icon

Excellent! I'll get another thread started with a Windows-version compiled and attached there, uploaded by this Wednesday(10/21), i'm just finishing last-minute additions(added a 'oneshot' attribute, and finishing the helpfile to describe it). Thank you so much!

πŸ‘½'tWβˆ†s βˆ†lienzπŸ‘½'s icon

the simplified rez~ object(and accompanying thread) is now here.