PD's scheduler, timing, control-rate, audio-rate, block-size, (sub)sample accuracy,
Hello,
this is going to be a long one.
After years of using PD, I am still confused about its' timing and schedueling.
I have collected many snippets from here and there about this topic,
-wich all together are really confusing to me.
*I think it is very important to understand how timing works in detail for low-level programming … *
(For example the number of heavy jittering sequencers in hard and software make me wonder what sequencers are made actually for ? lol )
This is a collection of my findings regarding this topic, a bit messy and with confused questions.
I hope we can shed some light on this.
- a)
The first time, I had issues with the PD-scheduler vs. how I thought my patch should work is described here:
https://forum.pdpatchrepo.info/topic/11615/bang-bug-when-block-1-1-1-bang-on-every-sample
The answers where:
„
[...] it's just that messages actually only process every 64 samples at the least. You can get a bang every sample with [metro 1 1 samp] but it should be noted that most pd message objects only interact with each other at 64-sample boundaries, there are some that use the elapsed logical time to get times in between though (like vsnapshot~)
also this seems like a very inefficient way to do per-sample processing..
https://github.com/sebshader/shadylib http://www.openprocessing.org/user/29118
seb-harmonik.ar posted about a year ago , last edited by seb-harmonik.ar about a year ago
• 1
whale-av
@lacuna An excellent simple explanation from @seb-harmonik.ar.
Chapter 2.5 onwards for more info....... http://puredata.info/docs/manuals/pd/x2.htm
David.
“
There is written: http://puredata.info/docs/manuals/pd/x2.htm
„2.5. scheduling
Pd uses 64-bit floating point numbers to represent time, providing sample accuracy and essentially never overflowing. Time appears to the user in milliseconds.
2.5.1. audio and messages
Audio and message processing are interleaved in Pd. Audio processing is scheduled every 64 samples at Pd's sample rate; at 44100 Hz. this gives a period of 1.45 milliseconds. You may turn DSP computation on and off by sending the "pd" object the messages "dsp 1" and "dsp 0."
In the intervals between, delays might time out or external conditions might arise (incoming MIDI, mouse clicks, or whatnot). These may cause a cascade of depth-first message passing; each such message cascade is completely run out before the next message or DSP tick is computed. Messages are never passed to objects during a DSP tick; the ticks are atomic and parameter changes sent to different objects in any given message cascade take effect simultaneously.
In the middle of a message cascade you may schedule another one at a delay of zero. This delayed cascade happens after the present cascade has finished, but at the same logical time.
2.5.2. computation load
The Pd scheduler maintains a (user-specified) lead on its computations; that is, it tries to keep ahead of real time by a small amount in order to be able to absorb unpredictable, momentary increases in computation time. This is specified using the "audiobuffer" or "frags" command line flags (see getting Pd to run ).
If Pd gets late with respect to real time, gaps (either occasional or frequent) will appear in both the input and output audio streams. On the other hand, disk strewaming objects will work correctly, so that you may use Pd as a batch program with soundfile input and/or output. The "-nogui" and "-send" startup flags are provided to aid in doing this.
Pd's "realtime" computations compete for CPU time with its own GUI, which runs as a separate process. A flow control mechanism will be provided someday to prevent this from causing trouble, but it is in any case wise to avoid having too much drawing going on while Pd is trying to make sound. If a subwindow is closed, Pd suspends sending the GUI update messages for it; but not so for miniaturized windows as of version 0.32. You should really close them when you aren't using them.
2.5.3. determinism
All message cascades that are scheduled (via "delay" and its relatives) to happen before a given audio tick will happen as scheduled regardless of whether Pd as a whole is running on time; in other words, calculation is never reordered for any real-time considerations. This is done in order to make Pd's operation deterministic.
If a message cascade is started by an external event, a time tag is given it. These time tags are guaranteed to be consistent with the times at which timeouts are scheduled and DSP ticks are computed; i.e., time never decreases. (However, either Pd or a hardware driver may lie about the physical time an input arrives; this depends on the operating system.) "Timer" objects which meaure time intervals measure them in terms of the logical time stamps of the message cascades, so that timing a "delay" object always gives exactly the theoretical value. (There is, however, a "realtime" object that measures real time, with nondeterministic results.)
If two message cascades are scheduled for the same logical time, they are carried out in the order they were scheduled.
“
[block~ smaller then 64] doesn't change the interval of message-control-domain-calculation?,
Only the size of the audio-samples calculated at once is decreased?
Is this the reason [block~] should always be … 128 64 32 16 8 4 2 1, nothing inbetween, because else it would mess with the calculation every 64 samples?
How do I know which messages are handeled inbetween smaller blocksizes the 64 and which are not?
How does [vline~] execute?
Does it calculate between sample 64 and 65 a ramp of samples with a delay beforehand, calculated in samples, too - running like a "stupid array" in audio-rate?
While sample 1-64 are running, PD does audio only?
[metro 1 1 samp]
How could I have known that? The helpfile doesn't mention this. EDIT: yes, it does.
(Offtopic: actually the whole forum is full of pd-vocabular-questions)
How is this calculation being done?
But you can „use“ the metro counts every 64 samples only, don't you?
Is the timing of [metro] exact? Will the milliseconds dialed in be on point or jittering with the 64 samples interval?
Even if it is exact the upcoming calculation will happen in that 64 sample frame!?
- b )
There are [phasor~], [vphasor~] and [vphasor2~] … and [vsamphold~]
https://forum.pdpatchrepo.info/topic/10192/vphasor-and-vphasor2-subsample-accurate-phasors
“Ive been getting back into Pd lately and have been messing around with some granular stuff. A few years ago I posted a [vphasor.mmb~] abstraction that made the phase reset of [phasor~] sample-accurate using vanilla objects. Unfortunately, I'm finding that with pitch-synchronous granular synthesis, sample accuracy isn't accurate enough. There's still a little jitter that causes a little bit of noise. So I went ahead and made an external to fix this issue, and I know a lot of people have wanted this so I thought I'd share.
[vphasor~] acts just like [phasor~], except the phase resets with subsample accuracy at the moment the message is sent. I think it's about as accurate as Pd will allow, though I don't pretend to be an expert C programmer or know Pd's api that well. But it seems to be about as accurate as [vline~]. (Actually, I've found that [vline~] starts its ramp a sample early, which is some unexpected behavior.)
[…]
“
- c)
Later I discovered that PD has jittery Midi because it doesn't handle Midi at a higher priority then everything else (GUI, OSC, message-domain ect.)
EDIT:
Tryed roundtrip-midi-messages with -nogui flag:
still some jitter.
Didn't try -nosleep flag yet (see below)
- d)
So I looked into the sources of PD:
scheduler with m_mainloop()
https://github.com/pure-data/pure-data/blob/master/src/m_sched.c
And found this paper
Scheduler explained (in German):
https://iaem.at/kurse/ss19/iaa/pdscheduler.pdf/view
wich explains the interleaving of control and audio domain as in the text of @seb-harmonik.ar with some drawings
plus the distinction between the two (control vs audio / realtime vs logical time / xruns vs burst batch processing).
And the "timestamping objects" listed below.
And the mainloop:
Loop
- messages (var.duration)
- dsp (rel.const.duration)
- sleep
With
[block~ 1 1 1]
calculations in the control-domain are done between every sample? But there is still a 64 sample interval somehow?
Why is [block~ 1 1 1] more expensive? The amount of data is the same!? Is this the overhead which makes the difference? Calling up operations ect.?
Timing-relevant objects
from iemlib:
[...]
iem_blocksize~ blocksize of a window in samples
iem_samplerate~ samplerate of a window in Hertz
------------------ t3~ - time-tagged-trigger --------------------
-- inputmessages allow a sample-accurate access to signalshape --
t3_sig~ time tagged trigger sig~
t3_line~ time tagged trigger line~
--------------- t3 - time-tagged-trigger ---------------------
----------- a time-tag is prepended to each message -----------
----- so these objects allow a sample-accurate access to ------
---------- the signal-objects t3_sig~ and t3_line~ ------------
t3_bpe time tagged trigger break point envelope
t3_delay time tagged trigger delay
t3_metro time tagged trigger metronom
t3_timer time tagged trigger timer
[...]
What are different use-cases of [line~] [vline~] and [t3_line~]?
And of [phasor~] [vphasor~] and [vphasor2~]?
When should I use [block~ 1 1 1] and when shouldn't I?
[line~] starts at block boundaries defined with [block~] and ends in exact timing?
[vline~] starts the line within the block?
and [t3_line~]???? Are they some kind of interrupt? Shortcutting within sheduling???
- c) again)
https://forum.pdpatchrepo.info/topic/1114/smooth-midi-clock-jitter/2
I read this in the html help for Pd:
„
MIDI and sleepgrain
In Linux, if you ask for "pd -midioutdev 1" for instance, you get /dev/midi0 or /dev/midi00 (or even /dev/midi). "-midioutdev 45" would be /dev/midi44. In NT, device number 0 is the "MIDI mapper", which is the default MIDI device you selected from the control panel; counting from one, the device numbers are card numbers as listed by "pd -listdev."
The "sleepgrain" controls how long (in milliseconds) Pd sleeps between periods of computation. This is normally the audio buffer divided by 4, but no less than 0.1 and no more than 5. On most OSes, ingoing and outgoing MIDI is quantized to this value, so if you care about MIDI timing, reduce this to 1 or less.
„
Why is there the „sleep-time“ of PD? For energy-saving??????
This seems to slow down the whole process-chain?
Can I control this with a startup flag or from withing PD? Or only in the sources?
There is a startup-flag for loading a different scheduler, wich is not documented how to use.
- e)
[pd~] helpfile says:
ATTENTION: DSP must be running in this process for the sub-process to run. This is because its clock is slaved to audio I/O it gets from us!
Doesn't [pd~] work within a Camomile plugin!?
How are things scheduled in Camomile? How is the communication with the DAW handled?
- f)
and slightly off-topic:
There is a batch mode:
https://forum.pdpatchrepo.info/topic/11776/sigmund-fiddle-or-helmholtz-faster-than-realtime/9
EDIT:
- g)
I didn't look into it, but there is:
https://grrrr.org/research/software/
clk – Syncable clocking objects for Pure Data and Max
This library implements a number of objects for highly precise and persistently stable timing, e.g. for the control of long-lasting sound installations or other complex time-related processes.
Sorry for the mess!
Could you please help me to sort things a bit? Mabye some real-world examples would help, too.
Problem with running different Sample rates in different instances using [Pd~]
Hi all,
I'm trying to run different instances of my main patch using the [pd~] object using 2 different sample rates.
Main patch runs at 48khz:
1st) [pd~ -ninsig 1 -noutsig 1 -sr 48000]
2nd) [pd~ -ninsig 1 -noutsig 1 -sr 12000] ---> this runs at 48 kHz
Unfortunately the sample rate of the main patch that contains the 2 [pd~] objects as shown above affect the sample rate of the sub instances.
So if my main patch containing the 2 [pd~] is running at 48kHz the 2 sub instances run at 48kHz overriding the one set to work at 12kHz and vice versa if the main patch runs at 12kHz then the sub instance that is set to run at 48kHz runs at 12kHz.
Main patch runs at 48khz:
1st) [pd~ -ninsig 1 -noutsig 1 -sr 48000]
2nd) [pd~ -ninsig 1 -noutsig 1 -sr 12000] ---> this runs at 48 kHz
Main patch runs at 12kHz
1st) [pd~ -ninsig 1 -noutsig 1 -sr 48000] ---> this runs at 12 kHz
2nd) [pd~ -ninsig 1 -noutsig 1 -sr 12000]
do you have any idea how I can get the 2 instances to run at different samplerate~ ?
Thank you in advance!
*[list item](Samplerate[Pd~]pd.pd link url)
Problem installing purr data on Pop_os! ( Ubuntu-based )
As a sidenote, when I usually have this problem (installing a deb I got off the internet) I can solve it 3 simple ways:
The simple method
double-click on the package file, and there is a little widget that comes up and lets you install it (and goes and finds the deps for you.)
The older, non-GUI method
sudo dpkg -i FILE.deb
# there will be errors
sudo apt-get -f install
This will grab all the deps (if they are available) and fix future apt errors.
The modern non-GUI method
You can also use the apt
wrapper to do both steps:
sudo apt install ./FILE.deb
In most cases this works for things that are made for ubuntu, on Pop!OS, but in this case I get some errors (probly due to the version hard-coding):
sudo apt install ./pd-l2ork-2.9.0-20190416-rev.2b3f27c-x86_64.deb
[sudo] password for konsumer:
Reading package lists... Done
Building dependency tree
Reading state information... Done
Note, selecting 'pd-l2ork' instead of './pd-l2ork-2.9.0-20190416-rev.2b3f27c-x86_64.deb'
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:
The following packages have unmet dependencies:
pd-l2ork : Depends: libgsl2 but it is not installable
Depends: libpng12-0 (>= 1.2.13-4) but it is not installable
Recommends: tap-plugins but it is not going to be installed
Recommends: ladspa-foo-plugins but it is not going to be installed
Recommends: invada-studio-plugins-ladspa but it is not going to be installed
Recommends: blepvco but it is not going to be installed
Recommends: swh-plugins but it is not going to be installed
Recommends: mcp-plugins but it is not going to be installed
Recommends: cmt but it is not going to be installed
Recommends: blop but it is not going to be installed
Recommends: slv2-jack but it is not installable
Recommends: omins but it is not going to be installed
Recommends: ubuntustudio-audio-plugins but it is not going to be installed
Recommends: rev-plugins but it is not going to be installed
Recommends: dssi-utils but it is not going to be installed
Recommends: vco-plugins but it is not going to be installed
Recommends: wah-plugins but it is not going to be installed
Recommends: fil-plugins but it is not going to be installed
Recommends: mda-lv2 but it is not going to be installed
E: Unable to correct problems, you have held broken packages.
installing PD-extended onto the raspberry pi 3
Hello everyone!
I following the installing instructions for Pd extended for Raspberry Pi
and when I run this command:
$ sudo dpkg -i Pd-0.43.3-extended-20121004.deb
I keep getting this error:
Selecting previously unselected package pd-extended.
(Reading database ... 57768 files and directories currently installed.)
Unpacking pd-extended (from Pd-0.43.3-extended-20121004.deb) ...
dpkg: dependency problems prevent configuration of pd-extended:
pd-extended depends on libfftw3-3; however:
Package libfftw3-3 is not installed.
pd-extended depends on libftgl2 (>= 2.1.3~rc5); however:
Package libftgl2 is not installed.
pd-extended depends on libglu1-mesa | libglu1; however:
Package libglu1-mesa is not installed.
Package libglu1 is not installed.
pd-extended depends on libgsl0ldbl (>= 1.9); however:
Package libgsl0ldbl is not installed.
pd-extended depends on libjack-jackd2-0 (>= 1.9.5~dfsg-14) |
libjack-0.116; however:
Package libjack-jackd2-0 is not installed.
Package libjack-0.116 is not installed.
pd-extended depends on liblua5.1-0; however:
Package liblua5.1-0 is not installed.
pd-extended depends on libmp3lame0; however:
Package libmp3lame0 is not installed.
pd-extended depends on libquicktime2 (>= 2:1.2.2); however:
Package libquicktime2 is not installed.
pd-extended depends on libspeex1 (>= 1.2~beta3-1); however:
Package libspeex1 is not installed.
dpkg: error processing pd-extended (--install):
dependency problems - leaving unconfigured
Processing triggers for man-db ...
Processing triggers for menu ...
Processing triggers for hicolor-icon-theme ...
Processing triggers for desktop-file-utils ...
Processing triggers for shared-mime-info ...
Errors were encountered while processing:
Has anyone else encountered this problem?
If so, any suggestions?
thanks,
J
Lua Midi Markov
Here is an update of the patch.
It is now possible to choose the GM midi instruments that are stored in the midifile, but mostly it sounds more interesting to choose different sounds.
And it is possible to store collections of midi data to a file.
For now I could not store the length of the notes, because between note on and note off events of one note are often other notes in the midifile and because of the markov characteristic the note off can happen in a markov chain a long time after the note on, or even before.
Because of that the sound would hang a lot of times.
The only way to have the note length information from a midifile that I can think of would be to calculate the milliseconds of a note with counting the ticks from one note on event to the corresponding note off event and to save this millisecond value together with the other midi values like pitch, velocity, program change etc..
But that seems to be quite complicated.
I hope the patch is more or less self explainig but I will try to answer any questions if that is not the case (and perhaps write a little documentation).
I am also happy to hear about errors.
Here is an interesting read about markov chains and jazz improvisation:
https://vtechworks.lib.vt.edu/bitstream/handle/10919/36831/dmfetd.pdf?sequence=1
[poly] object glissando
i tried using the CC messages but i keep getting the same result. The problem is that maybe poly is not the right object to use for what i need.
Basically i need monophonic midiout; the reason i am using poly as [poly 1 1] is that it triggers the note off whenever a second note is triggered. Although, doing so the midi out results as follows:
(when first note is triggered)
midi note: 44
velocity: 100
(when second note is triggered)
midi note: 44
velocity: 0
midinote 45
velocity: 100
So basically, in this way i will always end up having stepped notes without legato...
Is there any other method to make sure that a note off is triggered at the right time? I think that what i need at the output to eliminate the stepping between notes is something like this:
(when first note is triggered)
midi note: 44
velocity: 100
(when second note is triggered)
midi note: 45
velocity: 100
midinote 44
velocity: 0
foo_pd - Pure Data plugin for foobar2000
This is a spiritual successor to amPd. It's much more stable and has many more features than amPd:
-
reads/writes metadata to/from patches. This is done by storing the info in the form of comments, in a canvas called [pd meta] or [pd info]. If no such canvas exists, foobar will add it in the top left-hand corner of your patch.
-
comes with a Win32 Dialog UI element, containing sliders, toggles, buttons, and edit-text/button combos to send messages to your patch.
- foobar looks in your patch for a canvas called [pd mix] and uses the parameters of whatever sliders, bang objects, or toggles it finds there to give your UI controls similar functionality.
How playback works
- libpd sends a 1 to vol, then a bang to play.
- Generally this is where, in your patch, you have an [r play] hooked up to your metro, and an [r vol] connected to a [*~ ] before your output reaches [dac~].
- the length of the song is arbitrarily set by the user.
- This affects the trackbar's cursor visibility and ability to set a position.
- If the length is 0, there will be no trackbar cursor. Otherwise, the cursor, when moved, will send its position in seconds to pos. From there, it's up to your patch to take that information from [r pos] and work it into song events.
- The patch will not actually stop and move on to the next track until libpd receives a bang from [s stop].
How the mixer works
- all mixer controls go inside of [pd mix]
- horizontal and vertical sliders are turned into slider controls in the UI element
- labels assigned to sliders in the patch become labels for the UI element's slider controls. The same applies for send symbols.
- min and max values of sliders on the UI element work in integers only, so if you want a gradual shift from, say, 0 to 1, write "gradient" in the slider's receive symbol, and the slider's range will be broken down into roughly 200+ individual steps.
- there are currently 7 sliders in the UI element
- bang objects with no label become simple buttons in the UI
- their send symbols will be reflected in the button's name and they will send a bang when clicked.
- there are currently 3 buttons
- bang objects with a label assigned become message buttons
- these have an edit text field associated with them, where you can type out any message you want and send it to the destination.
- the bang's label is placed inside of the edit text field as a suggested message to send.
- pure data strips commas out of labels, so I'm using apostrophes to denote where commas should go. ex: do this' then this
- there are currently 2 message buttons, with the 'any' button being a potential 3rd.
- a bang object with a label written in the format dest : msg will be assigned to the 'any' button.
- the 'any' button has an editable destination field, giving you access to basically any receive symbol in your patch.
- also substitutes as a third normal message button, when the other two are already in use
- toggles become checkboxes
- each checkbox can have a label and send symbol assigned to it
- there are currently 4 checkboxes
- right-clicking a track shows the context menu entry Pd Player -> Load mixer.
- basically, you can load mixers of tracks not currently playing for some potentially interesting exchanges between patches. After loading the mixer, you still need to hit the Refresh button to show the changes.
foo_pd's copy of libpd.dll contains only the externals that I needed to run the example patches. If you want your own patches to work with foo_pd, you might need to make another build using MSYS2. If you're not sure which objects aren't instantiating, foobar's console prints all of pd's messages while audio is being processed. I'll also add more externals over time.
I'll be maintaining foo_pd at https://github.com/myQwil/foo_pd where you can also find the latest builds
foo_pd.zip
Last Updated: Feb 26, 2021 3:55pm EST
REAPER playing MIDI notes sent by Pure Data
are you using [makenote] like in the video? I am not familiar with reaper, but your OSC messages received don't look like full midi information. i'd expect to see this:
/note [i] 80 76 1
/note [i] 80 0 1
/note [i] 62 101 1
/note [i] 62 0 1
/note [i] 62 98 1
/note [i] 62 0 1
where every note on has a note number, a velocity and a channel, and every note on has a corresponding note off (velocity 0).
ANN library - where to get?
@Hugo Legrand thanks a lot. i downloaded the file "ml-0.17.0-alpha-WIN32.zip" from this link: https://github.com/cmuartfab/ml-lib/releases somehow the windows build contains only 2 .pd objects (ml.svm-help and ml.zerox-help) but a lot of .dll´s. i added the library path to the search path and the name to start processes and pd prints can´t load library. the 2 objects are recognized but only half of the messages do work. so i am not sure if i do something wrong, or if the build does not work (for me). i tried it with the osx build, in comparison to windows build the library get loaded on startup but everything else seems the same.
this are the printed messages if i click every help-file message from ml.svm-help.pd:
ml.svm: Support Vector Machines based on the GRT library version 0.2.5 revision: 2-Jan-2017
error: ml.svm: messages with the selector 'bang' are not supported
error: ml.svm: function not implemented
error: ml.svm: messages with the selector 'bang' are not supported
error: ml.svm: messages with the selector 'normalise' are not supported
error: ml.svm: function not implemented
ml.svm: new input vector size, adjusting num_inputs to 4
error: ml.svm: class label must be a positive integer
error: ml.svm: messages with the selector 'predict' are not supported
error: ml.svm: messages with the selector 'estimates' are not supported
error: ml.svm: messages with the selector 'load' are not supported
error: ml.svm: messages with the selector 'save' are not supported
Lissa Executable / ofxOfelia compile error (Solved)
@cuinjune I tried to compile the lissa seq patch. but when i open the executable it opens only a small empty window.
i also tried to compile a help patch for testing, with the same result.
but your example works fine(Win32Example).