gen & loop size synced looper

jo geisler's icon

Dear all,

I am currently patching a live performance looper and have some basic gen architectural questions:

What does the looper do:

There is only one button (record / play) where loops are recorded at a first press and played with a second press. Recording of any additional loops starts always immediately when you press the button. Syncing is done via loops length as the loop lengths are dynamically adjusted (shorten loop / extend loop length).

The initial loop provides reference length of the loop e.g. 64 samples. The second and all following loops will be automatically trimmed to a division or a multiply of the sample length (factor 2: eg. 1,2,4,8,16,32,64,128,256,... samples). In this example the first loop is 64 samples long. If the second loop was recorded and would have a length of 70 samples it will be cut down to 64 automatically. Another example would be a third loop that would record 40 samples would be cut down to 32 samples (nearest). With this methodology all loops loop in the same place and are in sync (no drifting).

This functionality is know from the KaosPad from Korg.

My question:

for my looper I need to have always loops stored in a buffer that are related with each other with the division or multiplication of 2 (2,4,8,16,32,64). If I e.g. have a reference first loop of e.g 125 samples and a second loop that was recorded with 60 samples I would need to extend the second loop to 62,5 samples (to be a multiple of the first loop) which is to my view not possible... If I extend the loop to 63 samples my looper would be out of sync.

In short: how can I have a loop that is 125 samples long and another one that is exactly half the length so that both loops will stay in sync concerning the loop length. To my view samples are the smallest measure in Gen...

Any thoughts for a solution?

Jo

Evan's icon

I would probably rethink how necessary it is to have the loops be exactly half the length. Instead of worrying about 'drifting' you could just resync all the loops when the 'master' loop restarts (or when the longest loop restarts or something).

jo geisler's icon

Thanks Evan for your feedback.

I considered that already but as this is a live performance looper where the first loop could be just 100ms long (e.g recording audio from two really fast clicks on the record / play button) resetting would take place very often and I would rather have a tighter solution that has no drifting and the nessesarity to re sync.

I went down the GEN path especially with the looper to avoid the nessesarity to resync as I understood that this is possible with the sample accuracy that is provided with GEN.

Hope for any other suggestions from the GEN members :-)

Evan's icon

Well yeah it's possible to not have to resync, when you're working with integer indexes (samples ion a buffer), and not fractions of indexes. You're going to have to make a compromise somewhere in your implementation.

Another thought would be, if a loop has a non integer length, you could change the length of the loop according to how many repetitions will account for an extra sample drift. For instance if the length was 200.5 samples, the loop length would be 200,201 ,200 ,201. This becomes more of a pain if the loop length is 200.25, then it would be 200, 200, 200, 201.

I'f be interested to know how noticeable the 'drift' is in practice if you just rounded to the nearest integer value.

jo geisler's icon

Evan, just have to laugh out loud as I had the same thought last night thinking about the problem :-) So this would mean I would have:

1. one audio loop => standard implementation with gen buffer, peek, poke & counter objects
2. one loop with a series of loop integer sizes => a bit of codebox code which provides a series of different loop integer sizes according to the initial loop size

Before I will get into trying out the idea above one further general question that struck my mind:

With the implementation above I provide my loops individually with start and end points that in relation to each other will ensure that they will always stay in sync concerning their relative loop sizes. There is no fixed link between the first, master loop and the rest of the loops during runtime (when the loops are played) as e.g. counter index objects are not connected to each other.

So are you aware that gen ensures that there are no hiccups / drifts concerning the triggering of gen objects / scripts when a sample changes? Hope that makes sense... Just one example: If I would have 10 loop buffers in gen I could provide them a counter with start end parameters and let them run or I could provide the master loop with a counter and link this counter to all other 9 buffers.

Joachim

Source Audio's icon

Syncing loops of different lengths in real time performance.
I did such loopers many years ago without gen with plain max objects.
The thing is - musician wants to record something and have it repeated
the way it sounded in context while played. Is that so in Your concept ?
Let's say You have a Loop of 1000 ms feeling like 4/4 rolling, and someone records
a fragment that would do 6/8 pattern in same tempo, and the recording started
somewhere in the middle of the playing loop, because it just sounded right.
Now how do You plan to restart the whole loop machine, and play the loops
so that they allign exactly like they were recorded and originaly played ?
My solution was this way - divide the first Loop's length till one gets a value
that still can be accepted as a beat or managable length that a musician can
accep as a rhythmical point.
That becomes quantising length for the future Loops.
Every time new loop recording starts, it actually waits for a quantised point
and also ends that way.
At same time recording offset compared to first loop's start gets noted,
so that Loop can be restarted at the same position as recorded.
Easy part on that was that I did not have to deal with such short
Loops as 100 ms.
Maybe You can find something usefull in the whole story...

jo geisler's icon

It is pretty similar as you described except that loop recording starts anytime. You push the record button it starts - the internal logic takes care that when you press the record button again either continues the record or cuts the loop to a measure that keeps the looplcenght in sync with the original one. So you will always get loops with a loop length of 1, 2, 4, 8, 16, 32, 64 times or a division of the first loop length. This is total freedom to me.. :-)