<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><div class="">@Miller, I just saw your message - we will try that asap!</div></div><div class=""><br class=""></div><div class=""><br class=""></div>Hello Chuck, <div class=""><div class=""><br class=""></div><div class="">Good point! Thanks for these thoughts, there is no good reason to duplicate the table with each object, apart from initially being too lazy to code it correctly.  </div><div class=""><br class=""></div><div class="">I will have a look at the code again and see which solution I can arrive at! Method 3. sounds a bit like the unique pointer idea in modern C++…</div><div class=""><br class=""></div><div class="">There is another thing that I struggle to understand: (I already posed this question on Github)</div><div class=""><br class=""></div><div class="">Should the sinc interpolation change its filter characteristics when you change the delay time?</div><div class=""><p class="">
If that is the case, the code would need a little bit of adaption.</p><p class="">From what I understand, increasing the delay time is like downsampling (is it?). Now, I wonder how exactly delay time and sample rate are related mathematically. E.g. if I took the derivative of the delay time, would I get something that is proportional to the change in sample rate?</p><p class="">I read about the filter curve adaption during downsampling here:<br class="">
<a rel="nofollow" href="https://www2.spsc.tugraz.at/www-archive/downloads/Mueller11_DopplerSRC_0.pdf" class="">https://www2.spsc.tugraz.at/www-archive/downloads/Mueller11_DopplerSRC_0.pdf</a><br class="">
...but how would that apply to delay time interpolation?</p></div><div class="">Also: Is it really mandatory to choose a filter cutoff below pi, when the input and output Sample rates match? For a simple static delay that should be the case.</div><div class=""><br class=""></div><div class="">Best wishes, </div><div class="">Clemens</div><div class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">Am 2021-04-29 um 17:55 schrieb Charles Z Henry <<a href="mailto:czhenry@gmail.com" class="">czhenry@gmail.com</a>>:</div><br class="Apple-interchange-newline"><div class=""><div class="">It's sort of disappointing that it has to be so expensive, but you do<br class="">what you have to to get the quality and consistency of the sound.  The<br class="">question of whether there is an optimal interpolating kernel (which<br class="">I'd like to work on) isn't really going to help you in the near term.<br class="">It's enough just to find a solution that works well and performs well.<br class=""><br class="">You've got a scalability issue when using multiple instances of delreadsinc~:<br class="">Each new instance recalculates the table when created.  The table is<br class="">stored in the struct _sigvdsinc so it is also duplicated for each<br class="">instance beyond the first.<br class="">So, I propose a few other choices:<br class="">1.  Calculate the table during setup and add a class method that<br class="">returns a pointer to that table, so that a new object doesn't<br class="">calculate the table.  It just points at the existing table.  This<br class="">option would use memory, even if the object is never used, and would<br class="">not free the table under any circumstances (not great, but easy)<br class="">2.  Add a class method that returns NULL if the table has not been<br class="">created or a pointer to the existing table and a class method to set<br class="">the pointer.  The first instance of the object used would run the<br class="">initialize_sinc_table function, but each additional instance would<br class="">not.  The table hangs around for future use, even if the instances are<br class="">deleted.<br class="">3.  Add the class methods in 2. plus methods to keep a count of the<br class="">number of instances.  Then, when the last instance is deleted, the<br class="">table is freed and the pointer re-assigned to NULL.<br class=""><br class="">By my approximation, that table uses about (4*4096*10) 160 kB (or 320<br class="">kB in double precision).  I'm not real clear on the differences in<br class="">stack, static array allocation, and dynamic allocation in<br class="">behavior/performance.  I know it's there, just can't seem to digest it<br class="">when I look at it.  You might have had some reasons in mind to<br class="">allocate the array the way you did--I'd like to learn more about this<br class=""><br class="">Best,<br class="">Chuck<br class=""><br class="">On Wed, Apr 28, 2021 at 2:27 PM Max <<a href="mailto:abonnements@revolwear.com" class="">abonnements@revolwear.com</a>> wrote:<br class=""><blockquote type="cite" class=""><br class="">Hi Chuck,<br class=""><br class="">Clemens isn't on the list (yet), he sent me some measurements he made in<br class="">response to your post.<br class=""><br class="">All at 48kHz.<br class=""><br class=""><a href="https://cloud.yuca.biz/s/WZseAmBQm9z6NdL" class="">https://cloud.yuca.biz/s/WZseAmBQm9z6NdL</a><br class=""><br class="">he says he can't hear a difference with 10 samples cutoff@pi and 14<br class="">samples cutoff@0.85*pi<br class="">It sounds better than than delread4~ from 6 samples cutoff@pi upwards.<br class=""><br class="">greetings,<br class="">Max & Clemens<br class=""><br class=""><br class=""><br class="">On 28.04.21 17:56, Charles Z Henry wrote:<br class=""><blockquote type="cite" class="">I read through the code in your d_delay.c for the delread_sinc implementation.<br class="">It's a 22-point interpolator--very high quality and it looks like a<br class="">good implementation<br class=""><br class="">The Hermite spline is the best 4-point cubic interpolator, but the<br class="">point of those polynomial interpolators is just to be cheap, and good<br class="">enough for regular usage.  It doesn't require a table, so it also<br class="">doesn't need as much cache space<br class=""><br class="">I don't think it's *the* optimal 4-point interpolator.  It's just the<br class="">best cubic polynomial 4-point interpolator.  You could re-use your<br class="">sinc interpolator code for other shorter interpolation kernels, ones<br class="">that are better than cubics but more expensive to calculate.<br class=""><br class="">At least for me, it's still an open mathematical problem that I've<br class="">come back to, from time to time.  I started to wonder if I could<br class="">expand the error terms in the truncated sinc spectrum in the form of<br class="">1/w, 1/w^2, 1/w^3, .... and then cancel them out by polynomial<br class="">correctors.  An alternative to windowing the sinc function, this could<br class="">be a more precise way to set the rate of attenuation in the stop-band,<br class="">while still retaining all the smoothness of the sinc shape.<br class="">I get a break from teaching in about 3 weeks.  I'm looking at the math<br class="">right now, and I don't think I can solve it quickly (or maybe at all).<br class=""><br class="">How short does your sinc interpolator with Blackman-Harris window need<br class="">to be when you start to get the timbre change effect?<br class=""><br class="">Best,<br class="">Chuck<br class=""><br class="">On Sun, Apr 25, 2021 at 7:18 PM Max <abonnements@revolwear.com> wrote:<br class=""><blockquote type="cite" class=""><br class="">Interesting. I've included that in the test patch.<br class="">It exposes the same samplerate dependent timbre change. So far only the<br class="">Sinc function solves the issue.<br class=""><br class=""><br class="">On 25.04.21 23:15, Sebastian Shader wrote:<br class=""><blockquote type="cite" class="">I have a [vdhs~] object in my library that does hermite spline<br class="">interpolation for a delay line (like tabread4c~).<br class="">https://github.com/sebshader/shadylib<br class="">(also on deken)<br class=""><br class="">I had to re-make delread~ as delread4c~ because delread~s delay lines<br class="">are not exposed in the .h files<br class=""><br class="">-seb<br class=""><br class="">-----Original Message-----<br class="">From: Max <abonnements@revolwear.com><br class="">To: pd-list@lists.iem.at <pd-list@lists.iem.at><br class="">Sent: Sun, Apr 25, 2021 5:45 am<br class="">Subject: [PD] 4-point interpolation changes timbre depending on sample rate<br class=""><br class="">Hi list,<br class=""><br class="">the 4-point interpolation in tabread4~ has been a popular topic in the<br class="">past, going back to at least 2008. [1]<br class=""><br class="">A similar issue is in delread4~. In fact a simple resonator changes its<br class="">timbre quite drastically by just changing the sample rate of the audio<br class="">interface. Attached is a test patch.<br class=""><br class="">The issue becomes audible when choosing an odd delay time and compare<br class="">the result between an odd and an even sample rate (e.g. 44.1k vs. 48k).<br class=""><br class="">This is not good. In fact this is a serious defect. Imagine you want to<br class="">market a product like a synth plugin (based on libpd) which sounds<br class="">different depending on if the daw is opened in 44.1 or 48 kHz.<br class=""><br class="">Cyrille Henry has coded tabread4c~ with a four-point cubic interpolation<br class="">in the nusmuk library, but there is no delread4c~ equivalent in nusmuk.<br class=""><br class="">Clemens Wegener has coded delreadsinc~ which implements a<br class="">Whittaker–Shannon interpolation (Sinc function). This implementation<br class="">does sounds consistent in any sample rate. It also sounds much better at<br class="">very slow speeds inside a pitch shifter where delread4~ produces serious<br class="">artefacts. The Sinc function requires a larger padding for the<br class="">interpolation.<br class=""><br class="">There are a couple of questions regarding on how to contribute this to Pd.<br class="">Vanilla objects are currently:<br class=""><br class="">delwrite~ = the sink<br class="">delread~ = control rate tap<br class="">delread4~ (vd~) = audio rate tap with a four-point interpolation<br class=""><br class="">1. the code in delwrite~ isn't agnostic towards the interpolation since<br class="">it already provides the padding for the 4 point interpolation<br class=""><br class="">2. if we add more interpolation methods to delread / tabread, the<br class="">cleanest way would be to just have one tap object and the interpolation<br class="">can be changed by a message and argument to it. currently there are<br class="">implementations for the miller 4pt, cubic 4pt and Sinc.<br class=""><br class="">Unfortunately delread4 already carries the 4 from 4-point interpolation<br class="">in its name, so probably it would be the best to deprecate that and find<br class="">a new name like varidelay~ or so.<br class=""><br class=""><br class=""><br class="">[1] Review of tabread4~ threads in the archive<br class="">https://lists.puredata.info/pipermail/pd-list/2019-06/125391.html<br class=""><https://lists.puredata.info/pipermail/pd-list/2019-06/125391.html><br class=""><br class="">[2] https://github.com/chairaudio/pure-data/tree/feature/delreadsinc<br class=""><https://github.com/chairaudio/pure-data/tree/feature/delreadsinc><br class=""><br class="">_______________________________________________<br class="">Pd-list@lists.iem.at <mailto:Pd-list@lists.iem.at> mailing list<br class="">UNSUBSCRIBE and account-management -><br class="">https://lists.puredata.info/listinfo/pd-list<br class=""><https://lists.puredata.info/listinfo/pd-list><br class=""></blockquote><br class="">_______________________________________________<br class="">Pd-list@lists.iem.at mailing list<br class="">UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list<br class=""></blockquote><br class=""><br class=""><br class="">_______________________________________________<br class="">Pd-list@lists.iem.at mailing list<br class="">UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list<br class=""><br class=""></blockquote><br class=""><br class=""><br class=""><br class="">_______________________________________________<br class="">Pd-list@lists.iem.at mailing list<br class="">UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list<br class=""></blockquote><br class=""><br class=""><br class="">_______________________________________________<br class=""><a href="mailto:Pd-list@lists.iem.at" class="">Pd-list@lists.iem.at</a> mailing list<br class="">UNSUBSCRIBE and account-management -> <a href="https://lists.puredata.info/listinfo/pd-list" class="">https://lists.puredata.info/listinfo/pd-list</a><br class=""></div></div></blockquote></div><br class=""></div></div></body></html>