Quality granular processing in pd
OK, here's a basic live input granulator, no really fancy features, just pitch shifting.
The handling of grain playback rate in the one-grain abstraction is a neat trick I had worked out some time ago. For example, if you want to play the grain an octave higher (2x speed), then you need to span 2 * dur ms of audio in dur ms of time. You can do that by modulating the delay time as a straight line, from dur ms to 0 ms -- adding dur to the delay time at the beginning adds that many ms to the amount of audio being used: dur * (rate-1). Or, to play slower, start with a shorter delay and go toward a longer delay, and the boundary is again dur * (rate-1). If rate = 1, then the delay time goes from 0 to 0 = no change = normal speed. That might look a bit funky in the patch you can try it with different transposition intervals, which will show that it's correct.
For sound file processing, replace the delay line with a soundfiler-filled array, and use tabread4~ for the audio source (and the line~ driving it will have to be different too).
IMO granular processing is 99% refinement and more advanced modulation of these basic parameters, which you should be able to tailor to your needs. I think the pitch shifting is more-or-less smooth here, though I'm not sure it matches your comparison plugins -- this is 66.6667 grains per second, with 4x overlap.
one-delay-grain.pd
live-granular.pd
hjh
Waveguide/Karplus strong delay time problem
Hello, to put you into context I'm working on a waveguide-style physical modeling synth in PlugData (basically the same as Pure Data), and I'm running into an issue where my delay line won't produce high-pitched notes correctly. I'm using a [delwrite~] and [vd~] or [delread4~] combo, with the delay time calculated from frequency using [expr~ 1000 / $v1], where $v1 is the pitch in Hz (converted from MIDI with [mtof]). The delay time is in milliseconds.
The patch works fine for low and mid frequencies, but when I try to play higher notes (especially MIDI note 100 and up), the pitch output seems stuck. it just keeps playing the same note, i doesn't happen with low notes though.
I've already tried the usual fixes. I made sure the [delwrite~] buffer is small (100 and even around 5–10 ms), verified that the delay time input is a smooth signal ([sig~]), and tried both [vd~] and [delread4~] for interpolation, nothing works.
Out of curiosity, I tested the patch at a global sample rate of 96,000 Hz. That actually allowed the waveguide to reach the correct higher notes, but the patch became very laggy and glitchy, and the CPU usage was noticeably worse (as expected)
At this point, I'm wondering if there's a clean way to make a delay line in Pure Data (or PlugData) that supports very short delay times for high pitches (e.g. MIDI 120+), without needing to oversample the entire patch or push the sample rate to 96kHz. Is there a known solution for sub-millisecond delay accuracy that works well in Pd? Would a local oversampling strategy using [block~] be effective here? Any guidance or best practices would be really appreciated 

ofxOfeliaExtended
These are the contents of the .zip file you mention:
abs/ CHANGES.txt examples/ LICENSE.txt ofelia-object-help.lua ofelia_textwindow.tcl opencv_core4100.dll opencv_features2d4100.dll opencv_imgproc4100.dll README.md
assimp-vc142-mt.dll classesAndGlobalFunctions.txt libxml2.dll ofelia.dll ofelia-object-help.pd opencv_calib3d4100.dll opencv_dnn4100.dll opencv_flann4100.dll opencv_objdetect4100.dll stable-diffusion.dll
Are these supposed to be located in the ofeliaExtendedLib directory? Because, all there is in there, is already in the directory of the ofelia.pd_linux Pd external directory too.
Avoid clicks controlling Time Delay with MIDI Knob
@Zooquest You will hear clicks because there will be jumps between samples.... if the playback was at a sample level of 0 and you change the delay time to a point where the level is 1 then the click will be loud.
You will hear "steps" as the playback point is probably being changed repeatedly by the ctrl messages.
You could experiment with a [lop~] filter in the delayed sound output, with a high value e.g... [lop~ 5000] but you will lose some high frequencies in the echo.
That might sound natural though, like an old tape echo, but you will probably still hear the clicks a little.
Or you could "duck" the echoes by not changing the delay time immediately, reducing the echo volume to zero in say 3msecs using using [vline~] and not bringing the echo volume back up to 1 (in, say, 3msecs again) until you have NOT received a ctrl message to change the delay time...... for again 3msecs.
The last part of that would need a [delay 3] using the property that any new bang arriving at its inlet will cancel the previously scheduled bang.
You would need to duck the FB signal as well though, and all that that might sound worse than the [lop~].
I cannot remember well...... but this "sampler_1.pd" might contain elements useful to demonstrate "ducking" https://forum.pdpatchrepo.info/topic/13641/best-way-to-avoid-clicks-tabread4/12
Or do a crossfade between separate delays once the incoming control messages have stopped..... https://forum.pdpatchrepo.info/topic/12357/smooth-delay-line-change-without-artifacts ..... as you can then avoid the "duck"ing effect.
David.
Karplus strong and strange issues with fexpr~
@reubenm I never care about computational expense until it's a problem, and even then it sometimes generates some cool stuttering that I would never have thought of. But if that fexpr~ way of doing things speaks to you, then maybe you should look into supercollider
And I'm not trying to be a jerk because as a former java/c# programmer I'd probably prefer it!
Edit: Ouch! I think I'm confused about the delay line and forced order of execution. In KS you're feeding back the output of the delay line into the input, so either you have to have the delay line read upstream of the write (and so you have a min 1 block delay) or you have to send the delay line read signal back up to the delay line write (which also incurs a 1 block delay). So either way I think you have to reduce the block size to get frequencies above 689hz.
count~ pause option?
@KMETE said:
edit: and my reason is that if I want to do comparison of two numbers - lets say if the timer that s running is larger then constant number - if the timer will not output the numbers constantly I might miss this logic...
What you're talking about is a timeout situation -- checking whether something did or didn't happen within x amount of time.
In the normal case, in Pd, you can do a timeout like this (no [metro], no constant polling):

Here, I'm using the word "start" and "stop," but they can be any messages being generated for any reason.
-
If the user hits only "start," then the [delay] time expires, [delay] generates a bang, and you know that the elapsed time >= threshold.
-
If the user hits "start" and then "stop" within the time limit, then 1/ you have the trigger from the user and 2/ the [delay] gets canceled (no erroneous timeout message).
When you're talking about a timer that can pause, that complicates it a bit (because [delay] wouldn't know about the pause).
But, to be honest, based on your requirement from the other thread -- when audio playback pauses (because of user action or the 30-second(?) timeout), you're always resetting the timer. When the timer goes back to 0, then pause is irrelevant. So I kinda wonder if the original question in this post stems from an unclear requirement rather than an actual need (though it is a kinda cool abstraction, and I'll add it to my library later).
After all, if you only want to stop checking for the timeout based on user pause, you can just stop banging the [timer] at that point... then, no check, no false timeout, and no need to over-engineer. Or using the [delay] approach, just "stop" the delay.

So there's a polling timeout that is aware of paused status, without using a special pausable timer. So this idea that you have to keep banging the timing object and the timing object should be responsible for not advancing when paused is perhaps overcomplicated.
edit2: I could bang the poll message every 10ms using metro but then we again have an issue on cpu?
[timer] shouldn't use much CPU... it's probably fine, and if it's more comfortable for you, feel free to go that way. I'm just pointing out that brute force is not the only way here.
hjh
PlugData / Camomile "position" messages: What are these numbers?
@whale-av said:
@ddw_music Yes.... buffer.
Maybe some DAWs have implemented a tempo message since then?
Tempo must be available, since plug-ins have been doing e.g. tempo-synced delays for at least a decade already.
(In fact, it is available via Camomile: [route tempo position].)
Anyway... I've been considering solutions, and I think I can do this.
- Set some threshold close to the beat, but before the beat, say x.9 beats.
- For the first tick past the threshold, get "time to next beat" = roundUp(pos) - pos = int(pos + 0.99999999) - pos.
- [delay] by this many beats ([delay] and the tick-scheduler will have been fed "tempo x permin" messages all along).
- Then issue the tick message to the scheduler, in terms of whole beats (where the time-slice duration is always 1.0).
At constant tempo, I'd expect this to be sub-ms accurate.
If the tempo is changing, especially a large, sudden change, then there might be some overlaps or gaps. But [delay] correctly handles mid-delay tempo changes, so I'd expect these to be extremely small, probably undetectable to the ear.

Half a beat at 60 bpm + half a beat at 120 bpm does indeed = 750 ms -- so the delay object is definitively updating tempo in the middle of a wait period.
I'll have to build it out and I don't have time right now, but I don't see an obvious downside.
hjh
phase index of an oscillator and 1 sample delay in pd?
delread~ is not a sample delay it is a tapping buffer.
a tapping delay does not delay "the samples", it delays their content.
plus its minimum delay time is the vectorsize.
i think in pd you would replace [delay~ 1] with [fexpr~]... something like x = x1, no idea about the correct synthax.
s~/r~ throw~/catch~ latency and object creation order
For a topic on matrix mixers by @lacuna I created a patch with audio paths that included a s~/r~ hop as well as a throw~/catch~ hop, fully expecting each hop to contribute a 1 block delay. To my surprise, there was no delay. It reminded me of another topic where @seb-harmonik.ar had investigated how object creation order affects the tilde object sort order, which in turn determines whether there is a 1 block delay or not. Object creation order even appears to affect the minimum delay you can get with a delay line. So I decided to do a deep dive into a small example to try to understand it.
Here's my test patch: s~r~NoLatency.pd
The s~/r~ hop produces either a 64 sample delay, or none at all, depending on the order that the objects are created. Here's an example that combines both: s~r~DifferingLatencies.pd
That's pretty kooky! On the one hand, it's probably good practice to avoid invisible properties like object creation order to get a particular delay, just as one should avoid using control connection creation order to get a particular execution order and use triggers instead. On the other hand, if you're not considering object creation order, you can't know what delay you will get without measuring it because there's no explicit sort order control. Well...technically there is one and it's described in G05.execution.order, but it defeats the purpose of having a non-local signal connection because it requires a local signal connection. Freeze dried water: just add water.
To reduce the number of cases I had to test, I grouped the objects into 4 subsets and permuted their creation orders:
The order labeled in the diagram has no latency and is one that I just stumbled on, but I wanted to know what part of it is significant, so I tested all 24 permuations. (Methodology note: you can see the object creation order if you open the .pd file in a text editor. The lines that begin with "#X obj" list the objects in the order they were created.)

It appears that any time the phasor group is created before the r~, there is latency. Nothing else matters. Why would that be? To test if it's the whole audio chain feeding s~ that has to be created before, or only certain objects in that group, I took the first permutation with latency and cut/pasted [phasor~ 1] and [*~ 44100] in turn to push the object's creation order to the end. Only pushing [phasor~ 1] creation to the end made the delay go away, so maybe it's because that object is the head of the audio chain?
I also tested a few of these permutations using throw~/catch~ and got the same results. And I looked to see if connection creation order mattered but I couldn't find one that did and gave up after a while because there were too many cases to test.
So here's what I think is going on. Both [r~ next] and [phasor~ 1] are the heads of their respective locally connected audio chains which join at [-~]. Pd has to decide which chain to process first, and I assume that it has to choose the [phasor~ 1] chain in order for the data buffered by [s~ next] to be immediately available to [r~ next]. But why it should choose the [phasor~ 1] chain to go first if it's head is created later seems arbitrary to me. Can anyone confirm these observations and conjectures? Is this behavior documented anywhere? Can I count on this behavior moving forward? If so, what does good coding practice look like, when we want the delay and also when we don't?
Signal-rate circular buffer?
@ddw_music I think whichever's easiest depends on if you're (over)writing the circular buffer continuously or not. If you are then [vd~]/[delread4~] with some kind of [samphold~] & [phasor~] combo to keep playing the same grain might be easier than managing your own but maybe the case is specific enough that it's worth making your own delay line that can pause writing.
but then how does it wrap around if you don't pause before the end? AFAICS there is no reliable way to make it do that.
you would have to make sure the array is a multiple of 64 samples and schedule the [tabwrite~] to start the next pass using message-rate (probably [delay]). granted, it might be far messier than the [poke~] object solution. But that would be the vanilla way to do it, and it may be more efficient since you don't have to provide your own [phasor~] (and things may be vectorized better by the compiler).
going that route might be more complicated in coordinating the exact delay time when stopping recording anyways though. (bc signal/message rate interaction).
But the thing about pausing writing is that when you move off of that grain the next time frame won't be available yet, the stuff in the array will be behind by however long you were playing that grain for, so you would have to wait for the entire array to fill up again in order to guarantee consistency in delay time.
What we really need is an object like max/msp's [stutter~] (which copies from a delay-line to another play buffer) with interpolation. I've been meaning to get to making a near-clone..
it may be possible to somehow do the same thing that [stutter~] does with complicated logic, but keeping track of what needs to be played from the delay line vs. what's already been copied to the play buffer (and therefore which should be read from for any given sample) would be even more of a headache in pd than it would be in c imo.



