Hi list,
I'm looking for concepts like a queue or arrayDeque in Pd. Like a delay line which I can pause adding new elements into and it will act like an array until I decide to add more. At audio rate. Is there something simple that I have overlooked? What's the best strategy to implement this?
M.
Hi, Max.
You could have a looper feeding into a variable delay line whose delay is modulated appropriately.
A looper would be an N-sample feedback loop with some input feeding into it, where the input gain and the feedback gain are mutually exclusive. That would prevent new elements from being added and you'd have the same recirculating material when you freeze it:
y[n] = Rx[n] + (1-R)y[n-N]
with R being 1 to write into it, or 0 to freeze it.
The output of the looper could then feed an N-sample delay line whose delay is offset consistently to always point to the same buffer position:
delay[n] = (lineN[n] + element[n]) % N
where
lineN[n] = (1[n-1] + lineN[n-1]) % N
and element[n] is an int between 0 and N - 1 determining the array element that is being output.
I don't have this in PD but here's the Faust implementation:
https://faustide.grame.fr/?autorun=1&voices=0&name=lotkavolterra_A&a...
Ciao, Dario
On Fri, 26 Feb 2021 at 14:03, Max abonnements@revolwear.com wrote:
Hi list,
I'm looking for concepts like a queue or arrayDeque in Pd. Like a delay line which I can pause adding new elements into and it will act like an array until I decide to add more. At audio rate. Is there something simple that I have overlooked? What's the best strategy to implement this?
M.
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list
Em sex., 26 de fev. de 2021 às 10:03, Max abonnements@revolwear.com escreveu:
Hi list,
I'm looking for concepts like a queue or arrayDeque in Pd. Like a delay line which I can pause adding new elements into and it will act like an array until I decide to add more. At audio rate. Is there something simple that I have overlooked? What's the best strategy to implement this?
M.
I'm thinking about creating a variant of delread/write~ for ELSE with this "freeze" functionality. But maybe we can request to add it to vanilla.
Em dom., 28 de fev. de 2021 às 16:20, Alexandre Torres Porres < porres@gmail.com> escreveu:
maybe we can request to add it to vanilla.
Hey Max, what do you need this for exactly? I've been meaning to get to this since I started working with cyclone, the idea then was to clone tapin~/tapout~ but the same design seems complicated for Pd as I discussed in other threads.
So, I made changes to delread4~/delwrite~ that allows freezing, but I already have 2 delay externals in ELSE, and I should "freeze" them too.
I have [ffdelay~] and [fbdelay~] (feed forward and feedback). These are single objects so you don't need a "write"/"read" pair. For feed forwarding delay, that's just fine, the problem with [fbdelay~] is that you cannot put anything in the feedback loop, for that you need a pair like tapin~/tapout~ or delwrite~/delread4~ and put other stuff inside the chain.
So I ask why you need this for cause if it's for feed forwarding or simple feedback (without putting anything in the feedback loop), my existing externals would be ok for you now. I'll focus now on how to freeze them now as well.
cheers
Em dom., 28 de fev. de 2021 às 17:23, Alexandre Torres Porres < porres@gmail.com> escreveu:
Em dom., 28 de fev. de 2021 às 16:20, Alexandre Torres Porres < porres@gmail.com> escreveu:
maybe we can request to add it to vanilla.
Em dom., 28 de fev. de 2021 às 17:23, Alexandre Torres Porres < porres@gmail.com> escreveu:
PR that adds freeze to [delwrite~], ya'll can test https://github.com/pure-data/pure-data/pull/1276
As Derek Holtzer pointed on facebook, you can do something like this to freeze:
[image: Screen Shot 2021-03-03 at 09.52.16.png]
So I wonder if that doesn't already make it for you Max. And how crucial it'd be to have this in Vanilla.
Em ter., 2 de mar. de 2021 às 16:44, Alexandre Torres Porres < porres@gmail.com> escreveu:
Em dom., 28 de fev. de 2021 às 17:23, Alexandre Torres Porres < porres@gmail.com> escreveu:
PR that adds freeze to [delwrite~], ya'll can test https://github.com/pure-data/pure-data/pull/1276
this way Alexandre posted won't prevent the write pointer of the delay line from advancing, when you unfreeze it will write in another place, and not append where it stopped.
Also on facebook i came with a solution with switching off the delwrite, and then you need to update the time in the delreads if there is anyone reading from that delwrite, i will post the patch, see if you need something like this
this can be used to create very glitchy effects, if you put little things in the delay line and keep freezing and unfreezing
Em qua., 3 de mar. de 2021 às 10:08, Alexandre Torres Porres < porres@gmail.com> escreveu:
As Derek Holtzer pointed on facebook, you can do something like this to freeze:
[image: Screen Shot 2021-03-03 at 09.52.16.png]
So I wonder if that doesn't already make it for you Max. And how crucial it'd be to have this in Vanilla.
Em ter., 2 de mar. de 2021 às 16:44, Alexandre Torres Porres < porres@gmail.com> escreveu:
Em dom., 28 de fev. de 2021 às 17:23, Alexandre Torres Porres < porres@gmail.com> escreveu:
PR that adds freeze to [delwrite~], ya'll can test https://github.com/pure-data/pure-data/pull/1276
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list
They're all different, both patches and my PR, which will just stop writing new values into the delay line.
I don't know if there is a special/canonical way of doing freeze that suits a specific use case. MAX's code is closed so we'd need to make some reverse engineering tests or ask users.
I can think of yet another fourth approach which is waiting until the delay line reaches the end and then stop writing.
What bothers me in some cases with delay lines is that when you loop through the delay line (such as when doing a reverse delay effect) you get a click. The code could perform a cross fade to avoid that. My 4th proposed approach could be useful for that.
Anyway, time to better research the golden rule and practices of freezing delay lines.
cheers
Em qua., 3 de mar. de 2021 às 13:04, José de Abreu abreubacelar@gmail.com escreveu:
this way Alexandre posted won't prevent the write pointer of the delay line from advancing, when you unfreeze it will write in another place, and not append where it stopped.
Also on facebook i came with a solution with switching off the delwrite, and then you need to update the time in the delreads if there is anyone reading from that delwrite, i will post the patch, see if you need something like this
this can be used to create very glitchy effects, if you put little things in the delay line and keep freezing and unfreezing
Em qua., 3 de mar. de 2021 às 10:08, Alexandre Torres Porres < porres@gmail.com> escreveu:
As Derek Holtzer pointed on facebook, you can do something like this to freeze:
[image: Screen Shot 2021-03-03 at 09.52.16.png]
So I wonder if that doesn't already make it for you Max. And how crucial it'd be to have this in Vanilla.
Em ter., 2 de mar. de 2021 às 16:44, Alexandre Torres Porres < porres@gmail.com> escreveu:
Em dom., 28 de fev. de 2021 às 17:23, Alexandre Torres Porres < porres@gmail.com> escreveu:
PR that adds freeze to [delwrite~], ya'll can test https://github.com/pure-data/pure-data/pull/1276
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list
Em qua., 3 de mar. de 2021 às 13:54, Alexandre Torres Porres < porres@gmail.com> escreveu:
Anyway, time to better research the golden rule and practices of freezing delay lines.
For reference, this seems like a regular use case of "freeze delay", which is eventually looping your input https://www.youtube.com/watch?v=XVghai8leTI&ab_channel=EZBOT
another reference from what's out there: https://www.youtube.com/watch?v=gnnpXHbNP_g&ab_channel=DoNoise
Em qua., 3 de mar. de 2021 às 16:34, Alexandre Torres Porres < porres@gmail.com> escreveu:
Em qua., 3 de mar. de 2021 às 13:54, Alexandre Torres Porres < porres@gmail.com> escreveu:
Anyway, time to better research the golden rule and practices of freezing delay lines.
For reference, this seems like a regular use case of "freeze delay", which is eventually looping your input https://www.youtube.com/watch?v=XVghai8leTI&ab_channel=EZBOT
very nice videos! but i think i used the wrong name then, what i did was what max asked, when you switch off the delay, it just works as an array and the write pointer keeps frozen and only resumes writing when you switch it on again
i didn't mean to create these effects from the videos, sorry...
the only thing that makes this cumbersome is that to read it you need to mannualy advance time in the delreads when the delwrite is switched off, but it is a way to implement this controlled "queue" delay, where you let the delay write or pause until you decide to write more
Em Qua, 3 de mar de 2021 16:42, Alexandre Torres Porres porres@gmail.com escreveu:
another reference from what's out there: https://www.youtube.com/watch?v=gnnpXHbNP_g&ab_channel=DoNoise
Em qua., 3 de mar. de 2021 às 16:34, Alexandre Torres Porres < porres@gmail.com> escreveu:
Em qua., 3 de mar. de 2021 às 13:54, Alexandre Torres Porres < porres@gmail.com> escreveu:
Anyway, time to better research the golden rule and practices of freezing delay lines.
For reference, this seems like a regular use case of "freeze delay", which is eventually looping your input https://www.youtube.com/watch?v=XVghai8leTI&ab_channel=EZBOT
Em qua., 3 de mar. de 2021 às 21:38, José de Abreu abreubacelar@gmail.com escreveu:
very nice videos! but i think i used the wrong name then, what i did was what max asked, when you switch off the delay, it just works as an array and the write pointer keeps frozen and only resumes writing when you switch it on again
I confess I was just kind of obsessed with the idea of providing a 'freeze' function a la MAX, cause since I started working on cyclone I was jealous they had it. Apart from jealousness and envyness I actually never needed or thought about.
Now that I keep thinking about this, I realize there's also the alternative of doing the other way around. That is, write into an array and use that as a delay line. Maybe not easily doable with vanilla, cause I guess [tabwrite~] won't easily loop when writing into the array, but there are externals for this.
In cyclone we have [record~] and [poke~] to write to arrays, plus [play~] to play them. Just keep writing into arrays in a loop and read also in a loop (but delayed). One can also use [tabread4~], why not? This is not all that straightforward, I know, but I don't think this hack with the delay line is pretty :)
By the way, I learned that in SuperCollider you have a Tap object that just plays from a regular buffer (i.e. an array) like that.
I have to confess I haven't fully figured it out yet how the code of [delread~]/[delwrite~] worksl, but it seems it's just like that, it keeps writing into a buffer in a loop...
Anyway, I'm now toying with the idea of implementing a delay without delread/write objects for fun.
I can also suggest objects from the ELSE library, like [tabwriter~] to record and [taplayer~] to play, or also [table~] driven by [ramp~]
And the idea is that you can easily stop writing into the arrays with these objects and continue from where you left off.
what do you think?
cheers
Em qui., 4 de mar. de 2021 às 01:33, Alexandre Torres Porres < porres@gmail.com> escreveu:
In cyclone we have [record~] and [poke~] to write to arrays, plus [play~] to play them.
Here's a shot with [record~] and [play~]. The [record~] object outputs its phase and that is useful for managing a delayed output by reading this buffer. It can also continue recording from where it stopped.
This sort of implements a delay, and I was taking a shot in keeping it playing from the same spot when you stop writing into the buffer. I haven't made this "freeze" and stop.
what do you think?
Em dom., 28 de fev. de 2021 às 16:20, Alexandre Torres Porres < porres@gmail.com> escreveu:
I'm thinking about creating a variant of delread/write~ for ELSE with this "freeze" functionality. But maybe we can request to add it to vanilla.
maybe this is best for the pd-dev list, but here I go.
In my design choice for a variation of delread/write, I think it could be given a unique delay name when a delay write object is not given a delay line argument. This name could then be sent via an outlet to a read object. This looks like how things work for MAX's tapin~/tapout~ and I confess I'm taking it as a model.
Now, big question, can I force an order of execution with such a connection? Would it have to be a signal connection only?
thanks
On 01.03.21 04:13, Alexandre Torres Porres wrote:
Em dom., 28 de fev. de 2021 às 16:20, Alexandre Torres Porres <porres@gmail.com mailto:porres@gmail.com> escreveu:
I'm thinking about creating a variant of delread/write~ for ELSE with this "freeze" functionality. But maybe we can request to add it to vanilla.
maybe this is best for the pd-dev list, but here I go.
In my design choice for a variation of delread/write, I think it could be given a unique delay name when a delay write object is not given a delay line argument. This name could then be sent via an outlet to a read object. This looks like how things work for MAX's tapin~/tapout~ and I confess I'm taking it as a model.
Now, big question, can I force an order of execution with such a connection? Would it have to be a signal connection only?
I think adding that freeze option to delay would be fantastic and even more so when it gets Pd's functionality en par with the Max/MSP counterparts.
What I also would like to see is a tabwrite~-like object that uses an array to write to, but each new sample gets pushed to the next index of the array when a new one is added.
m.
Em seg., 1 de mar. de 2021 às 16:51, Max abonnements@revolwear.com escreveu:
I think adding that freeze option to delay would be fantastic and even more so when it gets Pd's functionality en par with the Max/MSP counterparts.
I do like this option in Vanilla, I have to confess I haven't figured it out yet how to adapt the code to do that. I'd love to provide that before we could see this in Vanilla, but I got stuck.
I'm still thinking if I can force an order of execution with a control connection, but maybe as discussed in my other email, I'd need an API change so objects know about connections.
What I also would like to see is a tabwrite~-like object that uses an array to write to, but each new sample gets pushed to the next index of the array when a new one is added.
I'm also putting that into my list. I have else/tabwriter~, which could have that option.
Em ter., 2 de mar. de 2021 às 02:08, Alexandre Torres Porres < porres@gmail.com> escreveu:
I got stuck.
I made it! Freeze working now! I can include this in an update of ELSE soon, and also make a PR for vanilla now. As for the other design issues and questions, I guess I'll let it go and focus on this added functionality as the selling point.
It finally came to me that when I put tabwrite~ into an abstraction I can pause the array writing by stopping audio processing in that abstraction using switch~. It also can loop by writing into the table like into a ringbuffer. The other half of the issue is to also take account for the write pointer in the player. I'm using sig~ 1 into rpole~ 1 (Thanks José de Abreu) and using that in the deque reader. The accompanying dequread4~ uses that write head position as an offset to the table (modulo the table size).
it's vanilla
it may have stupid problems / errors, please let me know if you find any. There is an error in the Pd console no such table '' but that doesn't seem to affect the functionality and Pd can't trace that error.
On 02.03.21 18:51, Alexandre Torres Porres wrote:
Em ter., 2 de mar. de 2021 às 02:08, Alexandre Torres Porres <porres@gmail.com mailto:porres@gmail.com> escreveu:
I got stuck.
I made it! Freeze working now! I can include this in an update of ELSE soon, and also make a PR for vanilla now. As for the other design issues and questions, I guess I'll let it go and focus on this added functionality as the selling point.
One issue is that the 4 point interpolation isn't working where the table playback is wrapped. In an earlier version I had two arrays and was writing in both with a 50% offset, but that got ugly.
On 05.03.21 17:45, Max wrote:
It finally came to me that when I put tabwrite~ into an abstraction I can pause the array writing by stopping audio processing in that abstraction using switch~. It also can loop by writing into the table like into a ringbuffer. The other half of the issue is to also take account for the write pointer in the player. I'm using sig~ 1 into rpole~ 1 (Thanks José de Abreu) and using that in the deque reader. The accompanying dequread4~ uses that write head position as an offset to the table (modulo the table size).
it's vanilla
it may have stupid problems / errors, please let me know if you find any. There is an error in the Pd console no such table '' but that doesn't seem to affect the functionality and Pd can't trace that error.
On 02.03.21 18:51, Alexandre Torres Porres wrote:
Em ter., 2 de mar. de 2021 às 02:08, Alexandre Torres Porres <porres@gmail.com mailto:porres@gmail.com> escreveu:
I got stuck.
I made it! Freeze working now! I can include this in an update of ELSE soon, and also make a PR for vanilla now. As for the other design issues and questions, I guess I'll let it go and focus on this added functionality as the selling point.
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list
Might have fixed it.
On 05.03.21 21:10, Max wrote:
One issue is that the 4 point interpolation isn't working where the table playback is wrapped. In an earlier version I had two arrays and was writing in both with a 50% offset, but that got ugly.
On 05.03.21 17:45, Max wrote:
It finally came to me that when I put tabwrite~ into an abstraction I can pause the array writing by stopping audio processing in that abstraction using switch~. It also can loop by writing into the table like into a ringbuffer. The other half of the issue is to also take account for the write pointer in the player. I'm using sig~ 1 into rpole~ 1 (Thanks José de Abreu) and using that in the deque reader. The accompanying dequread4~ uses that write head position as an offset to the table (modulo the table size).
it's vanilla
it may have stupid problems / errors, please let me know if you find any. There is an error in the Pd console no such table '' but that doesn't seem to affect the functionality and Pd can't trace that error.
On 02.03.21 18:51, Alexandre Torres Porres wrote:
Em ter., 2 de mar. de 2021 às 02:08, Alexandre Torres Porres <porres@gmail.com mailto:porres@gmail.com> escreveu:
I got stuck.
I made it! Freeze working now! I can include this in an update of ELSE soon, and also make a PR for vanilla now. As for the other design issues and questions, I guess I'll let it go and focus on this added functionality as the selling point.
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list
Hi Max, I'm responding to an email from another thread, but I think it belongs here :)
On 05.03.21 17:45, Max wrote:
It finally came to me that when I put tabwrite~ into an abstraction I can pause the array writing by stopping audio processing in that abstraction using switch~. It also can loop by writing into the table like into a ringbuffer. The other half of the issue is to also take account for the write pointer in the player. I'm using sig~ 1 into rpole~ 1 (Thanks José de Abreu) and using that in the deque reader. The accompanying dequread4~ uses that write head position as an offset to the table (modulo the table size).
it's vanilla
it may have stupid problems / errors, please let me know if you find any. There is an error in the Pd console no such table '' but that doesn't seem to affect the functionality and Pd can't trace that error.
So, I've seen your last revision of the patch and I'm not sure I get how it is useful or why you need it like that. And now I'm really just curious and interested in the applications of this.
It's nice that it is all vanilla, but it is still very limited as I see it. You don't have sample accuracy for start writing and stopping or pause/continue.
And I see that the looping (or ring buffering) isn't perfect either because of this sample accuracy issue. You're analyzing to see if your signal counter goes over the array size but the resulting bang comes out after some samples, so... clicks.
Anyway, this approach of yours is quite similar to what I did here with objects from cyclone, have you checked it? Doesn't it do the same thing? Does it fail for your needs somehow?
I just made an update to the ELSE library (version beta 37) and now I can do the same with objects from ELSE, so I'm attaching it here.
Note I've also added a new [del~] object with a freeze option and also included that functionality in [ffdelay~], but I guess that's something not really appropriate for what you want, what do you say?
cheers
Em sex., 26 de fev. de 2021 às 10:03, Max abonnements@revolwear.com escreveu:
Hi list,
I'm looking for concepts like a queue or arrayDeque in Pd. Like a delay line which I can pause adding new elements into and it will act like an array until I decide to add more. At audio rate. Is there something simple that I have overlooked? What's the best strategy to implement this?
M.
On 14.03.21 21:56, Alexandre Torres Porres wrote:
Hi Max, I'm responding to an email from another thread, but I think it belongs here :)
Sorry for the delay. I only see one thread - a Gmail issue?
On 05.03.21 17:45, Max wrote:
It finally came to me that when I put tabwrite~ into an abstraction I can pause the array writing by stopping audio processing in that abstraction using switch~. It also can loop by writing into the table like into a ringbuffer. The other half of the issue is to also take account for the write pointer in the player. I'm using sig~ 1 into rpole~ 1 (Thanks José de Abreu) and using that in the deque reader. The accompanying dequread4~ uses that write head position as an offset to the table (modulo the table size).
it's vanilla
it may have stupid problems / errors, please let me know if you find any. There is an error in the Pd console no such table '' but that doesn't seem to affect the functionality and Pd can't trace that error.
So, I've seen your last revision of the patch and I'm not sure I get how it is useful or why you need it like that. And now I'm really just curious and interested in the applications of this.
I have a kind of a sampler which I control with a sensel morph (btw, I'm using the 14 bit MIDI mode of the sensel, not the sensel object, because the MIDI is rock solid and the object isn't). Anyway, the sampler records continuously the last ~7 seconds and as soon as i put a finger on the sensel I can mess with this buffer. If I let go, it continues to write into that buffer.
It's nice that it is all vanilla, but it is still very limited as I see it. You don't have sample accuracy for start writing and stopping or pause/continue.
I just need block accuracy for my application.
And I see that the looping (or ring buffering) isn't perfect either because of this sample accuracy issue. You're analyzing to see if your signal counter goes over the array size but the resulting bang comes out after some samples, so... clicks.
that may be, but irl i'm not too bothered by it because the whole thing has a glitchy aesthetic anyway, so that can stay.
Anyway, this approach of yours is quite similar to what I did here with objects from cyclone, have you checked it? Doesn't it do the same thing? Does it fail for your needs somehow?
I could not figure out how that patch works, which toggle is supposed to do what and I would have to read all the help files for all the unfamiliar cyclone objects to understand what is going on. It feels out of control for me, for convenience I rather use the patch I made myself because I still know what's going on there. I need to fully understand it to feel confident that I can fix it if a problem should arise. I think that's why many Pd users start to write their own abstractions rather than using someone else's (Pun not intended).
I just made an update to the ELSE library (version beta 37) and now I can do the same with objects from ELSE, so I'm attaching it here.
cool, but same as above applies there.
Note I've also added a new [del~] object with a freeze option and also included that functionality in [ffdelay~], but I guess that's something not really appropriate for what you want, what do you say?
I have a table based granular sampler so to speak - 10 fingers on the sensel = 10 grains playing. I would have to re write that to play from a delay line instead of a table. Probably possible, but I rather not touch that part which I'm already happy with :)
Thanks for your commitment Alex. Even though I can't use it right now it truly is appreciated!
Max
Am 21. März 2021 12:29:27 MEZ schrieb Max abonnements@revolwear.com:
Anyway, the sampler records continuously the last ~7 seconds and as soon as i put a finger on the sensel I can mess with this buffer. If I let go, it continues to write into that buffer.
so once you let go, you have to wait for another 7 seconds until the entire buffer is usable again?
mfg.hft.fsl IOhannes