Support

If you have a problem or need to report a bug please email : support@dsprobotics.com

There are 3 sections to this support area:

DOWNLOADS: access to product manuals, support files and drivers

HELP & INFORMATION: tutorials and example files for learning or finding pre-made modules for your projects

USER FORUMS: meet with other users and exchange ideas, you can also get help and assistance here

Freely Configurable Filter

DSP related issues, mathematics, processing and techniques

Freely Configurable Filter

Postby martinvicanek » Sun Sep 02, 2018 8:14 pm

This is one of my current projects, a freely configurable filter. The user specifies a transfer curve in the frequency domain by placing control points, which are interpolated to give the desired transfer function. The application calculates FIR filter coefficients and provides a ready-to-use filter. The actual filter characteristic may deviate to some extent from the specification because the filter length is 1024 taps; longer filters have higher latency and use more CPU.

DISCLAIMER: The Ruby code violates all style guides and recommendations. In particular, I am guilty of using for-loops - a lot of them. :oops: Read at your own risk! Minors stay away!

ACKNOWLEDGEMNET: My special thanks to Spogg, :ugeek: who solved a Preset Manager problem that had given me a serious headache. I am also grateful for some expert advice from Tulamide :ugeek: concerning graphics optimization.

Please download, use, and give some feedback!
Attachments
curves2.fsm
(2.69 MiB) Downloaded 254 times
InteractiveCurve.png
InteractiveCurve.png (19.03 KiB) Viewed 4872 times
User avatar
martinvicanek
 
Posts: 915
Joined: Sat Jun 22, 2013 8:28 pm

Re: Freely Configurable Filter

Postby tulamide » Sun Sep 02, 2018 9:53 pm

1) The idea itself
Brilliant! Has this been done ever before? A paint-your-own-filter? I don't think it can become any more versatile, or do I miss something?

2) The real deal (DSP)
Once again top quality work. I love how the Impulse Response module works. Certainly gets the most out of green, speedwise. That I don't understand anything of it, is another sign of quality :lol:

3) Ruby
Well done. Yes, you ignore a lot, but to make such a complex Ruby code work really is an achievement. However, no code that couldn't be optimized. So here are a few things.

Starting with the smallest, you seem to be unaware of some range features.
Code: Select all
1..12 ## range from 1 to 12
1...12 ## range from 1 to 11

## more precisely, three dots define a range excluding the last value.
##no need for this:
1..n-1
##replace with
1...n


I highly recommend to replace the for loops. It isn't difficult, but saves CPU load.
Code: Select all
for k in 0..@xLabel.size-1 do
   rect = [@x0 - lwh + @w*@xLabelPos[k], @y0 + @h + 0.5, lw, lh]
   v.drawString @xLabel[k], font, sf, rect, lBrush
end

Code: Select all
@xLabel.each_with_index do |label, i|
   rect = [@x0 - lwh + @w*@xLabelPos[i], @y0 + @h + 0.5, lw, lh]
   v.drawString label, font, sf, rect, lBrush
end


Move all creations of class instances for Pen, Brush, Color and Font to the init method, and use their class methods to change colors or sizes (for example, @myPen.setWidth or @myBrush.setColor. This way you reduce the work the GC has to do, which results in faster execution overall. This is only important in settings, where you draw repeatedly over time, like in your module.

Last, splines. You could have saved a lot of cpu by using my Spline class. I explicitly designed it for use in realtime environments, using
- faster calculations (no expensive polynomial math)
- adaptive (switchable) adjustment of drawing point clouds (= more segments for longer curves, less for shorter)
- anything from linear to cubic through one class
- nodes support mirroring of control points
- methods for mouse control included (detects mouse on node and on control points)
- optional output of interpolation points, independend on drawing settings (!)
- comes with an extensive pictured manual, that describes each method in detail, including usage

With your current skills in Ruby, it would have been a breeze to use the Spline class. Give it a try: http://flowstone.guru/downloads/ruby-for-flowstone-expansion-spline-class/
tulamide
 
Posts: 1931
Joined: Sat Jun 21, 2014 2:48 pm
Location: Germany

Re: Freely Configurable Filter

Postby martinvicanek » Sun Sep 02, 2018 10:37 pm

Thanks, Tula, some stuff for me to consider in more detail. I know your spline classes for sure, but frankly I just couldn't get anything to work, not even a very basic "hello world" type of thing, sorry. If you say there is a manual I will give it a second try.

I am also aware of TheOm's work, however I figured it was easier to write my own code than to modify his to my needs. In my opinion cubic splines are useless for drawing curves because they always overshoot. How often have I cursed at Photoshop for implementing cubic splines? That's why I have included the smart (monotone) interpolation mode. I know you can do Bezier - that*s OK for parametric curves [x(t),y(t)] but not so much for functions y(x).

Now tell me, why are those "each"-iterators preferrable over for-loops? To me the notation is awkward, when I see |x|
I always associate abs(x) (or x.abs for that matter). I need a hard and fast advantage to switch. And then, how can I control excecution order?

Again, thanks for your hints, much appreciated!
User avatar
martinvicanek
 
Posts: 915
Joined: Sat Jun 22, 2013 8:28 pm

Re: Freely Configurable Filter

Postby tulamide » Mon Sep 03, 2018 12:02 am

I know what you mean. Splines can be difficult for Y(x) functions. TheOms editor is perfect for those. However, you can get splines over fixed x-values with the Spline class (for example by switching off auto-resolution and instead set a resultion of n, which will evenly divide the spline distance on the x-axis). But I admit it was more about speed (I used the Splines once to visualize frequencies, so I can assure you that class is fast), than difficulties in translating the values, that drived me to mention the class.

The each iterators are a fixed component of Ruby's core (enumerator class). They are as fast as C ececution is. 'For loops' can't take advantage of internal optimizations and so are just as fast as Ruby is (interpreted). The same goes for the range functionality I pointed out. Using the three dots saves a few cycles per iteration (n-1 is calculated per iteration, not once). By drawing like 20 times per second that is already a lot.

And what do you mean by "control execution order"? It is the same as with your for loops. You should read more about iteration in Ruby, as it can be crucial to optimise speed.
General enumerator info: https://ruby-doc.org/core-1.9.3/Enumerator.html
Arrays implement enumerators and have their own methods built upon enumerator, for example ::map https://ruby-doc.org/core-1.9.3/Array.html#method-i-map
tulamide
 
Posts: 1931
Joined: Sat Jun 21, 2014 2:48 pm
Location: Germany

Re: Freely Configurable Filter

Postby RJHollins » Mon Sep 03, 2018 5:00 am

Man ... this is so cool, MartinV.

8-) 8-) 8-)
RJHollins
 
Posts: 1350
Joined: Thu Mar 08, 2012 7:58 pm

Re: Freely Configurable Filter

Postby Spogg » Mon Sep 03, 2018 10:22 am

Absolutely fantastic Martin!

You just draw the filter characteristics you want, and I totally love it.

I’m wondering if this could be used to accurately match a spectral profile for mastering somehow. Just thinking out loud.

Cheers

Spogg
User avatar
Spogg
 
Posts: 2170
Joined: Thu Nov 20, 2014 4:24 pm
Location: Birmingham, England

Re: Freely Configurable Filter

Postby KG_is_back » Mon Sep 03, 2018 12:53 pm

I'm especially fascinated by the minimum phase response mode. I always knew that it should be possible to calculate minimum phase response for given magnitude curve and I've been hunting for such algorithm for years now... Do you by any chance have some references to what you've done there? I can see some cepstrum log/exp sorcery going on there but I can't quite figure it out...
KG_is_back
 
Posts: 1222
Joined: Tue Oct 22, 2013 5:43 pm
Location: Slovakia

Re: Freely Configurable Filter

Postby martinvicanek » Mon Sep 03, 2018 6:43 pm

Spogg wrote:I’m wondering if this could be used to accurately match a spectral profile for mastering somehow. Spogg

Like this?
viewtopic.php?f=2&t=3972&start=50#p22927
User avatar
martinvicanek
 
Posts: 915
Joined: Sat Jun 22, 2013 8:28 pm

Re: Freely Configurable Filter

Postby martinvicanek » Mon Sep 03, 2018 6:55 pm

KG_is_back wrote:[...] minimum phase response mode.[...] Do you by any chance have some references?

Julius O. Smith is a good source:
https://www.dsprelated.com/freebooks/sa ... esign.html

Here is a concise recipe:

1. Given a (real valued) frequency magnitude response X[k], k = 0..N-1 calculate the cepstrum y[n]

y[n] = IFFT{ log|X[k]| }

2. Flip all negative quefrencies to positive (for causality)

for n = 1 to N/2-1 { y[n] = y[n] + y[N-n] }
for n = N/2+1 to N-1 { y[n] = 0 }

It is a good idea to taper the cepstrum to avoid a step at n = N/2, for instance

for n = 0 to N/2 { y[n] = y[n]*(1 - 4n^2/N^2) }

3. Transform back to frequency domain

Z[k] = FFT{ y[n] }

and undo log by taking the (now complex) exponential:

W[k] = exp( Z[k] ) = exp( Re Z[k] )*( cos( Im Z[k] ) + i*sin( Im Z[k] ) )

4. Convert to time domain to obtain the impulse response IR[k]:

IR[n] = IFFT{ W[k] }

It is a good idea to taper the IR at n = N-1, for instance

IR[n] = IR[n]*(1 + cos(pi*n/N))/2

There you go, ready for convolution.
User avatar
martinvicanek
 
Posts: 915
Joined: Sat Jun 22, 2013 8:28 pm

Re: Freely Configurable Filter

Postby BobF » Mon Sep 03, 2018 9:22 pm

WoW what more can be said! As always Martin, your projects are truly amazing. Very cool indeed.

Later then, BobF.....
BobF
 
Posts: 512
Joined: Mon Apr 20, 2015 9:54 pm

Next

Return to DSP

Who is online

Users browsing this forum: No registered users and 7 guests