Help STILL needed testing and/or debugging intermittent DC blocker behavior

Follow this link for the latest request for help. The more important immediate need is for testers to see if a particular version can be released. Thanks!

I hope to release Venom v2.8 to the library this weekend, but I am being confounded by an apparent bug in my DC blocker (high pass filter with cutoff at 2Hz) that causes it to fail on some machines, and work fine on others :frowning:

So my first thought is I must be failing to initialize something somewhere, leading to “random” behavior. But for the life of me I cannot find the problem.

Currently I am aware of 3 different cases where my DC blocker is failing:

  • VCA MIX 4 failed to produce output for @MinorNoise on his windows machine if DC offset removal is enabled. This was using Venom v2.7. It works fine for me on my Windows machine, but for a brief while it was failing on my MacBook Air. Unfortunately it no longer fails on my Mac.
  • My new VCO Lab oscillator in soon to be released Venom 2.8 has linear FM CV input with AC coupling by default. I implement the AC coupling using the same DC blocker filter. It works fine for me on both my Win 10 desktop and MacBook Air. But it fails for Omri on his Win 11 desktop and Win 10 laptop. By fail I mean the input is completely blocked if the AC coupling is active.
  • The same VCO Lab has optional DC offset removal on all outputs, and all outputs are silenced for Omri if the DC offset removal is activated, yet for me it works fine.

So the problem seems to be isolated to my DC blocker filter. I have made sure I initialize everything I can think of, but I can’t seem to crack this problem.

I sure could use some help!

Venom 2.8 development binaries are available at reset DCBlock filter as part of filter initialization · DaveBenham/VenomModules@05b5893 · GitHub

I assume the relevant VCO Lab code should be in Filter.hpp and Oscillator.cpp, with the array of filters named dcBlockFilter.

I assume that if the VCO Lab problem can be solved, the mixer solution will be self evident.

Don’t know if this has anything to do with it, but to make a filter with a sharp feature at a low freq you need more resolution than a float. I use doubles for this. Does it work at a higher frequency?

That said, I’ve usually only seen excessive noise with floats…

1 Like

I don’t see how that can be the problem. The results are great on my machine, but the filter totally fails for others when using the exact same patch and sample rate. We are not talking unwanted noise - but rather total lack of signal output from the filter.

well, make sure to post what the answer is when you find it.

On my M1 mac the VCO lab goes completely silent as soon as DC block is enabled, no output produces any signal. Not helping, I know…

Yep. Yet on my M1 laptop it works perfectly, both ARM64 and x64. And I downloaded the same binaries from gitHub.

So I don’t think it is the logic of the actual filter code, but rather something wrong with how something is getting initialized (or not). I suppose the problem could be isolated from the DC block code, and it is just chance as to what gets clobbered. But it is awfully suspicious that nothing else seems to be affected, and the same DC block code fails in different modules, and at different points within the same module.

The worst part is, I can’t get a failure on any of my machines, so it is hard to test.

Aargh.

Maybe run it through address/memory sanitizer and see if that throws up anything? Valgrind may also be useful?

1 Like

I downloaded your devel. Binaries and both Mix 4s work fine for me with the different DC options combined with the other ones. VCO Lab doesn’t show up, despite it being in the manifest.

Windows 11. Rack 2.5.2.

Edit: VCO Lab shows under Linux and, indeed, goes silent when I activate the DC blocker, and so does Mix 4.

Are you sure TRCFilter and float_4 play nice together?

Ugh, thanks.

Well, TRCFilter is a template, and it compiles without error or warning, and it works on some machines. So… yes?

If they were not compatible, then I don’t see why it would work on some machines, and not on others.

And I have coded DCBlockFilter_4 the same way I did OversampleFilter_4, and I haven’t any reported failures with oversampling.

But if someone can explain why it is not compatible, then I am all ears.

Every time I have ever had inconsistent behavior like this, it has always been a simple initialization or bad pointer issue. I am expecting that to be the case this time as well. But damn, it sure is elusive.

I am beginning to worry it may be some uninitialized pointer, which can be a beast to find because the culprit may be completely isolated from the failing code. But if so, it is just weird that it only affects my DC blocker, and never crashes.

I haven’t any experience with either of those.

I tried address/memory sanitizer by adding -fsanitize=address to the cpp compile options. But I got a boat load of undefined reference to __asan_XXXX error messages.

Not sure how to use that properly.

Works fine on my Win11 laptop (Rack 2.5.2) in various oversampling and sample rate combinations. Will try other machines later. Also, nothing jumped out re: the code on a quick look. Weird problem! Good luck!

yes

I can be a pain. I always run it under linux in a VM. And I run it on windows, but only for my unit test suite.

Thanks everyone for your input, but I give up… (for now)

Rather than try and figure out why my DC block filter fails on some machines, I decided to implement an entirely different algorithm. It is much simpler and kinder to the CPU as well, so maybe all for the better.

Hopefully I am not simply kicking the can down the road, and the problem is actually fixed. Fingers crossed…

Here is the new binary: New implementation of DCBlockFilter, hopefully solves "random" failures · DaveBenham/VenomModules@26b8025 · GitHub

I hope some of you can test this new version and report back. I use the new method everywhere I have DC offset removal within the Venom plugin.

1 Like

Works for me, both Linux and Windows.

1 Like

Well that is a good sign :slight_smile:

Hopefully I can get a thumbs up from a few more people for whom it failed before.

Well, all outputs work fine with DC Block with the new algo on my M1. So appears a good solution! Mix I still need to work out how to get going, but that quick test said: problem solved

Hot diggity dog! Omri reports it is working on both of his Windows machines. So I think this issue has been put to bed! Thanks everyone for your input.

I would like to know why the old DC blocking filter was having problems. But not enough to continue to investigate. I have bigger fish to fry - like releasing Venom 2.8!

5 Likes

Well damn! The working code was naive and did not have a constant cutoff frequency as sample rate and/or oversampling rate was changed. So I modified the code a bit to get consistent behavior, and of course it worked perfectly, but broke for Omri again.

There is no way the changes I made should cause the code to fail, so I am all but convinced that the underlying problem has nothing to do with the DC Blocker, yet the bug manifests itself by breaking that code, yet seemingly nothing else.

So I have two big favors to ask.

1- Test this naive version so I can get a release out the door

I have a final naive version that seems to work, and I need to verify across a wide collection of users that it works reliably. It is not OS dependent, but rather machine dependent. For example, all versions work on my Windows 10, but not on Omri’s Win 10 laptop or Win 11 desktop. So I could use as many testers as possible across all platforms.

Here is the tentative release binary (version 2.8.0dev3-a112d5a):

Also if you could test this older version 2.8.0dev-05b5893 that I know fails for some, so I can confirm that the newer version actually fixed something for some of you.

Things to test:

  • verify VCO Lab has output when DC removal button is active
  • verify linear FM works while AC coupled (the default configuration)
  • verify any of the Venom mixers (Mix 4, Mix 4 Stereo, VCA Mix 4, VCA Mix 4 Stereo) continue to give output when DC removal button is active

If this seems to work for all, then I will use this version for now and publish and release to the library. I am pretty sure there is still an underlying bug, but if it is not manifesting any problems, then I am willing to live with it for now. I am really excited about these new modules.

Different sample rates / oversample rates give different DC removal results, and it attenuates bass tones excessively as you increase sample rate / oversample rate. But it is better than nothing, and can be bypassed if needed.

2- Help me diagnose and fix the underlying bug

I think I need the help of an experienced coder for whom the improved code does not work, who is willing to work with me, compiling my code, and helping me figure out what on earth is going on. It is very frustrating that I cannot get the code to fail for me, so I am unable to test effectively.

I am thinking the problem probably has nothing to do with the DC blocker, but an unrelated bad pointer, or something is somehow causing the DCBlocker to fail.

Here is the original DC blocker code that failed for some and not for others:

class DCBlockFilter_4 {
  public:
    void init(float sampleRate){
      f[0].setCutoffFreq(2.f/sampleRate);
      f[1].setCutoffFreq(2.f/sampleRate);
      f[2].setCutoffFreq(2.f/sampleRate);
      f[3].setCutoffFreq(2.f/sampleRate);
      reset();
    }
    void reset(){
      f[0].reset();
      f[1].reset();
      f[2].reset();
      f[3].reset();
    }
    rack::simd::float_4 process(rack::simd::float_4 val){
      f[0].process(val);
      f[1].process(f[0].highpass());
      f[2].process(f[1].highpass());
      f[3].process(f[2].highpass());
      return f[3].highpass();
    }
  private:
    rack::dsp::TRCFilter <rack::simd::float_4>f[4]{};
};

Here is the naive code that I hope works for all


class DCBlockFilter_4 {
// Naive version that doesn't adjust for sample rate or oversampling, so cutoff is not consistent
// Also attenuates bass tones too much as sample rate and/or oversampling rate rises
  public:
    rack::simd::float_4 val = rack::simd::float_4::zero();

    rack::simd::float_4 process( rack::simd::float_4 x ) {
      val = x - prevX + static_cast<rack::simd::float_4>(0.999f) * val;
      prevX = x;
      return val;
    }

  private:
    rack::simd::float_4 prevX = rack::simd::float_4::zero();
};

And below are two related forms that compensate for sample rate and oversample rate. Nothing fancy, they work fine for me, but not for Omri.

/*
class DCBlockFilter_4 {
// This version is mysteriously not working on some machines
// Be sure to uncomment `, oversample` in process calls if reverting to this version
  public:
    rack::simd::float_4 val() {
      return prevY;
    }
    
    rack::simd::float_4 process( rack::simd::float_4 x, int over = 1 ) {
      float r = 1.f - 250.f / rack::settings::sampleRate / static_cast<float>(over);
      rack::simd::float_4 y = x - prevX + static_cast<rack::simd::float_4>(r) * prevY;
      prevX = x;
      prevY = y;
      return y;
    }
  
  private:
    rack::simd::float_4 prevX = rack::simd::float_4::zero();
    rack::simd::float_4 prevY = rack::simd::float_4::zero();
};
*/

/*
class DCBlockFilter_4 {
// This version is mysteriously not working on some machines
// But I really like the behavior when it does.
//  - Minimal bass attenuation
//  - Consistent at all sample rates and oversampling rates
//  - Excellent DC offset filtering
// Be sure to uncomment `, oversample` in process calls if reverting to this version
  public:
    rack::simd::float_4 val() {
      return rtn;
    }
    
    rack::simd::float_4 process( rack::simd::float_4 x, int over = 1 ) {
      double r = 1. - 100. / static_cast<double>(rack::settings::sampleRate) / static_cast<double>(over);
      for (int i=0; i<4; i++){
        double y = static_cast<double>(x[i]) - prevX[i] + r * prevY[i];
        prevX[i] = static_cast<double>(x[i]);
        prevY[i] = y;
        rtn[i] = static_cast<float>(y);
      }
      return rtn;
    }
  
  private:
    double prevX[4]{};
    double prevY[4]{};
    rack::simd::float_4 rtn = rack::simd::float_4::zero();
};
*/
1 Like

Is this code on github?