-
jameslo
@mbbaker This is just my educated guess as someone who has written interrupt driven multitasking stuff in assembler during the Pleistocene era
.
Anytime you have independent processes that have to communicate, they have to do it through some kind of buffer because the time slices that each process will receive are not under the programmer's control. Compare with cooperative multitasking using co-routines. So if 2 or more Pd processes have to stream audio between them and not miss a real-time deadline, there has to be a fifo buffer between them.
How big a buffer is required? That depends on each OS and differs from moment to moment depending on what other processes are competing for CPU time. Some processes may lurch forward in execution while others wait to be scheduled. So it can't be predetermined, and therefore it's a configurable option.
In my one project that used [Pd~}, -fifo 1 worked without issue. The lower the number, the lower the roundtrip latency between processes, so I guess that means the fifo size is a tradeoff between latency and reliability.
-
jameslo
@polyplexmescalia Have you seen this explanation? https://puredata.info/
Scroll down to the section entitled "Main Pd Flavours" -
jameslo
@porres said:
I read the first messages and I couldn't understand at all what you people are discussing, or the idea about this complicated patch, sorry
OK, here's a restatement of the problem but presented as a patch. See if you can complete the two subpatches in such a way that it passes the exact copy test on the right. phasor snapshot problem statement.pd
I think you will discover that there's no snapshot or vsnapshot that is sufficient to make the right phasor output the exact same sequence as captured on the left. That said, there were other solutions proposed above that had a different structure, so it's not impossible, I'm just claiming it's impossible without going to 64 bit using this structure. -
jameslo
@whale-av Interesting idea, but I suppose another limitation is that you lose the slave's state when you exit Pd. But it suggests another way: count the number of blocks from when dsp gets turned on, and then run a fresh phasor in fast forward that same amount of time to get back to that state. It's more complicated than what I need, but it doesn't have the tiny timing disruption that my compromise solution has.
-
jameslo
@FFW The idea of trading state-uncertainty for time-uncertainty sounds so cool that I desperately want it to be real
! But to "only allow the phasor to stop at specific states" suffers from the same issue as I had, no? How can you know what state the phasor is in? I'm arguing that knowing its inputs and output are not enough, even if you could capture them at audio rate timing, because phasors accumulate in double precision internally.
-
jameslo
@lacuna said
And single precision is not enough for you?
I'm not sure what you're asking. I'm saying that doubles are required to capture [phasor~]'s state, so in that sense singles are not enough. But otherwise they are. And singles are OK for everything in my patch as long as I accept that I have to disrupt the double accumulation whenever I snapshot.
Do you know what is not working in Pd64?
In my real patch? No. But I should've said earlier that WRT state saving, things were working well enough last week to stop working on this problem (and finally switch back to making music). I started this topic just to report on the most interesting thing I learned during the 2 weeks I spent debugging my poor patch
Did you think about other ways, like rec/playback?
Yes, that's what this is for, to record snapshots of my chaotic patch to REAPER as sysex so that I can return to the exact same state and fiddle with things to make them sound better. I had to capture the values of 32 floats--20 were UI controls but 12 were the states of things like phasors, sampleholds, rzero-revs, and arrays used for feedback. I think we may be thinking slightly differently about recording, so let me tell you how I use it. My patch is kind of unpredictable, and I'm just randomizing its UI controls on a bang to see what I get. Each time I randomize them, I take one of these snapshots. When I'm listening back later, I might want one of the snapshots to be longer, so I just go to the sysex track and add time. Or I might go back and fiddle with the UI a little, then take another snapshot. The sound associated with each snapshot is not steady-state--it might do something surprising if you let it run long enough--so that's why recording the sound is not enough. But it's also true that you don't need any more data than those 32 floats to get back to where you were, no matter if you're only interested in the next second or the next 3 hours.
RE ppphasor-repeat, Pd is complaining about non-existent arrays. If you feel like fixing that, then you might also want to add something that tests whether the repeat is a sample-for-sample copy of the original. That's what I was starting to add before I noticed the error messages.
-
jameslo
@lacuna It's interesting that you see this in terms of freq vs amplitude accuracy. That point of view hadn't occurred to me. That said, it appears that my issue is about neither one--only repeatability!
-
-
jameslo
@lacuna said:
Don't know about phasor's right inlet, but I guess for more precision on the outside of objects we'd have to use 'Pd double precision'.
Yes, I confirmed that my test patch runs without issue under Pd64. Unfortunately, my real patch doesn't
Also remember @ddw_music different approach than [phasor~]:
I think that "different approach" is a different issue--I'm not multipying its output to index into a large table. I'm just using it as an oscillator/LFO. Are you suggesting that there's a way to build an oscillator with [rpole~] that is as frequency-accurate as [phasor~] but without the single vs double precision issue?
On one sample late: It is [snapshot~] who is early, not [phasor~]:
...
I would call this a bug of [snapshot~] !%§$*(I don't understand your conclusion about the timing of [snapshot~]. Here's how I would analyze your demonstration patch: the top bang is processed in-between audio blocks. Therefore, [tabplay~] and [fexpr~] run in the following audio block. [snapshot~] is different though, because it's a bridge between control rate and audio rate--like bang, it also runs between audio blocks. Therefore, the best it can do (without having to predict the future) is to return the last sample of the previous audio block. So it's not surprising for [fexpr~] to have to reach back into the previous audio block to get the same value as [snapshot~]. If [snapshot~] were to return the first sample of the following audio block, it couldn't pass that value to control rate code until that audio block's processing is complete. Do you see my point?
Also, I'm not saying [phasor~] is early, I'm just saying its right inlet isn't a mechanism for restoring its state. It's just for what the documentation says it's for: to reset its phase to a given value.
-
jameslo
Suppose you want to capture the state of a [phasor~] in order to return to it later, i.e. you want it to output the exact same sequence of samples as it did from the moment you captured its state. As a first attempt, you might [snapshot~] the [phasor~]'s output and then send that value to the [phasor~]'s right inlet sometime later to restore it. Of course you also want to capture the state of its frequency inlet (and record it if it's changing). But there are two subtleties to consider. Firstly, the value you write to the right inlet is the next value that the [phasor~] will output, but when you [snapshot~]ed it, the next value it output was a little greater, greater by the amount of the last frequency divided by the current sample rate. So really, this greater value (call it "snap++") is the one you should be writing to the right inlet.
The second subtlety has to do with the limits of Pd's single precision floats. Internally, [phasor~] is accumulating into a double precision float, so in a way, the right inlet overwrites the state of the phasor with something that can only approximate its state. The only solution I could find is to immediately write snap++ to the right inlet of the running [phasor~], so that the current and all future runs output the exact same sequence of samples. This might not be acceptable in your application if you are reliant on [phasor~]'s double precision accumulation because you'd be disrupting it in exchange for repeatability.
Here's a test patch that demonstrates the issue:
phasor snapshot restore test.pd