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

Thread: Modulated Delay: Chorus/Flanger

  1. #1

    Modulated Delay: Chorus/Flanger

    Hello,

    i am trying to build a modulated delay for the audio library. The whole thing should work as a chorus/flanger.

    As base I used effect_delay.*. I added an input as modulation source. The audio data is written into a circular buffer (like the delay) and an index is calculated by means of the modulation signal, which gets a value from the circular buffer. I added a spline interpolation (found on the net), so that values between two index-values from the circular buffer can be adjusted by interpolation.

    In principle this works. But I have strange artifacts (cracking) always when the sign of the (sinus or triangle) wave of the modulation signal (with or without interpolation!) changes.

    After searching for hours, I can't find a cause. Maybe someone from the pros has an idea and can help?

    TIA, Holger

    P.S.: Complete test code for a Teensy with SGTL5000: Test_ModulatedDelay.zip (outputs a modulated 1000Hz sine)

  2. #2
    Senior Member Blackaddr's Avatar
    Join Date
    Mar 2017
    Location
    Canada
    Posts
    209

    Post

    Quote Originally Posted by C0d3man View Post
    Hello,

    i am trying to build a modulated delay for the audio library. The whole thing should work as a chorus/flanger.

    As base I used effect_delay.*. I added an input as modulation source. The audio data is written into a circular buffer (like the delay) and an index is calculated by means of the modulation signal, which gets a value from the circular buffer. I added a spline interpolation (found on the net), so that values between two index-values from the circular buffer can be adjusted by interpolation.

    In principle this works. But I have strange artifacts (cracking) always when the sign of the (sinus or triangle) wave of the modulation signal (with or without interpolation!) changes.

    After searching for hours, I can't find a cause. Maybe someone from the pros has an idea and can help?

    TIA, Holger

    P.S.: Complete test code for a Teensy with SGTL5000: Test_ModulatedDelay.zip (outputs a modulated 1000Hz sine)
    You can't use a raw triangle wave as a modulation source directly, it will cause glitching because a perfect triangle has infinite bandwidth due to discontinuities at the peaks/troughs. This infinite bandwidth causes you aliasing due to violating Nyquist. Your triangle wave must be band limited, i.e. rounded edges. You can manually create a smoothed triangle Waveform, or you can pass your LFO output through an IIR filtering processing. Lots of different ways to do it, you just need to always stay bandlimited in audio, everything very smooth, no sudden jumps of any kind! :-)

  3. #3

    Lightbulb

    Quote Originally Posted by Blackaddr View Post
    You can't use a raw triangle wave as a modulation source directly, it will cause glitching because a perfect triangle has infinite bandwidth due to discontinuities at the peaks/troughs. This infinite bandwidth causes you aliasing due to violating Nyquist. Your triangle wave must be band limited, i.e. rounded edges. You can manually create a smoothed triangle Waveform, or you can pass your LFO output through an IIR filtering processing. Lots of different ways to do it, you just need to always stay bandlimited in audio, everything very smooth, no sudden jumps of any kind! :-)
    Ok, you told me that a few months ago, but I don't understand it until now. I usually have to try something like this by myself and try to solve the individual problems one after the other.

    I have now put a simple IIR filter behind the modulation input and before calculating the modulation-index. Unfortunately I could not try it out or hear it yet. To calculate the coefficients for the IIR filter (and even to get simple C-code for it) the following page seemed to be very helpful: http://www-users.cs.york.ac.uk/~fish...lter/trad.html

    I'll post my results here then.

    Thanks, Holger

  4. #4
    Senior Member DD4WH's Avatar
    Join Date
    Oct 2015
    Location
    Central Europe
    Posts
    404
    Hi Holger,

    give this a try also, its a very nice filter designer and also plots the response and gives you the coefficients. Also helpful is the possibility to test the filters with different accuracies of your calculations and scalings (fixed point vs. floating point, 16bit vs 24bit etc.).

    http://www.iowahills.com/

    IIR code can be found there also, but maybe you would like to give the CMSIS library a try, which has highly optimized code for many types of filters:

    https://www.keil.com/pack/doc/CMSIS/...ascadeDF1.html

    And finally you could look at the code in the audio library, which also contains highly optimized code for fixed point implementation of IIR biquad filters. You can also find formulae for calculating coefficients on-the-fly for IIR biquads in that code.

    Have fun with the Teensy,

    Frank DD4WH

  5. #5
    Senior Member Blackaddr's Avatar
    Join Date
    Mar 2017
    Location
    Canada
    Posts
    209
    Quote Originally Posted by C0d3man View Post
    Ok, you told me that a few months ago, but I don't understand it until now. I usually have to try something like this by myself and try to solve the individual problems one after the other.
    Don't worry! We're hear to help.

    You might also want to try something dead simple first. Rather than designing a proper BiQuad IIR filter, what about just a 1st order IIR where you have

    Code:
    // Simple 1st order IIR, mix the new value with the old value
    float alpha = 0.9f; // 90% new value, 10% feedback
    filteredOutput = (newValue * alpha) + filteredOutput*(1 - alpha);
    When alpha = 1.0f, no filtering is performed, as you turn alpha down you are increasing the filter feedback making it more and more of a low pass filter. This will obviously modify the shape of the Triangle in an assymetric way, but it might provide enough smoothing to eliminate aliasing caused by this particular issue. Since the triangle shape has a large impact on how it will sound, you may want to replace it later with something more complex like a precomputed waveform table or apply higher order IIR filtering using BiQuads, etc.

  6. #6

    Quote Originally Posted by DD4WH View Post
    Hi Holger,

    give this a try also, its a very nice filter designer and also plots the response and gives you the coefficients. Also helpful is the possibility to test the filters with different accuracies of your calculations and scalings (fixed point vs. floating point, 16bit vs 24bit etc.).

    http://www.iowahills.com/

    IIR code can be found there also, but maybe you would like to give the CMSIS library a try, which has highly optimized code for many types of filters:

    https://www.keil.com/pack/doc/CMSIS/...ascadeDF1.html

    And finally you could look at the code in the audio library, which also contains highly optimized code for fixed point implementation of IIR biquad filters. You can also find formulae for calculating coefficients on-the-fly for IIR biquads in that code.

    Have fun with the Teensy,

    Frank DD4WH
    Many thanks @Frank! Very good information. Just tried a little bit around and learned much new things about this topic!

    Regards, Holger

  7. #7
    Quote Originally Posted by Blackaddr View Post
    Code:
    // Simple 1st order IIR, mix the new value with the old value
    float alpha = 0.9f; // 90% new value, 10% feedback
    filteredOutput = (newValue * alpha) + filteredOutput*(1 - alpha);
    When alpha = 1.0f, no filtering is performed, as you turn alpha down you are increasing the filter feedback making it more and more of a low pass filter. This will obviously modify the shape of the Triangle in an assymetric way, but it might provide enough smoothing to eliminate aliasing caused by this particular issue. Since the triangle shape has a large impact on how it will sound, you may want to replace it later with something more complex like a precomputed waveform table or apply higher order IIR filtering using BiQuads, etc.
    Many thanks!

    I have tried a few things and hope to have learned a lot in the meantime. Currently I use filter coefficents for a lowpass calculated with the Iowa-Hills-IIR-Filter-Designer, which I use with
    Code:
    arm_biquad_cascade_df1_f32(&filter, modulation_f32, modulation_f32, AUDIO_BLOCK_SAMPLES);
    for the modulation data (f=1000Hz)

    Strangely enough, I still have "click" noises. I think I have a problem accessing the ring buffer somewhere.

    One more question: If I should make a triangle waveform a bit smoother by lowpassing it, why not using a sine wave for modulation?

    Regards, Holger

  8. #8
    Senior Member Blackaddr's Avatar
    Join Date
    Mar 2017
    Location
    Canada
    Posts
    209
    Yes, use a sine wave. When I made my chorus I got it working glitch free with a sinewave first, then moved on to investigating ways of bandlimiting the other waveforms like triangle.

Posting Permissions

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