GEN~ copy buffer

JesterN's icon

Hi all I'm trying to copy buffers from a circular buffer to a fix one. Doesn't work. Any help?

Untitled3.maxpat
Max Patch
Buffers


jo geisler's icon

Here is a gen code box function which works fine. It will return 1 if the copy procedure has finished.

BR

Jo
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Duplicate_Buffer (Copy_SourceBuffer, Copy_TargetBuffer, Copy_AmountSamples) {
    History Copy_SegmentSize (32);
    History Copy_Counter (0);

    if (Copy_Counter < Copy_AmountSamples) {    
        for (i=0; i < Copy_SegmentSize; i += 1) {    
                read = peek (Copy_SourceBuffer, Copy_Counter);
            poke (Copy_TargetBuffer, read, Copy_Counter);
            Copy_Counter = Copy_Counter + 1;                    
            }
    }
    else
        if (Copy_Counter >= Copy_AmountSamples) {        
         Copy_Counter = 0;
            return 1; // SPIKE :-)
        }
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Graham Wakefield's icon

Nice routine!

Maybe it needs an additional condition in the for loop to break when the source buffer is fully copied (in case the source buffer is not a multiple of 32 samples long):

Duplicate_Buffer (Copy_SourceBuffer, Copy_TargetBuffer, Copy_AmountSamples) { 
    History Copy_SegmentSize (32);
    History Copy_Counter (0);
    if (Copy_Counter < Copy_AmountSamples) {    
        for (i=0; i < Copy_SegmentSize && Copy_Counter < Copy_AmountSamples; i += 1) {    
            read = peek (Copy_SourceBuffer, Copy_Counter);
            poke (Copy_TargetBuffer, read, Copy_Counter);
            Copy_Counter += 1;                    
        }
    }
    else if (Copy_Counter >= Copy_AmountSamples) {        
        Copy_Counter = 0;
        return 1; // SPIKE :-)
    }
}
jo geisler's icon

Hello Graham, thanks for the optimization of the code :-)

BR

Jo

JesterN's icon

HI Jo, thanks A LOT! almost there, I just can't find a way to put a bang into it to control when it copies. I adapted your function a bit.

CopyBuffers.maxpat
Max Patch

I

Source Audio's icon

looking at all that stuff, a simple message to dest buffer:
set src, set dst

would copy the source buffer to destination buffer, no need for
anything else, no java, no gen ---

Graham Wakefield's icon

I assumed the OP wanted to use gen for a specific reason.

BTW the 'set' message to buffer~ does not copy data, it just changes the name that a buffer~ is referenced by.

Source Audio's icon

I am gratefull fo all possible solutions for copying, merging etc buffers.
For me the best is el.buffet~ , but it does not work for me in version 3.
setting buffer to another one and back to original, grabs data from
the other buffer, so for me it is copy, or what would one call it ?

JesterN's icon

Hi there, still haven't found out how exactly to use that code. It copies but I'd like to copy it only at certain times, when I bang for example. Still doesn't do that any help

CopyBuffers.maxpat
Max Patch

jo geisler's icon

Bangs are used in the max world. Gen is the signal world. Therefore these are two pairs of shoes. If you want to trigger a gen function from the max world you have to use a click object from the max world. When you send a bang to the click object it will create signal spike. This spike can be used to trigger a function in the gen world.

So try using the following combination: button => click => gen

Jo

JesterN's icon

CopyBuffers.maxpat
Max Patch

Hmm maybe I attached the wrong patch but I used the click there. Just doesn't update the buffers for some reason. It does when I use sig~ but at weird intervals.

No filename
No file type

jo geisler's icon

As I said welcome to the signal world :-)

When you use the clock object it sends a signal spike to gen. The audio signal looks like this before and after you trigger the click object: 00000000000001000000000..... So this means that your code in the gen object is only triggered once and that means that it only copies one segment as the code is written that way. A segment is set to 32 in the code so this means it only copies 32 samples :-)

On the other hand when you use your sig method it will send the following to gen. You click on the box and the audio signal changes from 0 to 1 and stays that way. This means that your code is continuously executed. This means that you continuously copying. You see this when you clear the buffer manually. It will always copy again...

So you need to tell gen how long it shall execute the code that I was providing you and when it should stop executing.

Start is done using click and you would need a history variable in gen to keep that state.
Stop is provided by my routing as it sends out a 1 when it has finished copying.

I know this can be quiet strange but gen has no bangs it only has a continuous flow of audio signals :-)

BR

Jo

Anatoly K.'s icon

Hi, Jo G.
Please help me to catch a gist of Gen world. When I was trying to copy a buffer I encountered a problem. I'd tried to read copied dates but I found the silence: seems, nothing happened.
I use following code:

//////////////////////////////////////////////////////////////
Buffer source("source");
Data copy(44100);
count1, count2, count3 = counter(0, 0, 44100);
size_source = dim(source);
channel_source = channels(source);
size_copy = dim(copy);
channel_copy = channels(copy);

for (i=0; i<= 44100; i+=1) {
    sample_source = peek(source, i);
    poke(copy, sample_source, i);
}
sample_copy = peek(copy, count1);
out = sample_copy;
////////////////////////////////////////////////////////////

Also, I have a question about reading the buffer/data. I know that I can use counter/phasor/lookup and etc.
But, why doesn't the following code allow to reach success:
!!!!!WARNING!!!!!!
I DO NOT RECOMMEND TO LAUNCH SIMILAR CODE IN GEN. THAT CAN LEAD TO DESTRUCTION YOUR SOUND-SYSTEM OR/AND YOUR EARS.

//////////////////////////////////
for (i = 0; i <= size; i +=1) {
    slice = peek(source, i);
    out1 = slice;
    }
/////////////////////////////////
I get audio processing exception: too many iterations (runaway loop?)

Graham Wakefield's icon

Silence because your counter() is incrementing by zero. Try "c = count(1, 0, dim(copy))".

Runaway loop because you are copying 44100 samples on every sample, that is, 44100 x 44100 samples per second.

The code in a codebox runs on *every sample* of passing time. You need to either (a) make the copy only happen once, rather than on every sample, or (b) spread the copying over time. E.g.:

a)

Buffer src;
Data dst(44100);
History docopy(1);

if (docopy) {
    // set docopy=0 to prevent it happening on every sample
    // send message 'docopy 1' to gen~ to re-trigger the copy
    docopy = 0;
    
    for (i=0; i<dim(dst); i+=1) {
        poke(dst, peek(src, i), i);
    }
}

// continuous playback to verify it:
c = counter(1, 0, dim(dst));
out1 = peek(dst, c);

b)

Buffer src;
Data dst(44100);

// copy just one sample at a time
c = counter(1, 0, dim(dst));
poke(dst, peek(src, c), c);

// continuous playback to verify it:
out1 = peek(dst, c);
Anatoly K.'s icon

Thanks, Graham. I caught your idea. Your code is clear. But unfortunately neither a) and b) works. That has not produced a sound yet. I tried to use other "buffer" instead "data" object. In that case, I see the code works because of a filled buffer window. However, it's still blear why I cannot get a sound from gen's outlet.

Graham Wakefield's icon

I tested both a) and b) before posting, they do work. Here's b) with a buffer-based dst:

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

Graham Wakefield's icon

But apparently I pasted a) with a typo -- here's a) with a buffer based dst:

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

Anatoly K.'s icon

The major point is you used the object "buffer" for a dst instead of the object "data" as you wrote in the previous comment. That's clear and does make a scene. I was wondering why code doesn't work if use the object "data".

Nodanoma's icon

great thread, was about to give up on writing myriads of samples in one for loop in gen~ until I found this. Makes total sense to split the code into segments. I am using [edge~] with segment-exceed notifications to iterate through the segments and it works like a charm! Albeit, different usecase: spreading audio across channels evenly.

Thanks everyone.