In my test patch below, the cascaded subpatches force a delwrite~ into a 1 ms delay line to happen before a 0.02 ms delread~. The undelayed signal appears on the right, and the delayed signal on the left. Note that the snapshots are 56 samples apart, or 1.27 ms. I expected them to be approximately 4 samples apart.
If I simply delete the block~ object, I get snapshots 1 sample apart, which is what I would expect. With the block~ object in effect, increasing the delread~ delay does not produce a proportional increase the interval between snapshots. If I substitute the subpatches with a 1 sample delay using [cyclone/delay~ 1 1], the upsampled version gives snapshots that reflect the effective sample rate correctly. May I conclude that delread~ is broken under upsampling?
-
delread~ broken under upsampling?
-
@jameslo The minimum delay for [delwrite~] to [delread~] is the block size, and [block~] in the parent window is applied to sub-patches as well.
If you put [delwrite~] and [delread~] in the same sub-patch and put a [block~ 1] inside..... does that help.?
David. -
I don't think that's necessarily true, that the minimum delay from delwrite~/delread~ is 1 block. I'm getting a 1 sample delay (when I delete the block~ object) because I'm enforcing a delwrite~ before a delread~. I learned that write-before-read technique from an example in PD help: help->Browser....->Pure Data/->3.audio.examples/->G05.execution.order.pd.
BTW, I tested [fexpr~ $x1[-1]] and that also works fine as a 1 sample delay in both the normal and upsampled environments. Not sure how much more expensive it is than delwrite~/delread~.
-
I tried making your patch and it worked if the block size was lower than 256
edit: it's because your write buffer length is less than 256 samples. Increase past 1 ms and it works.
not sure why it would work with block sizes of 64 & 128 but not with 256 though.. and it seems like it should work anyways..edit2: For those curious (I was) after digging around what happens is that it is possible for the writer to write over its starting point in the buffer before the reader has a chance to read those values if the buffer size < the block size. Because the "real" delay time (that is, the starting read point in the circular buffer) is supposed to be < the write buffer size but is also supposed to be >= the block size, the delay is set to the buffer size so when it reads the buffer it starts at the buffer size and reads the buffer circularly until the block finishes.
In this specific case, because 1 ms is 176 samples, pd rounds the write buffer size up to 240 (for some reason it adds 64 samples). (And snapshot~ takes the last sample in a block) -
Thanks, increasing the buffer size addressed my issue. I'm still not clear why it works with the default 64 sample block size though, since a 1 ms buffer is smaller than the block size in that case too. And I'm not following your explanation, so I downloaded the source code to peek inside. Is the delay buffer managed in d_delay.c?
Any preference regarding delwrite~/delread~ vs fexpr~ $x1[-1] for a 1 sample delay?
-
yeah, here's some talk about DEFDELVS "Pd internally adds 64 samples to
the delay time you specify for [delwrite~], so the user will think that buffer
size = max. delay time."
This adds 64 to the given write buffer size. At 44100 the given size in samples is 44 and then 108 after DEFDELVS.
(in sigdelwrite_updatesr called from the dsp methods)I don't really know how fexpr~ works or how efficient it is, but it would use less memory probably.. I usually use delwrite~/delread~ but idk why