Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 17 of 17

Thread: High frequency response of the State Variable (Chamberlin) Filter

  1. #1
    Junior Member
    Join Date
    Apr 2016
    Location
    London/UK
    Posts
    12

    High frequency response of the State Variable (Chamberlin) Filter

    I just started to explore the combination Teensy and Audio board and I'm stuck with a problem.

    This is the diagram of the processing with the source code.
    Click image for larger version. 

Name:	diagram.png 
Views:	239 
Size:	10.3 KB 
ID:	7050
    experiment_2_0a.ino

    This is frequency response diagram that shows in red the frequency response of the Teensy Audio shield then output is connected directly to the input: i2s1 connected directly to i2s2 (aka DPS bypass). In blue the frequency response of the audio card I used for the measurements.
    Click image for larger version. 

Name:	frequency linear.jpg 
Views:	170 
Size:	157.8 KB 
ID:	7052

    This below is the actual response of the filters. The blue line in the LPF output, the green line the HPF and the red line is the DSP bypass.

    What worries me is the loss of high frequencies when the filter is introduced. The cut off frequency is set at 100Hz and the high frequency loss kicks in a 4kHz. At 10kHz is around -2dB and 15kHz -3.7dB.

    For a digital filter is not a great frequency response. Did you notice anything similar before? Am I doing something wrong?
    Click image for larger version. 

Name:	filters.jpg 
Views:	171 
Size:	163.6 KB 
ID:	7051

    P.S. I enabled IMPROVE_HIGH_FREQUENCY_ACCURACY and IMPROVE_EXPONENTIAL_ACCURACY in filter_variable.cpp but it didn't make any visible difference.

  2. #2
    Junior Member
    Join Date
    Apr 2016
    Location
    London/UK
    Posts
    12
    It gets weirder and weirder. I tried with another project that doesn't involve filters:
    Click image for larger version. 

Name:	mixers diagram.png 
Views:	109 
Size:	10.7 KB 
ID:	7059
    experiment_2_0e_mixer.ino

    The resulting frequency response is this:
    Click image for larger version. 

Name:	mixers freq.png 
Views:	95 
Size:	56.3 KB 
ID:	7060
    In red the frequency response with i2s1 connected directly to i2s2. In green the frequency response of the project.

    Please note that the only thing that I changed between the two frequency response measurements is the piece of software generated by GUItool.

    Am I the only one that experienced odd and unpredictable frequency response at high frequencies?

    (for the frequency measurement I used HOLMImpulse. Free download)

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,135
    That is very strange. Might be a bug in the filter code?

    How are you doing these tests? What hardware & software do I need to recreate the same test and get those plots?

  4. #4
    Junior Member
    Join Date
    Apr 2016
    Location
    London/UK
    Posts
    12
    Hi Paul,

    The tests were very straight forward. I connected:

    Audio card output (Edirol FA-101, output 3) to both channel of the line input of the audio board.
    Audio board line output to audio card input (input 2).

    The software that I used to measure the frequency response is HOLMImpulse. It is a free download.

    The source code is available in the first post.

    I agree. It is very strange. Please note that in this diagram:
    Click image for larger version. 

Name:	filters.jpg 
Views:	96 
Size:	163.6 KB 
ID:	7072
    The only difference between the red line and the green line is the software. Nothing changed regarding hardware or connections.

  5. #5
    Junior Member
    Join Date
    Apr 2016
    Location
    London/UK
    Posts
    12
    It doesn't look like there is an overwhelming interest for this issue but just in case, I think I managed to find the exact cut off frequency of the attenuation. The -3dB point looks located a 11kHz. It is suspiciously close to 44.1Khz/4 but it might be just a coincidence.

  6. #6
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,135
    Maybe there's some sort of problem with how the filter is doing the 2X internal oversampling?

  7. #7
    Junior Member
    Join Date
    Apr 2016
    Location
    London/UK
    Posts
    12
    Quote Originally Posted by PaulStoffregen View Post
    Maybe there's some sort of problem with how the filter is doing the 2X internal oversampling?
    My knowledge of DSP processing is next to zero but it sounds a reasonable assumption.

  8. #8
    Quote Originally Posted by Ardaudio
    It is suspiciously close to 44.1Khz/4 but it might be just a coincidence.
    That almost rings a bell.

    I have faint memories of the Chamberlin SVF being unstable above fs/4. I just leafed through Hal's book, but I'm not finding it right now.

    There's a link in the source file to a Music DSP thread:
    http://www.musicdsp.org/showArchiveC...p?ArchiveID=92

    Where there's a line that seems to indicate that the 2x oversampling moves that stability limit to fs/2...there's also a commenter implying that the 2x oversampling is pretty crude, just recalculating with the same input sample a second time.

    But am I reading your second post correctly; are you seeing this HF falloff with only a mixer (no filters at all) in the audio chain, but not seeing the falloff if input leads directly to output?

  9. #9
    Junior Member
    Join Date
    Apr 2016
    Location
    London/UK
    Posts
    12
    Quote Originally Posted by B.Jacquot View Post
    (...)I have faint memories of the Chamberlin SVF being unstable above fs/4
    If this were the case, it would be a little bit of a disaster for me. With the biquad filter unable to go below 400Hz and the Chamberlin cutting above 11kHz, I'd have to abandon the Teensy+audio idea. I planned to use it professionally for a couple of products but I can't do it without filters.

    Quote Originally Posted by B.Jacquot View Post
    But am I reading your second post correctly; are you seeing this HF falloff with only a mixer (no filters at all) in the audio chain, but not seeing the falloff if input leads directly to output?
    Yes, you are reading the second post correctly. Frankly, when I saw the frequency response, my jaw dropped.

    As you said, if I connect the input block directly to the output block, everything is as expected: apart from a gentle roll-off at the lower frequencies, the frequency response is linear. When I connected the mixers the high frequencies were attenuated.

    It is so weird that I don't know what to think. Can it be a piece of code that remained active after I removed the filter and I designed the new diagram?

    I double checked that the only thing that changed was the software. I didn't touch any cable, controls on the audio card or options in the software I used for measuring the frequency response.

    On a general note, I am really surprised nobody noticed this before. Frequency response and distortion are the first things that usually people check in an audio system. I find hard to believe the nobody checked the actual frequency response during the development of the filters. Perhaps it was checked but I'm doing something wrong? I'm confused.

  10. #10
    Can it be a piece of code that remained active after I removed the filter and I designed the new diagram?
    If there's a chance that you changed the program, but it didn't upload, then the previous one would still be active. It's very unlikely that if you changed it, and the upload was complete, that there's somehow "old code" hanging around.

    Actually, there's one other place that old code might persist - in the codec chip on the audio board. The codec has a pile of features inside, including filters - check the datasheet for details. If those filters got set, they might persist, even when loading new programs. Similarly, most audio DACs perform significant oversampling, which is in effect another filter - but the SGTL5000 datasheet doesn't ever use the word oversampling. It sounds too good to not be using it.

    Try a patch where the left input leads straight to the left output, but the right channel has some different blocks inserted - a mixer, a multiplier. Then you can compare HF behavior, perhaps nailing it down to specific blocks. I don't have a ready explanation as to why the mixer would alter the frequency response. You might also check to see if the headphone output is any different - be warned, it's DC coupled.

    If you want filters that don't do funny things at fs/4 and fs/2, you might consider an analog solution...or a higher-res DSP solution that puts fs/4 above the audible band.

    Frequency response and distortion are the first things that usually people check in an audio system. I find hard to believe the nobody checked the actual frequency response during the development of the filters.
    It's a $15 board that is far superior to the 8-bit mangling I'd been doing before. I'm not looking this gift horse in the mouth - my ears tell me it's good enough.

  11. #11
    Junior Member
    Join Date
    Apr 2016
    Location
    London/UK
    Posts
    12
    Quote Originally Posted by B.Jacquot View Post
    If there's a chance that you changed the program, but it didn't upload, then the previous one would still be active. It's very unlikely that if you changed it, and the upload was complete, that there's somehow "old code" hanging around.
    I entirely agree. The hypothesis of old code hanging around is pretty unlikely.

    Everything is possible but I'm pretty confident I uploaded the program before the test. I repeated the test to be sure.

    Quote Originally Posted by B.Jacquot View Post
    Try a patch where the left input leads straight to the left output, but the right channel has some different blocks inserted - a mixer, a multiplier. Then you can compare HF behavior, perhaps nailing it down to specific blocks. I don't have a ready explanation as to why the mixer would alter the frequency response. You might also check to see if the headphone output is any different - be warned, it's DC coupled.
    It's a good suggestion - thanks! I'll see if I can narrow it down to a set of simple cases that point in a clear direction.

    I will also re-test the first example just to be on the safe side.

    Quote Originally Posted by B.Jacquot View Post
    If you want filters that don't do funny things at fs/4 and fs/2, you might consider an analog solution...or a higher-res DSP solution that puts fs/4 above the audible band.
    Thanks for the suggestion B.Jacquot but I already use analogue solutions. I would like to be sure that the issues I'm experiencing are due to hardware limitations and not software bugs before throwing in the bin the idea of using Teensy+audio. I get your point though.

    Quote Originally Posted by B.Jacquot View Post
    It's a $15 board that is far superior to the 8-bit mangling I'd been doing before. I'm not looking this gift horse in the mouth - my ears tell me it's good enough.
    Fair enough. If it sounds good to your ears and everything works as it should for your applications, it's a good thing.

    My observation was due to the fact that I usually try to get objective measures when I work on something. It doesn't mean that my way of operating is better in absolute terms. It's just the way I work and I was taught. My apologies if my comment sounded judgemental and/or disrespectful.

  12. #12
    Junior Member
    Join Date
    Apr 2016
    Location
    London/UK
    Posts
    12
    I run further tests:

    == filters =================

    I re-run the same tests of first post. I uploaded multiple times with a frequency response test after every upload. I also tested the frequency before and after a board reboot (power off/on). The result was always the same.

    I also tried with the headphone output. The frequency response is the same of the line output.

    == mixer ===================

    This is a little bit more complicated and weird. This is the code I used.

    Code:
    /*
    * f_response_1_0
    *
    *
    *
    */
     
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    // GUItool: begin automatically generated code
    AudioInputI2S            i2s1;           //xy=87,167
    AudioMixer4              mixer1;         //xy=300,239
    AudioMixer4              mixer2;         //xy=506,302
    AudioOutputI2S           i2s2;           //xy=530,169
    AudioConnection          patchCord1(i2s1, 0, mixer1, 0);
    AudioConnection          patchCord2(i2s1, 0, i2s2, 0);
    AudioConnection          patchCord3(i2s1, 1, mixer1, 1);
    AudioConnection          patchCord4(mixer1, 0, i2s2, 1);
    AudioConnection          patchCord5(mixer1, 0, mixer2, 0);
    AudioConnection          patchCord6(mixer1, 0, mixer2, 1);
    AudioControlSGTL5000     sgtl5000;       //xy=86,41
    // GUItool: end automatically generated code
    
    
    
    /***********************************************
    ***** setup() **********************************
    ***********************************************/
    void setup()
    {
      /* 
      * Audio interface/objects initialization
      */
      AudioMemory(100);
      sgtl5000.enable();         // Enable the audio shield
      sgtl5000.inputSelect( AUDIO_INPUT_LINEIN );  // enable line-in
      sgtl5000.volume(0);        // disable headphone out
      sgtl5000.muteHeadphone();  // disable headphone out
      sgtl5000.micGain(0);       // minimum gain for mic in
      sgtl5000.unmuteLineout();  // enable line out
      sgtl5000.lineInLevel(5);   // 3.13V p-p
      sgtl5000.lineOutLevel(29); // 3.16V p-p
      sgtl5000.dacVolume (1); // set the pre-dac attenuation (1=no attenuation)
      sgtl5000.audioProcessorDisable();
      /*----------------------------------------*/
    
    
      mixer1.gain(0, 0.5);
      mixer1.gain(1, 0.5);
      mixer1.gain(2, 0.0);
      mixer1.gain(3, 0.0);
    
      mixer2.gain(0, 0.1);
      mixer2.gain(1, 0.1);
      mixer2.gain(2, 0.1);
      mixer2.gain(3, 0.1);
      
    }
    
    
    /***********************************************
    ***** loop *************************************
    ***********************************************/
    void loop()
    {
      int n = 0;
      
      //  n = 0  
      //  n = 1  
      //  n = 2
      
      switch( n )
      {
        case 0:
          mixer2.gain(0, 0.0);
          mixer2.gain(1, 0.0);
          mixer2.gain(2, 0.0);
          mixer2.gain(3, 0.0);
          break;
        case 1:
          mixer2.gain(0, 0.5);
          mixer2.gain(1, 0.5);
          mixer2.gain(2, 0.0);
          mixer2.gain(3, 0.0);
          break;
        case 2:
          mixer1.gain(0, 0.5);
          mixer1.gain(1, 0.5);
          mixer1.gain(2, 0.5);
          mixer1.gain(3, 0.5);
          break;
      }
    }
    
    
    // EOF
    I uploaded the software and measured the frequency response. The frequency response was the same of the frequency diagram in the second post. I re-run the frequency analysis 3 times - same result.

    Then I rebooted the board and the frequency response changed. It became linear. Again, measured 3 times - no changes.

    I changed a comment to force a re-compile and uploaded again. The frequency response stayed linear.

    I re-uploaded the filters software of the first post, measured the frequency, the result was the same as in the previous filter tests.


    This is the interesting part: I compiled/uploaded the mixer test (i.e. the software of the second post) and measured the frequency. The high-frequency cut returned back. The frequency plot was the same of the second post.

    I rebooted the board and the frequency response kept cutting the high frequency.

    I rebooted the board again and the frequency response returned linear.

    In all the tests above I didn't plug/unplug any connector. I only used keyboard and mouse.

  13. #13
    A couple of quick questions:

    When you say "reboot," exactly what steps are you taking?

    Also, when the you see the HF droop, is it on both channels? If the channel that's direct input->output experiences it, it would seem to exonerate the mixer.

    If that's true, a guess would be that the codec is either coming up in an unpredictable state and not being fully initialized, or something in it is being overwritten.

  14. #14
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,135
    Quote Originally Posted by Ardaudio View Post
    As you said, if I connect the input block directly to the output block, everything is as expected: apart from a gentle roll-off at the lower frequencies, the frequency response is linear. When I connected the mixers the high frequencies were attenuated.

    It is so weird that I don't know what to think.
    This is *really* weird indeed.

    On a general note, I am really surprised nobody noticed this before. Frequency response and distortion are the first things that usually people check in an audio system. I find hard to believe the nobody checked the actual frequency response during the development of the filters.
    When I wrote this filter code, I did quite a lot of testing with a function generator to the line-in and the filter to the line-out, viewing with my oscilloscope. I also did several tests with specific input signals and compared numerical output to a prototype of the code on my PC using double precision floats.

    Of course, I also did quite a bit of listening, but losing the top octave is the sort of thing that could go unnoticed in casual listening. That's why I did most of the testing with a signal generator and oscilloscope.

    Perhaps it was checked but I'm doing something wrong? I'm confused.
    Might be a subtle bug in the code, or the SGTL5000, or the testing methodology. Very hard to guess.

    Realistically, I probably won't be able to really dig into this until mid-June. It definitely is saved on my list of reproducible problems to investigate.

  15. #15
    Junior Member
    Join Date
    Apr 2016
    Location
    London/UK
    Posts
    12
    Quote Originally Posted by B.Jacquot View Post
    When you say "reboot," exactly what steps are you taking?
    Sorry, it wasnt 'very clear in my post. I meant that I powered off the board for a couple of seconds and I switched on the power again afterwards.

    Quote Originally Posted by B.Jacquot View Post
    Also, when the you see the HF droop, is it on both channels? If the channel that's direct input->output experiences it, it would seem to exonerate the mixer.
    Good point. The HF drop was only on the right channel (i.e. the channel with the mixer). The left channel had the output connected directly to the input and there wasn't any HF drop.

  16. #16
    Junior Member
    Join Date
    Apr 2016
    Location
    London/UK
    Posts
    12
    Quote Originally Posted by PaulStoffregen View Post
    This is *really* weird indeed.
    I couldn't agree more Paul

    Quote Originally Posted by PaulStoffregen View Post
    Might be a subtle bug in the code, or the SGTL5000, or the testing methodology. Very hard to guess.
    If you have any suggestion regarding further tests please let me know. I'd be very happy to help.

    Quote Originally Posted by PaulStoffregen View Post
    Realistically, I probably won't be able to really dig into this until mid-June. It definitely is saved on my list of reproducible problems to investigate.
    I understand the situation and I appreciate your help on this. If you need any info, please post here or do feel free to contact me with a PM.

    If I had to give a priority to the problems, I would give a higher priory to the high-frequency cut of the filter but you know better than anybody else what is the best way to move forward.

  17. #17
    Quote Originally Posted by Ardaudio View Post
    Sorry, it wasnt 'very clear in my post. I meant that I powered off the board for a couple of seconds and I switched on the power again afterwards.
    OK, that's reasonable. My concern was that there's more than meets the eye going on when you press the button on the teensy itself - it'll invoke the bootloader and reflash the board if you've got the loader app running.

    Quote Originally Posted by Ardaudio View Post
    Good point. The HF drop was only on the right channel (i.e. the channel with the mixer). The left channel had the output connected directly to the input and there wasn't any HF drop.
    That implicates the mixer, rather than the codec.

    Can you try two more things:

    1. #1: swap the channels in the previous patch - put the passthru on the other side.
    2. #2: Try a patch that uses a multiply object instead of the mixers.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •