Cabbage Logo
Back to Cabbage Site

Modal Filter Bank Efficiency

Hey everyone,

I am working on a Modal Synthesis VST and am hoping I can reduce its cpu usage. Currently the synth is very basic, and allows the user to tune 20 resonz filters to create metal timbres that can be transposed through keyboard input. Right now to generate the filter bank I am passing few arrays into a recursive opcode which sets the filter parameters and sends a signal to all of the filters.

modalSynth.csd (6.4 KB)

This ended up being more CPU intensive than I anticipated and I am wondering if anyone has any advise on the best way to modify my code to improve the efficiency. Also, in general is is better to pass a function table reference rather than an array?

Good question. I’d need to ask the Csound devs for more details on this. I imagine that function tables might be a little quicker, as I think array just get broken down into function tables anyway, but don’t quote me on that.

I can’t run your code here, I get an error about kNotes[] in your UDO. What version of Csound are you running? I’ve never used resonz, but does the mode opcode provide any CPU improvements, or any other resonant filters? The fact that you have all this wrapped into a UDO means it should be pretty quick to test other filter opcodes :thinking:

I am using csound 6.13. Here is the latest version I am working with which is running on my machine.
modalSynth.csd (7.2 KB)

I will look into reson as well-- I chose resonz because it was blowing up less in the low end, but it appears reson some options for resonators, so I will check those out as well.

Changing the arrays to function tables seems to have saved a number of resources.

That’s good to know. I just took a look now at your code. I’m not really sure what is causing the slow down. Have you tried a vanilla Csound version? It would be interesting to note if it’s the GUI overheard that is causing problems here, or the use of the certain opcodes.

[edit] I think I might have found something. You’re using widget arrays. Any widgets created using array will have an identchannel identifier. The problem with these is Cabbage needs to check them on each k-cycle for updates. In your case you have more than 100 widgets with identifier channels. This will likely cause a bottleneck.

Your options are to either code each widget manually, or use a simple scripting language to geneate your GUI code. Alternatively, you can try custom plant imports with JS to generate the GUI.

Let me know how it goes. I guess I should provide a note in the docs about using widget arrays…

I will give that a look that the plugin does eat up cpu just by existing-- the ident channels may have part to do with that.

Do you know if using loop macros is a better way to go than recursion? I am unsure how the loops end up compiling as creating multiple instances of the macro, or running through the macro a number of times. I have also considered spawning a number of instruments, but i figured that would cause quite a bit of overhead.

These are questions I can’t really answer, but I have just asked some of the Csound guys so I’ll let you know :wink:

[edit] One of the main devs got back to me just now as said that he think loops might be faster than recursion and that arrays and tables should be more or less the same. I think in this case it’s most likely the widget arrays!

The efficacy is certainly better now. I did some optimizing of the recursive udo as well as the custom plant to help with this. I am having another issue when I try to make another custom plant and import it. Cabbage creating the first plant I imported on top of the second plant for some reason and then when I stop and start the instrument in cabbage, cabbage crashes. I have given them different namespaces and that does not seem to help. The second plant also does on load correctly if I comment out the first, so I think it has to do with the import.
If I change the order of the import, it solves the problem in the GUI, but the crash still persists.

modalSynth.zip (126.6 KB)

[edit] I think the crash may have something to do with the lfo code-- specifically the hrange widget. The weird duplication issue still exists but it seem to be separate from the crashing.

The range widgets have been known to cause issues in the past. Can you try taking them out and seeing if that helps? Also, I think you and @t_grey are the only people so far to use custom plant import, so it might be a little rocky at the start. I’ll check out your example and see what I can see…

[edit] it’s definitely the hrange slider that is causing the problems. But the second custom plant is appearing where it should for me?

[edit] only one channel is being imported for hrange, which is causing a crash when you try to reload the instruments. Just looking for a fix now…

If I could lend a hand, I would… but I think the libsndfile issues with that custom csound build have struck again Rory! The example segfaults immediately after the UI appears. Not a big deal tho.

If I I understand what I’m reading the problem to be and if I recall correctly, I think the range widgets didn’t work at all when imported, and needed a bit of reworking. I think I might even have an example or two somewhere using a pair or slider widgets instead of a range widget waiting for a fix, but it was never a priority at the time.

If there was an issue with libsndfile then Cabbage wouldn’t run at all. Are you able to run other examples? I’ve narrowed down the problem, just need to find a fix…

I found this thread from back in the day discussing the range issues: Issues with hrange in imported widget groups?

Yes, I can run MOST examples… every now and then I have one of my files that used to run but it crashes, but I’m close enough to 100% and have had enough on my plate to really worry too much about it.

This is what I get running modalSynth.csd in place with it’s other required files from the zip intact:

--Csound version 6.14 (double samples) Apr 21 2020
[commit: 393bfeb2f358c2baa3e302b47337ab479b298b64]
libsndfile-1.0.29pre2
Csound tidy up: Segmentation fault
 backtrace() returned 10 addresses
0   CsoundLib64                         0x000000010f1c15b2 signal_handler + 50
1   ???                                 0x0000000000000000 0x0 + 0
2   CabbageLite                         0x000000010e9b0327 _ZN4juce20AudioProcessorPlayer21audioDeviceIOCallbackEPPKfiPPfii + 1943
3   CabbageLite                         0x000000010e7df16e _ZN22StandalonePluginHolder21audioDeviceIOCallbackEPPKfiPPfii + 222
4   CabbageLite                         0x000000010e91b6aa _ZN4juce18AudioDeviceManager15CallbackHandler21audioDeviceIOCallbackEPPKfiPPfii + 810
5   CabbageLite                         0x000000010e9152d8 _ZN4juce16CoreAudioClasses21AudioIODeviceCombiner3runEv + 2376
6   CabbageLite                         0x000000010e9cfbac _ZN4juceL15threadEntryProcEPv + 412
7   libsystem_pthread.dylib             0x00007fff61591661 _pthread_body + 340
8   libsystem_pthread.dylib             0x00007fff6159150d _pthread_body + 0
9   libsystem_pthread.dylib             0x00007fff61590bf9 thread_start + 13
[Finished in 2.7s with exit code 1]

And when you run it in Cabbage as opposed to CabageLite? But do all of your .csds fail with the custom Csound build I made? Richard is using the same build in Berklee without any problems?

1 Like

Interesting, that does make the difference. It didn’t crash right off the bat, but I’m still not sure it’s working properly.

I don’t know that I’ve noticed C2/C2L making a difference before, so that’s also interesting. But next time one of mine crashes, I’ll definitely try that first!

And no, I’m not having problems… for the most part everything is working perfectly. But there is an example or two I had that I think crash every time. I’ll probably have found them by tomorrow, since I’m working my way file by file for some minor “refactors” right now anyway. :slight_smile:

1 Like

All good now. Gees, that was so simple to fix, yet took me about an hour of stepping through the debugger to find it. :roll_eyes:

New build here

2 Likes

Thank you @t_grey and @rorywalsh so much!

Awesome work Rory! Can’t wait to get my hands on these range widgets! :smiley:

Hrm, did something go wrong with the build? OSX appears to have built unusually quick, and I don’t see either C2 or C2L bins in the drop.

You’re right. Something is off with the OSX build. Leave it with me. Probably tomorrow morning before I get a chance to look into it…

1 Like