Performance of [t f] vs [pd nop]
Thanks for your responses! now that's interesting about the s/r performance - in this case, i get the following results (repeatedly tested again):
[perf_meter]: pd_nop
bangs time(ms) bangs/ms
9603563 1000.0 9603.55
[perf_meter]: t_f
bangs time(ms) bangs/ms
9987069 1000.0 9987.06
[perf_meter]: send_receive
bangs time(ms) bangs/ms
10147908 1000.0 10147.90
[perf_meter]: connected
bangs time(ms) bangs/ms
10711894 1000.0 10711.88
Here's the patch if you want to check these on your side: test-performance-nop.pd
I updated perf_meter.pd with this additional newline for clarity - but as I said, I'm also not completely sure if this is a valid way of checking performance.
timing events in pd
I am working on a piece that will turn on and off multiple motors at certain time based on certain variables.
What I'm trying to do is sequence like this:
sequence 1:
button is pressed
motor 1:
start at min 00: random pulse(ON time of 35 ms) every 7 - 10 sec
motor2:
start at min 01: random pulse(ON time of 35 ms) every 5 - 11 sec
motor3:
start at min 04: random pulse(ON time of 35 ms) every 3 - 13 sec
motor4:
start at min 06: random pulse(ON time of 35 ms) every 7 - 10 sec
motor5:
start at min 08: random pulse(ON time of 35 ms) every 5 - 12 sec
motor6:
start at min 10: random pulse(ON time of 35 ms) every 4 - 10 sec
all motors run
when button is pressed again (button count = 2):
sequence 2 starting:
motor 1:
continue random pulse(ON time of 35 ms) every 5 - 10 sec
stop after 01 min
motor 2: continue random pulse(ON time of 35 ms) every 3 - 12 sec
stop after 04 min
motor 3: continue random pulse(ON time of 35 ms) every 7 - 12 sec
stop after 10 min
motor 4: continue random pulse(ON time of 35 ms) every 3 - 8 sec
stop after 16 min
motor 5: continue random pulse(ON time of 35 ms) every 5 - 16 sec
stop after 18 min
motor 6: continue random pulse(ON time of 35 ms) every 7 - 10 sec
-- now only motor 6 is running >> button pressed>> last motor that running(motor 6) is stops.
sequence 3:
all motors pulsing together every 7 seconds for 2 minutes
after 2 minutes elapsed all motor stops.
how can I implements the above in PD?
how is possible to timing events without using metro rather something more accurate?
Thanks
count~ pause option?
The problem with a [metro]-based approach is that the [metro] puts a hard limit on time granularity. You can get more accuracy by increasing the [metro] speed, but this uses more CPU.
IMO if you want real accuracy, then [metro] isn't the way to go.
At first I was going to keep a [timer] running continuously, and also accumulate a "total pause time" value to subtract from the [timer].
But then I realized... at the moment of pausing, it could "freeze" the pause time -- then, when you resume, reset the timer to 0 and add the last frozen time -- so at that moment, 0 + frozen time = last-paused value, 1000 ms later = 1000 + frozen time etc.
This type of thing is IMO much easier to do in a programming language, but with some clever traffic policing, it does work:
For this type of abstraction, it's good to have a unit test -- provide a controlled input and make sure the output is as expected.
1, clear; 2, init the sequence; 3, "0 1000" to go.
input: 0 stop
input: 0 reset
input: 0 1
input: 0 bang
print: 0 OK
input: 250 bang
print: 250 OK (250 ms later)
input: 350 0 Pause at 350
input: 450 bang Poll 100 ms later
print: 350 Still paused at 350, OK!
input: 600 1 Resume 250 ms later (time should not have changed)
input: 700 bang +100 ms after the moment of resuming, then poll
print: 450 Result = 350 ms + 100 ms = 450 ms, OK!
input: 900 0
Unit test passed The paused duration between 350 and 600 ms does disappear as expected.
So you'll get full [timer] resolution without running a busy-counter loop.
hjh
Instability
Hello, first of all I want to say that I have been using Pd for 6 years on a PC i5 (fourth generation) 16gb ram and Windows 7 ultimate. Pd and other DAWs I have have always worked without any stability problems. A year ago I upgraded to Windows 10 home (I have always optimized Windows following the indications offered by Merging Technologies and some professional DAWS) Today all the software related to audio works perfectly and without any problem except PS that drives me crazy.
Just create a new patch with 2-3 tables and 2-3 signal objects to start the instability in Pd.
The first symptom that appears is the "feeling" of "overloaded". For example, when dragging an object with the mouse, the object is delayed with respect to the mouse pointer (the more the object patch is loaded, the more noticeable the delay is)
If I save the content of a table of only 8820 samples for example (200ms) with [soundfiler], it can take between 2 and 3 seconds to wait until the message appears in the console
It has also happened to me (although on fewer occasions) that when I press a bang button, the button remains pressed in black and Pd blocked (although I am not aware that this problem is directly related to the other comments).
I want to make it clear that I have not had any problems related to the audio, it is with the GUI that makes me think that something is not right. The first of the problems that I have named is the one that I consider serious for me, because it prevents me from working at ease and in the end I end up not going ahead with any patch. This happens to me in version 0.53.0 that I have now and in the previous 4 versions. I have used the same patches on a laptop that I have and everything works normally. I can't get to understand what is really happening and what the blissful problem may be related to, I have asked several Pd users on telegram and they have not been able to help me either...
Any ideas that occur to you will be welcome. Thank you!
Little help please: abstraction to shrink or compress not resize a table~
@svanya said:
What I need to do is, for example:
Take soundfiles, aka. tabplay~'s of varying sizes/lengths and shrink them all so they play over the same amount of time.
I think cyclone/play~ is the easiest way to do this. Its "start" message is in the format:
- Time within the array where you want to start playing (ms);
- Time within the array where you want to stop playing (ms);
- Duration to play.
The playback rate is then automatically calculated from (end - start) / dur.
The problem with cyclone buffer~ / play~ is that (AFAICS) they don't handle the situation where the audio file being loaded is at a different sample rate from the soundcard. (Maybe they do, but if so, I don't see it.)
If you're sure that the sound files will match the DSP sample rate, then, no problem -- if one array contains 750 ms of audio and you want it to play in 250 ms, then:
[start 0 750 250(
|
[cyclone/play~ arrayname]
If you're not sure, then one solution would be some abstractions in my library (https://github.com/jamshark70/hjh-abs) that provide [value] variables with information about sound files loaded into arrays. [value xxxscale] is file's sample rate / system sample rate (btw DSP should be on before loading... I should fix that later).
(Edit: You may need to have "-lib cyclone" in the [declare] too.)
hjh
Another modulation technique (experimenting with wavesets)
To be honest, I hadn't tested the patch before I shared it. Which I definately should have, because I just found some serious distortion problems! Not the kind of distortion that you may want, of course ...
The problem is this: In a digital (sampled) signal you can never really find zero-crossings. All you can get is the first sample after the zero crossing. So I had to calculate an imaginary point between the samples n (> 0) and n-1 (< 0) using linear interpolation. The point of zero crossing then is: n - x[n] / (x[n] - x[n-1])
Fortunately, the vline~ object is sub-sample accurate and can handle this!
So here is an improved version of the patch: waveset-experiments-ms.pd
One more problem might be pd's limited precision. But I've never worked with "double precision" and it would probably be an overkill for this kind of problem anyway.
Audio click occur when change start point and end point using |phasor~| and |tabread4~|
Hi Junzhe
I often like to think through something like this with a concrete example.
Let's start with 10 seconds of audio: phasor = 0 --> time 0, phasor = 1 --> time 10000 (ms).
Then, at 5000 ms, you change the end time to 7000 ms.
So, now, phasor = 0.5, time = 5000. And you need phasor = 1 now to map onto 7000 ms.
So two things need to happen:
- The phasor, running at its current speed, would reach its end 5000 ms later -- but you actually need it to reach the end in 2000 ms. So the phasor's speed has to increase by a factor of 5/2 = current_time_to_end / new_time_to_end.
- The linear mapping currently locates phasor = 1 at time = 10000, but now you need phasor = 1 --> time 7000. So the slope of the linear mapping will have to adjust by a factor of 2/5 = new_time_to_end / current_time_to_end (and the linear function's intercept would have to change too).
The changes in phasor frequency and linear slope should cancel out.
Then, at the start of the next cycle (which can be detected by [samphold~]), you would have to recalculate the slope for the entire start <--> end segment.
I might be overthinking it, but e.g. jameslo admits that in a simpler solution "the pitch is not steady as you adjust the start and end" so I think there aren't many shortcuts to be taken.
BTW there is another way to integrate a rate: rpole~. With an integrator, you don't have to worry about rejiggering slopes -- it just continues on its way, and reaches the end value in its own time. But, you would be responsible for triggering the reset at that point. This version uses control messages for triggering, so it would be quantized to block boundaries. To do it sample-accurately involves feedback and I never worked that out.
And a quick test patch (array "a" is 44100 samples, vertical range -10 to +50):
hjh
PS Hm, now I guess the [route float bang] isn't needed after all.
Paradigms useful for teaching Pd
This seems as likely a subcategory as any...
I'd like to connect with teachers using Pure Data in the classroom.
- Where are the stumbling blocks that you see students crash into frequently?
- (Anyone using Pd could chime in on that one... what are the things that confused you?)
- Are there any techniques/ideas/paradigms that helped the students to understand these difficulties more easily?
For a specific example: https://forum.pdpatchrepo.info/topic/13263/samphold-at-the-control-level -- "I want to get the number to update on the downbeat so it doesn't play anything while the number is being updated by some other process."
Extremely common scenario -- but I'll be danged if I can find anything in the help series that makes it clear.
This happens to be one of the sticking points for me -- which, lately, got me thinking about a paradigm of "feedforward" and "feedback" to cold inlets. It's (relatively) easy to understand chaining through hot inlets. Everything is immediate, and that's where the quoted question comes from -- if the only thing anyone taught you is how to chain immediate operations, then "save this datum for later" is scarcely even thinkable. (The quoted thread goes on to say "I'm having trouble explaining" -- meaning, whatever degree of exposure to Pd this user had, it wasn't enough to provide a vocabulary to talk about this problem.)
- "I have data now, but I don't want to use it until later" --> feed it forward to a storage object, then bang the storage object when you need it.
- "I want the next cycle of a loop to operate on the result of this cycle" --> feed it back to a storage object that's triggered by the loop.
This solves a bunch of problems. The quoted problem -- (data source) feeds forward to [f] right inlet. Or, initializing a counter at the beginning of the loop (feedforward). Or, building a list iteratively, but outputting only the final list (on each loop iteration, feed the list-in-progress forward to list storage, and bang the storage when the list is finished -- for this one in particular, I had struggled in the past with various bizarre usages of [spigot] but this is much easier).
One of the things I was missing over the last year and a half of getting up to speed in Pd is an established vocabulary of usage patterns. Sometimes I think Pd and Max pedagogy tries to stay away from typical computer-science problems -- but sooner or later, you're going to run into problems that have standard solutions. So why not collect them into a unified place? Like, in SC, for the fourth example below I can just write arrayOfMidiNotes.collect { |note| note.midicps }
and uses of collect
are all over the place in the help system... but in Pd, it took me literally over a year to figure out the best way to collect
/ map
. That's... kinda crazy.
hjh
how to limit DS array value range
By the way, i found a method to make the mouse plugin at least work without error messages: mouse-plugin.tcl
This creates a hidden file that contains a [r mouse_receive], opens it in the background and deletes the hidden file. This way there are no error messages, because there is always a receive present. It is still unclear how to determine the correct window from the focused window code.
Usage: Put the mouse-plugin.tcl in the extra directory, restart Pd, open a patch, create a [r mouse_receive] and connect it to a [print]. You can now see mouse movements and mouse up and down events.
Maybe this can be improved if a method like "ifexist" exists.
how to limit DS array value range
the problem also for me with the mouse plugin is, that you always need the [mouse receive] object in your patch if you want no error message. i think the best vanilla solution for getting mouse coordinates is this https://forum.pdpatchrepo.info/topic/10854/xy-abstraction-to-get-mouse-click-and-drag-coordinates-vanilla, but there is still a lot going on just for getting the mouse coordinates. an easy way to get mouse coordinates and a resizable drag area would be a nice addition to the data structure functionality (not sure if that would be possible...). yes, in some aspects they are unsatisfying