Forums > MaxMSP

[announcement] PM.Chamberlin~ (state-variable filter)

July 20, 2011 | 7:52 pm

Hi everybody, I’ve just posted a new svf filter to the toolbox. It does self-oscillation and saturation, supports higher cutoff rates than svf~ and adds a peak filtering mode. (it is more expensive, however) You can also control it via MIDI values and the tuning is accurate enough for melodic playing. It also has the option of only using one output which should save a bit of CPU when you don’t need all the outputs.

PM


July 21, 2011 | 12:48 am

Tomita Whistle, here we come….;-)
Thanks!
License mentions source?
filter model used?
Anyway, thanks again!

Charlie


July 21, 2011 | 7:11 am

Re source: It’s a binary distribution. That said, the filter is ported (lightly) from the ICST DSP library which is BSD-licensed, however, so you can definitely take a look at that. They also made an interesting two-part PDF which explains how it works.

The model is a Chamberlin state-variable digital filter, and has a non-linearity in the feedback, IIRC. The frequency is updated every 16 samples, so it works decent enough for sweeps, but FM is probably asking a bit much. Might add the ability to up/downsample the freq input in the future.


July 21, 2011 | 1:00 pm

Aw…yeah, we want to add lfo&env to freq for whistle patch, right, and stepping is bad to hear there…16 samps is *prob* ok, tho…
Thanks for reference, I had seen this design before, and indeed, it does sound excellent, oscillates great, and the non linearity in the feedback gives that lovely fat ‘formanty’ sound. Thanks again!
charlie


July 21, 2011 | 6:19 pm

this external shows up as a folder and max doesn’t see it. any suggestions?


July 22, 2011 | 3:51 am

Which Max, and which OS?


July 22, 2011 | 4:39 am

doh! sorry

Max 5.1.8
Mac OS 10.6.8
2.66 intel core 2 duo


July 22, 2011 | 8:50 pm

I’m not sure. I tested the link and I see the external fine; I can explore the package contents.

What do you see when you unpack it? I see PM.Chamberlin~.mxo, PM.Chamberlin~.maxhelp, and license.txt

I changed the link to add the bundle bit and updated the plist files; I’m not sure if this is a 10.5-10.6 difference or what the story is. HTH, and let me know.


July 25, 2011 | 9:18 pm

one more thing.. peter this sounds great.


August 17, 2011 | 12:41 pm

thanks Peter, the filter sounds great, it’s a useful addition to the msp toolbox!

However, I think there is still some unwanted (bitcruhs-like) distortion in the signal. This distortion is changing when you change the signal vector size.

Listen to this test patch:

– Pasted Max Patch, click to expand. –

I can provide audio samples if you don’t hear any differences on your system (mine is: 44.1kHz, mac os 10.5.8).
(addition: I am also curious about the level difference, I wasn’t expecting that)

thanks!

Timo


August 17, 2011 | 12:42 pm

idea: could it be that for upsampling you do not take into account the last values of the previous signal vector? (that you don’t store these in your object structure)


August 17, 2011 | 3:41 pm

Hi Timo,

I hear a level difference (-6dB), but I’m not getting the bit crushing. I think the level difference could be from the saturation code. I’ve tried this at signal vectors of 64,128, and 256 at 44.1kHz.

Because of the saturation, pre and post gain can make a big difference in the sound of the filter. I’d like to hear the recordings if you have time. Also, does this happen in both modes of the filter? (mono vs. poly outs) The code is slightly different there, and that could account for it.

– Pasted Max Patch, click to expand. –

August 22, 2011 | 6:22 am

Hi Peter,
I sorry for the delay but now I have time to reply and make examples for you.
I hear it in both modes of the filter (mono & poly outs), it’s not clearly visible in the scope~ and spectroscope~, but it is clearly audible on my system.
Timo

Attachments:
  1. sv512.aif

August 22, 2011 | 6:30 am

I included some spectrum plots of the audiofiles I attached to the previous post, this clearly shows the distortion that I hear (note: green is incoming audio, red is filtered audio, sv means signal vector size)

[attachment=169399,2557] [attachment=169399,2558] [attachment=169399,2559] [attachment=169399,2560] [attachment=169399,2561]

Attachments:
  1. sv32.png

August 22, 2011 | 9:43 am

Hey Timo,

Those spectrum plots look pretty cool!

If only you could get spectral plots like that it MaxMSP……

;-)

Well – maybe sometime in the not too distant future..

Alex


August 22, 2011 | 10:28 am

yeah Alex, having spectrum plots like this in in max would be awesome!! :-p


August 22, 2011 | 1:13 pm

Thanks for the thorough example. I’ll have to look through the code. The filter equation is from the ICST library. My guess is that the distortion may be from updating the filter coeff every 8 samples, and the filter coeff is affected by the feedback, so the slower updates could be causing the distortion.

I could add an option to set the update rate. I might do it as a % where 0-100 is scaled to 0-n where n is the result of the vector size 2^n.


August 22, 2011 | 1:22 pm

Peter, what if you update the filter coeffs only when they change? Do you still hear it? Maybe when you set the coeffs the ‘history’ of the filter is reset as well.

If it’s due to the filter resetting it is still weird that it changes with signal vector size (which are all multiple of 8 in my examples)


August 22, 2011 | 2:30 pm

Had the coffee now; the base2 log isn’t great, and I’ll probably just go with a sample delay.

It’s also interesting that the distortion seems to go up as the vector size increases. There’s a multiply involving 1/vs, and I hadn’t taken the do_every_nth factor into account there, and I’ll see about tweaking it.

It’d be really nice if we could message people privately. I had someone offer to build a windows version, but I have no way of contacting them…


August 22, 2011 | 2:36 pm

"It’d be really nice if we could message people privately. I had someone offer to build a windows version, but I have no way of contacting them… "

sometimes you can see the mail address of the person who replies in the email notification you receive in your mailbox

looking forward to the tweaks :-)


August 22, 2011 | 4:08 pm

I think I’ve got it tracked down. I had an error in my bit logic in the coeff update routine. See if this works better. There’s still some noise in it, but it looks harmonic, and much cleaner with a sine wave through it. It’s available on the download page.

One issue still to be resolved: updaterate of 1 sample sounds bad, but updaterate of 2 samples sounds fine.

I’m coming from Java, so I’m not used to doing a lot of bit-manipulation tricks. My do every nth code looks like this: (for i in vector)

if (0 == (i | nth))

where nth is nth -1 (so if every 8 samples, use 7 for the bitmask). Hopefully I’m getting that right now…


August 23, 2011 | 7:04 am

Hi Peter,

Thanks, the ‘bitcrush effect’ is gone.
Yes, there still is some distortion and, but this is due to the saturation I think and it really depends on the level of incoming audio.

Only it seems that in this version you have broken the non-signal frequency input, it only reacts on signal input now.

I don’t think "if (0 == (i | nth))" is doing what you want (check it with the max bitwise-or object if you like),
I think you are looking for "if (0 == (i % nth))" (where nth is nth – 0). Though you need to make sure that your signal vector size is a multiple of nth.

(it might be possible with bitmask operations as well if you stick to powers of 2, but I don’t know them so well either)

– Pasted Max Patch, click to expand. –

August 23, 2011 | 4:15 pm

You’re right, it definitely isn’t. I need:
0 == (i & nth) where nth = nth-1 (so if you say 8, it uses 7 for the bitmask)

The reason for doing this via bitmask and not % is that I’m trying to avoid adding a division to the mix. The 2^x-1 bitmask should always be non-zero except for when i%(2^x) is 0.

I’ll have to see what I did to kill the non-signal input…


August 24, 2011 | 7:16 am

Hi Peter, yes 0 == (i & nth) works, but I don’t think it works well for all values (I guess it only works for powers of 2).

if updaterate is 8 samples for example then nth = 7, then (i&nth)==0 for i=0, 8, 16 which is correct

if updaterate is 7 samples for example, then nth = 6, then (i&nth)==0 for i=0 , 1, 8 ,9, 16 ,7 which is NOT what you want

if updaterate is 6 samples for example, then nth = 5, then (i&nth)==0 for i=0, 2, 8, 10, 16, 18 which is NOT what you want

check it here:

– Pasted Max Patch, click to expand. –

Viewing 24 posts - 1 through 24 (of 24 total)