Convert analog reading of a microphone back into sound
hey @whale-av @manuels @jameslo thanks once again for the feedback! I think we are getting there, very exciting. I just quickly plugged your suggestion into my patches and they both work well. Interestingly enough now the sig~ and the resampling method result in two sounds that are timbrically quite different, but still coherent with what I would expect. This is super interesting, even as a creative toolset, as long as the difference in timbre are not artefacts. I will investigate this further and try to post some audio examples.
Gonna work more on the project this week and keep you posted. Just bear with me as I cannot work on this full-on every day like the past weekend, cause of other commitments.
@jameslo sorry to hear, it is quite jumping around these days, I hope your symptoms are bearable, and I'm glad that an interesting problem can help a little 
@whale-av the vline~ there is very elegant! I had previously tried with a line3 in the control domain but your suggestions makes more sense. I've used a bucket object to get the interval, that should be the same as what you are doing in your patch.
@manuels yes, indeed. Different filters are the next thing I'm gonna look into, especially as I gonna need a more systematic spectral analysis of the resulting sound to make sure it is still coherent with the expected signal.
Do you know how to dynamically write the function to an [expr]?
Thank you, @Jona and @whale-av for the pointers.
Yes. I want to be able to change the operators, etc. . So for instance the multiply in [expr $f1*$f2] to a plus while the Gem stream is running.
Two options I have tried are assembling an expr clone with all of its operators as type-selectable by idx, so an expr router of sorts. Where one could assemble the pieces by list(functypeID#) and variables. But that fails because it's just too clumsy.
The option below is the best, I've come up with so far.
And if, as you say whale-av, the expr itself is written at runtime (until the feature gets added sometime in the future
) probably the best way to go.
Should say something, I learned there is no way to pass it in as a symbol [expr $1`], where $1 is a creationarg symbol because expr interprets it as a desire to create an array.
One option may be using iemguts and dynamic patching. If I look into it, will try and let you know what I find out.
Seems sending it a list is something that should be added.
Would help a lot for patches where dynamically changing formulas in real-time streams (like a GEM or ~) best suit their design.
Thanks, again, @jona and @whale-av. Really appreciate your response and the timeliness with which you replied,
Happy PD-ing.
Here's the way I will probably go with: Popping the subwindow where all the expressions are then closing it when I'm done,

4 point interpolation increases peaks, but by how much?
@whale-av I'm not sure that ringing is relevant or helps quantify the issue, but I support all efforts to keep Spinal Tap relevant in international discourse. 
I found this explanation of 4 point interpolation helpful: interpolation.pdf .
It's kind of surprising how straightforward it is to construct a 3rd degree polynomial that hits all 4 points, and useful to know that the resulting polynomial is only for interpolating the interval x2..x3. That explains why tabread4-help says "Indices should range from 1 to (size-2) so that the 4-point interpolation is meaningful", e.g. if you have a 4 point table, you can only interpolate between indices 1 and 2 (the 2nd and 3rd table value). That in turn implies that I only need to characterize the overshoot produced by any given vector of 4 consecutive samples because everything before and after doesn't matter. You can see it in @whale-av's plot--those sharp points at some of the integer indices as the algorithm switches abruptly from one polynomial to another.
In a cursory search of the web I can find tutorials on how to find the local minima and maxima of a given 3rd degree polynomial, but not a family of them (varying over all yn). I think this means I need multivariable calculus to answer my question analytically.
Which in turn means it's probably not happening.
Soundfiler (or something else in PD) deleting files - is it possible?
I know that soundfiler essentially reads and writes .aiff files by copying into and out of arrays.
Is there a way to delete files from within a running PD patch without using a dialogue box?
Here is the problem I'm trying to solve:
I have a 16 track looper which uses a combination of delay lines as buffers and self-overwriting arrays for the loops. I have 100 save slots where you can save tracks (copy the arrays to .aifff files), then load those .aiffs into the track arrays.
All of this uses hardware and does not use any screens, keyboards or mice. The problem is that those 100 slots fill up quickly, so I'd like to be able to delete the contents of slots -- again, this needs to be "automatic" without using any dialogue boxes or anything like that. It's easy to keep track of the names, they would just be 0-100.aiff, essentially. So I would know I want to delete 4.aiff for example. Is there a way to do that?
Thank you!
How does one programmatically create pd objects from an external?
Thanks Seb! Very much appreciate the detailed explanation.
I managed to get it working with your advice.
Here's a demonstrative case:
#include "m_pd.h"
static t_class *demo_class;
typedef struct _demo {
t_object x_obj;
t_glist *mycanvas;
} t_demo;
void demo_bang(t_demo *x) {
t_atom av[4];
SETFLOAT(av + 0, (t_float)300);
SETFLOAT(av + 1, (t_float)10);
SETSYMBOL(av + 2, gensym("r"));
SETSYMBOL(av + 3, gensym("test"));
pd_typedmess((t_pd *)x->mycanvas, gensym("obj"), 4, av);
}
void *demo_new(void) {
t_demo *x = (t_demo *)pd_new(demo_class);
x->mycanvas = canvas_getcurrent();
return (void *)x;
}
void demo_setup(void) {
demo_class = class_new(gensym("demo"), (t_newmethod)demo_new, 0,
sizeof(t_demo), CLASS_DEFAULT, 0);
class_addbang(demo_class, demo_bang);
}
How does one programmatically create pd objects from an external?
Thanks for your reply, Seb,
Despite your advice, I'm still not sure what the correct way to go about it. The following segfaults.
t_glist *mycanvas = canvas_getcurrent();
t_atom av[4];
SETFLOAT(av+0, (t_float)300);
SETFLOAT(av+1, (t_float)10);
SETSYMBOL(av+2, gensym("r"));
SETSYMBOL(av+3, gensym("test"));
pd_typedmess((t_pd *)mycanvas->gl_owner, gensym("obj"), 4, av);
Any further tips would be much appreciated.
Why does Pd look so much worse on linux/windows than in macOS?
I have to admit that I forgot to get the Mac screenshot yesterday (smh).
@oid said:
free of the weird artifacts which I assumed were caused by a post screen grab resize, but could have been caused by the screen grabber itself. Lines should not be changing thickness like that, most noticed on the line between [moses] and the number box, they should be 1 pixel wide but it alternates between 1 and 2 pixels in width.
That issue is not caused by the screen grabber. It's the normal appearance of Pd for ages. See the 2nd "Modulation index" --> [*~]. (This is a png -- there are no jpg compression artifacts. This is how it really looks on my screen, in the Pd window.)

"Lines should not be changing thickness like that" -- agreed, but by that standard, then Pd's line rendering is sub-par. Lines in Pd have always been changing thickness, for as long as I've ever used it.
It's a (more-or-less) solved problem in the graphics world. FWIW here is angled-line drawing in SuperCollider (using Qt). Here, I've chosen an angle that will be maximally fuzzy. It's not great exactly but, in my opinion, less distracting than Pd's current display.

whale-av quotes seb-harmonik: "Tk/Tcl has solutions in the pipeline" ... erm... but... again, it's a solved problem. Tcl/Tk hasn't caught up with the rest of the world.
@whale-av said:
Pd I use as a tool to get things done and how it looks is unimportant except for keeping patches clean and readable.
I do understand, but I don't quite agree that appearance is completely unimportant.
For a software community to thrive over the long haul, it needs to attract new users. If new users get turned off by an outdated surface presentation, then it's harder to retain new users.
I've observed, at times, when someone points out a deficiency in Pd, the Pd community's response often downplays, or denies, or gets defensive about the deficiency. (Not always, but often enough for me to mention it.) I'm seeing that trend again here. Pd is all about lines, and the lines don't look good -- and some of the responses are "this is not important" or (oid) "I like the fact that it never changed." That's... thoroughly baffling to me.
I know it's not going to change anytime soon, because the current options are a/ wait for Tcl/Tk to catch up with modern rendering or b/ burn Pd developer cycles implementing something that Tcl/Tk will(?) eventually implement or c/ rip the guts out of the GUI and rewrite the whole thing using a modern graphics framework like Qt. None of those is good (well, c might be a viable investment in the future -- SuperCollider, around 2010-2011, ripped out the Cocoa GUIs and went to Qt, and the benefits have been massive -- but I know the developer resources aren't there for Pd to dump Tcl/Tk). But there's a big difference between "we know it's a problem but can't do much about it" vs "it's not a serious problem." The former may invite new developers to take some initiative. The latter discourages initiative. A healthy open source software community should really be careful about the latter.
hjh
Rewind and fast forward?
If you want to scrub a file it will need to be loaded to ram.
This will do it and then start at the point you choose.......... av-sync.pd
Vanilla or extended....... delete any objects that throw errors in vanilla (if they annoy you...!).
It will scrub video in sync as well if you have GEM, but you need to strip the audio from the video into a wav file.
It works without the video though...... just load a wav file into the audio block, and then use the video block scrub controls.
David.
PS there was a mistake in [av-sync] now corrected.
Tabwrite~/array has problems working as a long timebase oscilloscope?
Hi @whale-av ,
Many thanks for the feedback!
First, a note - I also checked [Scope~] found in pd-extended (pd-l2ork, Purr-data) - and it has also its troubles:
- It only reacts on zero-crossings - so it basically shows phasor~ as a straight line, unless it is brought down [-~ 0.5] a bit;
- If using bufsize 1000, it basically updates more than each second - so buffer size seems not to be expressed in samples ?!
Maybe it's possible to control this somehow, since if I open a patch with [Scope~] in PD vanilla, I do get some numbers:

... but I cannot find documentation on this anywhere, and don't really have the time to reverse engineer it...
@whale-av said:
@sdaau_ml Reliable will be to put the data and then bang once only for the new data.
scop.pd
Well, I don't think this will help me much:

First, the timing of slider bangs is inconsistent, at least on Linux/Gnome (and possibly macOS) - sometimes it will hit at 30-40 ms apart, sometimes in much less than a millisecond ( see https://forum.pdpatchrepo.info/topic/8961/repost-measuring-the-elapsed-time-for-gui-hsl-slider-object-events-in-puredata ); and that means sometimes I'll get more data shown in the array98 graphs, and sometimes less (which is not how an oscilloscope display works)... Also, it will not be continually updated, as you noted:
@whale-av said:
Unless you want continuous update in which case you need [snapshot~] and a counter..... sort of like this....... phase meter.zip
Ok, this is pretty cool, thanks for that:

... but this gives me Lissajous curves, not time-domain waveform which I need. Although, I guess [snapshot~] will "lose" some data (due to artifacts of a sampling process), whereas I'd prefer to throw data directly in the array...
@whale-av said:
This might help......... scop2.zip
You will need to play around with the metro timing and the length of the array (and therefore the count object....... send the length of the array to it's right inlet so that it counts through the whole index), doing some range sensing (trigger) math just like a real scope if you want to auto stabilise the waveform.
{{note.... this is using [tabwrite]...... not [tabwrite~].......}}
Ah, this is pretty cool - and actually seems to work close to what I want:

So, I guess [tabwrite ___ $1 $2] means write value $1 at index $2 (couldn't find anything explicit about this syntax in the help file)? In any case, even if it eats quite a bit of CPU, it seems to do the trick for what I need (and thankfully, I don't really need trigger conditions right now)..
Many thanks again for the help,
Cheers!



