Continiously recording into buffer

hmarstra's icon

I would like to record continiously into a 2 minute buffer (from the record~objekt?) When the buffer is full I want it to continue to record by deleting the oldest material. In this way the buffer should always contain the latest 2 minutes of the performance.
Can this be done and is buffer~and record~ the right objects to use? IS there some knd of message I can send to buffer?

(The next step should be to save the latest 2 minutes (the entire buffer) when I hit some button. But this I think I can manage)

pdelges's icon

record~ has a loop recording mode. So when the record head reaches the end of the buffer, it will start from the beginning. So you get a circular buffer.
The beginning of your olr recorded sound is just afer the recording position: you get it using record~'s outlet (* 120000 in ms, with a 2mn buffer).

Last time I tried, I think this loop mode worked only as long as the recording zone was the whole buffer (so if you set the max recording point to some value, record~ won't loop at that value even if loop mode is set). In that case , you can use poke~ driven for instance by a phasor~.

AlexHarker's icon

If you do use poke~ (and I've done this to create a double circular buffer where you can always read the last N ms or samples in one contiguous block) - I would suggest that count~ would be a better object to drive it with than a phasor~ as it is specifically designed for counting in integers once per sample, whereas phasor~ is not, and you could possibly experience issues with phasor~ due to float round-off errors.....

maaaxit's icon

Another approach here, using tapin and tapout and recording a buffer when you need it.
I don't know if it's is really what you need, but you can try it.

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

hmarstra's icon
hmarstra's icon

To Patrick
It sounds like loop gives this kind of order "11 12 13 14 5 6 7 8 9 10" (14 beeing the newest material and 5 beeing the oldest)
First you fill up the buffer with "1 2 3 4 5 6 7 8 9 10"
Then you start overwriting "11 12 13 14 .....
This gives a strange jump in the recording from "14" to "5"

I would like to somehow maintain the chronology so that the order was always "1 2 3 4 5 6 7 8 9 10) It shoud record till it reaches the end of the buffer and then continiously erase material from the beginning and move old material gradually towards the beginning of the buffer and ad new material to the end of the buffer.

what about the append command for record~

"Last time I tried, I think this loop mode worked only as long as the recording zone was the whole buffer"
I guess in my case the record will use the whole buffer so this is not an issue. Or did I misunderstand?

------
To Patrick/ AlexHarker

Poke~ sounds promising. For some reason the poke~ objekt doesnt show up. I will look into it

------

To maaxit

This sounds also interesting, but Im guessing that I would have to wait for the recording to happen from the point when I initialize the recordprosess. So If I want 5 mins of recorded material I would have to wait those 5 min before the prosess is compleated

Im using unfortunatly using max 4.5 so is there any chance of posting tew patch in an older format (perhaps this is an option in the text format of max 5) Or post a screenshot?

Henrik

pdelges's icon

Alex, you're right about count~; when I wrote "for instance", it was because I had this in mind but I'm currently working on a difficult looping system where phasor~ was unfortunately much more adapted than count~:-)

hmarsta, to get the right order you need to play the buffer from the last recorded position, wrap around at the end of the buffer to start reading from the beginning and stop after 2 minutes. That's the idea of a circular buffer.
As you will indeed use the whole buffer, my warning about loop mode is indeed useless for you :-)

hmarstra's icon

found poke

hmarstra's icon

Patrick: Im having differculties getting the exact details of your explanation. (Havent use poke or count before) Gratefull if someone have energy to post a quick patch (in some readable format: screenshot, old max format) ...... :)

AlexHarker's icon

This was what I did:

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

The buffer is TWICE as long as you actually need - it writes twice into the buffer at a time so that wherever you stop you can always read the last N ms contiguously (it doesn't move stuff - it just has two copies).

To get the bit you want subtract from the write position output the length of time you require and it will start at that point in the buffer. I'd leave a few ms spare at the end of the buffer to account for timing inaccuracies between max and msp. The length of the buffer is set in samples (in the count and +~ object - they need to be the same number) and in the code as sent is 60 secs at 44.1kHz sampling rate.

There is an upper limit to how long you can record accurately for in this way, as determined by the 32 bit floating point format (at some point counting will fail because you run out of bits) - there are 24 bits of accuracy in a 32 bit float - so thats 2^ 24 = 16777216 samples if my maths is correct, which would be about 380 seconds or about 6 minutes at 44.k Hz, but only about 1 minute twenty at 192kHz, so be careful. In addition to this because you need a double buffer for the technique I'm proposing that time is halved - there's no workaround for this using standard max objects - that's just the way it is.

If you want to then save the recording it you may need to copy / or crop the buffer somehow just to get the bit you want - there are plenty of posts here on the forum regarding those topics (it wasn't relevant to what I was trying to do).

Alex

maaaxit's icon

Yes, as I have wrote in a comment in the patch, there is this kind of limitation in my approach. You can have two couples of tapin-tapout (one for the recording and one for playing in order to get continuous sound),but if you need quickly availability of the buffer, my patch doesn't work.

But this can be a good question for the forum:
there is a way for writing a buffer directly from tapin?

Probably not useful for you, but here the patch for 4.5

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

hmarstra's icon

Sorry for the weekend absens. Many many thanks for posting patches. Maaxit, as you point out its the timedelay issue with the tapin/ out approach. I will keep this option as a backup solution if I cant make the other one work.

AlexHarker: Great. I will dive into it. So the input is the audiosignal. What about the two outputs. Where do they go? (they both say write position (ms) )

AlexHarker's icon

The outputs are what you calculate the read offset from. One is in samples - the other in milliseconds - probably the milliseconds one is more useful... See above for how to work out the offset to read from. If you want to turn recording on and off you'll need to modify the patch a bit (see the count~ helpfile~). In my case my needs were for the buffer to be constantly updating.

A>

hmarstra's icon

Thanks. Finally got it right
I used waveform and its crop (based on selection) message to resize the buffer

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

just have to remember to send size 120000 to buffer~ when you want to make a new recording after cropping (to 60000)

manysounds's icon

Kicking up an old topic here.
What I want is a long buffering loop that when I hit the "record button" saves the last 30 seconds and then continues to record
WHat I'd like to do is what HMARSTRA has BUT -when it gets to the end of the buffer the buffer "wraps around".
So I "think" what I could do is have a second selection area for a third buffer and then glue them together.
Make sense? So you end up with a half-buffer at the end and a half-buffer at the beginning and then when you hit a "save the last 30 seconds" (or however long) it prepends the end buffer to the beginning buffer and saves the newly created buffer.
Alternatively I guess I could record into HMARSTRA two buffers simultaneously, one of them offset by half the length and then, again, do the stitching afterwards.
There must be a more elegant way to do this but I'm not MSP god, just a hack.

Forest Kelley's icon

@manysounds, Did you find a solution? I need to do the same thing.

I have a program that generates sounds on it's own and I'd love to have Max recording continuously in the background so that if anything good starts to happen, I can start to record but also have the previous x minutes already recorded.

Source Audio's icon

post your logic as a list here.
Then one can look for best options, buffer based,
or combination buffer to keep x minutes history +
HD recording based long appended recording.
It depends in first place on available RAM, and maximum allowed rec time.
do you want to continue capturing of x past minutes in the background even after long recording started, what to do to stop recording and save file, or cancel and delete what got recorded so far, and so on.
Many questions to answer....
But the logic arround simple recording elements is the complicated part.

In the meantime you can have a look at stutter~ object
for history recording, and some sort of buffer copy (there are many options)

Oni Shogun's icon

hi there,
just found this thread as I was looking for such a tool myself – then thought I'd build an abstraction for it, and here it is:

it seems to accomodate all the necessary convenience features as it's based on mc.gen~ codebox, including export of recorded file, variable length and channelcount of audio, looped playback, etc.

I've added a helpfile and reference doc accordingly but obviously have not tested in depth yet.

recording audio

playing back recorded audio

hope this is useful for someone or other, do let me know if you run into trouble…
ciao xx