velipso / sndfilter

Algorithms for sound filters, like reverb, dynamic range compression, lowpass, highpass, notch, etc
BSD Zero Clause License
445 stars 70 forks source link

Reverb performance issue #1

Closed cuinjune closed 7 years ago

cuinjune commented 7 years ago

Hi, first of all Thank you so much for your amazing works. I tried using your reverb and it works well and sounds very good. But it seems like it is pretty heavy in terms of CPU usage. I wonder if you have any suggestion to reduce it's CPU usage other than reducing the channel to mono. Thanks!

velipso commented 7 years ago

Here are some ideas -- I haven't tried these, this is just off the top of my head. Give these a try and see what helps and what is acceptable.

You can reduce the oversampling by changing reverb.h:

#define SF_REVERB_OF 4

Try 1 to disable oversampling entirely, or 2 or 3 to just perform less oversampling.

Or you can start commenting out sections of the algorithm inside the sf_reverb_process function in reverb.c:

for (int i = 0; i < size; i++){
    // early reflection
    // ...

    // oversample the single input into multiple outputs
    // ...

    // for each oversampled sample...
    for (int i2 = 0; i2 < rv->oversampleL.factor; i2++){
        // dc cut
        // ...

        // noise
        // ...

        // diffusion
        // ...

        // cross fade
        // ...

        // bass boost
        // ...

        // dampening
        // ...

        // update cross fade bass boost delay
        // ...

        //
        float D1 = ...
        // delay stuff...

        osL[i2] = ... final oversampled output
        osR[i2] = ... final oversampled output
    }

    // ...reverse oversample
    output[i] = (sf_sample_st){ outL, outR };
}

In particular, the the following regions might be good candidates for commenting out:

Don't be intimidated by the formulas and what they're doing. Just try things and see. Most sections don't rely on the previous sections, and everything is mostly just stepping forwards modifying the sample one stage at a time. Just follow the variables.

velipso commented 7 years ago

Also for anyone else wondering: reducing the channels to mono would require a bit of changes to the source code. The current code processes stereo exclusively.

cuinjune commented 7 years ago

Thank you for your brilliant suggestion.

First of all, reducing the oversampling amount didn't really help. So I tried commenting out sections one by one as you suggested and the diffusion part turned out to be the most expensive section.

After some tests, I decided to comment out diffusion, cross fade and bass boost sections and it still sounded like a reverb :)

The original version used about 53 ~ 55% CPU for running 10 reverbs on my Macbook Pro. And after commenting out the 3 sections, now it uses about 32 ~ 34% CPU. I think it's okay to use for desktop applications but maybe a bit too expensive for mobiles.

Other than the performance issue, I think the reverb is really decent :) Once again, Thank you so much!

neevek commented 5 years ago

Also for anyone else wondering: reducing the channels to mono would require a bit of changes to the source code. The current code processes stereo exclusively.

I am new to all this DSP thing. I need mono support for this library, I have looked into the code, I can see that some calculations exchanged L and R samples, what's your suggestions for a newbie like me to start making it support mono?

velipso commented 5 years ago

I would change things one step at a time, and check the results. Start by making a WAV file with left and right channels the same, and send it through the reverb.

Then start removing/simplifying parts. Each step of the way, run through the same file, and make sure it doesn't sound drastically different.

If I remember correctly, some parts of the processing are strictly for bouncing the signal between L and R -- you could remove those entirely.

Just take your time; it's a little tedious, but that's how it goes.