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

Thread: Wavefolder possible?

  1. #1

    Wavefolder possible?

    Is wavefolding possible to do with current audio library objects?
    I'm aware that there is no wavefolder objects, i'm trying to find if there is a cleaver way of doing is with the objects avaliable.

    Here is a good exemple of what wavefolder does:
    https://www.youtube.com/watch?v=JS18BX4yIPQ

    Thanks!

  2. #2
    Senior Member
    Join Date
    Jul 2020
    Posts
    969
    effect waveshaper might be a possible approach, but I think this really needs a custom object to do the folding simply
    and efficiently.

  3. #3
    Senior Member
    Join Date
    Jul 2020
    Posts
    969
    I got bored and had a go at doing this...

    Created an AudioEffectWaveFolder class, here's the git hub links, but I've included at the end too.

    https://github.com/MarkTillotson/Aud...t_waveshaper.h
    https://github.com/MarkTillotson/Aud...waveshaper.cpp

    Its based on the AudioEffectMultiply, taking two inputs and multiplying them, the idea being one is the slow modulation control from
    an envelope or LFO, the other a signal to process. There's a gain of 16 so that modulation = 0.0625 will have unity gain and not
    trigger any folding, but higher values can (if the signal's high enough).

    The folding operation is applied to the result.

    Some 'scope shots:
    Click image for larger version. 

Name:	wavefolder_1.png 
Views:	23 
Size:	20.7 KB 
ID:	22351
    Click image for larger version. 

Name:	wavefolder_2.png 
Views:	21 
Size:	18.2 KB 
ID:	22352


    Here's the test script:
    Code:
    #include <Audio.h>
    //#include <effect_wavefolder.h>  // added to Audio.h in the branch now
    
    AudioOutputI2S         i2sout ;
    
    AudioSynthWaveform     sig ;   // signal to be modulated
    AudioSynthWaveform     mod  ;  // modulate the amplitude into folder
    AudioEffectWaveFolder  folder ;
    
    AudioConnection        c0 (mod, 0, folder, 0) ;
    AudioConnection        c1 (sig, 0, folder, 1) ;
    AudioConnection        c2 (folder, 0, i2sout, 0) ;
    AudioConnection        c3 (folder, 0, i2sout, 1) ;
    
    // The Audio Shield chip
    AudioControlSGTL5000 codec;
    
    void audio_setup()
    {
      AudioMemory(4);
      
      sig.begin (0.99, 100, WAVEFORM_SINE) ;
      mod.begin (0.03, 5, WAVEFORM_SINE) ;
      mod.offset (0.0625) ;
      
      codec.enable();  
      codec.volume(0.6);
      codec.lineOutLevel (13) ;  // turn up line out to max
    }
    
    void loop () {}
    
    void setup ()
    {
      Serial.begin (115200) ;
      audio_setup () ;
    }
    And the implementation:
    effect_wavefolder.h
    Code:
    /* Wavefolder effect for Teensy Audio library
     *
     * Copyright (c) 2020, Mark Tillotson
     *
     * Permission is hereby granted, free of charge, to any person obtaining a copy
     * of this software and associated documentation files (the "Software"), to deal
     * in the Software without restriction, including without limitation the rights
     * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     * copies of the Software, and to permit persons to whom the Software is
     * furnished to do so, subject to the following conditions:
     *
     * The above copyright notice, development funding notice, and this permission
     * notice shall be included in all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     * THE SOFTWARE.
     */
    
    #ifndef effect_wavefolder_h_
    #define effect_wavefolder_h_
    
    #include "Arduino.h"
    #include "AudioStream.h"
    
    class AudioEffectWaveFolder : public AudioStream
    {
    public:
      AudioEffectWaveFolder() : AudioStream(2, inputQueueArray) {}
      virtual void update() ;
    
    private:
      audio_block_t * inputQueueArray[2] ;
    };
    
    #endif

    effect_wavefolder.cpp
    Code:
    /* Wavefolder effect for Teensy Audio library
     *
     * Copyright (c) 2020, Mark Tillotson
     *
     * Permission is hereby granted, free of charge, to any person obtaining a copy
     * of this software and associated documentation files (the "Software"), to deal
     * in the Software without restriction, including without limitation the rights
     * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     * copies of the Software, and to permit persons to whom the Software is
     * furnished to do so, subject to the following conditions:
     *
     * The above copyright notice, development funding notice, and this permission
     * notice shall be included in all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     * THE SOFTWARE.
     */
    
    #include "effect_wavefolder.h"
    
    void AudioEffectWaveFolder::update()
    {
      audio_block_t * blocka = receiveWritable (0);
      if (!blocka)
        return;
      audio_block_t * blockb = receiveReadOnly (1);
      if (!blockb)
      {
        release (blocka);
        return;
      }
      int16_t * pa = blocka->data ;
      int16_t * pb = blockb->data ;
      for (int i = 0 ; i < AUDIO_BLOCK_SAMPLES ; i++)
      {
        int32_t a12 = pa[i];
        int32_t b12 = pb[i];
    
        // scale upto 16 times input, so that can fold upto 16 times in each polarity
        int32_t s1 = (a12 * b12 + 0x400) >> 11 ;
        // if in a band where the sense needs to be reverse, detect this
        bool flip1 = ((s1 + 0x8000) >> 16) & 1 ;
        // reverse and truncate to 16 bits
        s1 = 0xFFFF & (flip1 ? -s1 : +s1) ;
    
        pa[i] = s1;
      }
      transmit(blocka);
      release(blocka);
      release(blockb);
    }

  4. #4
    I only saw it today, thank you for putting an effort on this !
    Will try it later today, when i'm back home.

  5. #5
    Just tested the wavefolder and sounds great! but i'm having some "clicks" here and there.
    Maybe i'm doing something wrong?

    I'm using the PT8211 audio codec. Could be this guy's fault?
    I also added a dc offset object, since i want to control the folder with a pot.

    here is my code (ugly i know), can someone spot something?

    [ CODE]
    #include <Audio.h>
    #include <effect_wavefolder.h> // added to Audio.h in the branch now
    #include <Smoothed.h> // Include the library

    AudioOutputPT8211 pt8211_1; //xy=788,362
    AudioSynthWaveformDc dc1; //xy=218.03125,732.53125

    AudioSynthWaveform sig ; // signal to be modulated
    AudioEffectWaveFolder folder ;

    AudioConnection c0 (dc1, 0, folder, 0) ;
    AudioConnection c1 (sig, 0, folder, 1) ;
    AudioConnection c2 (folder, 0, pt8211_1, 0) ;
    AudioConnection c3 (folder, 0, pt8211_1, 1) ;

    float mapf(float x, float in_min, float in_max, float out_min, float out_max)
    {return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;}


    #define SENSOR_PIN A0 // pin para smooth do folder
    Smoothed <float> smoothFolderKnob;


    void setup()
    {
    AudioMemory(100);
    analogReadResolution(12);

    sig.begin (0.6, 100, WAVEFORM_SINE) ;

    smoothFolderKnob.begin(SMOOTHED_AVERAGE, 10);
    }

    void loop () {

    float currentSensorValue = analogRead(SENSOR_PIN);
    smoothFolderKnob.add(currentSensorValue);
    float foldKnob = smoothFolderKnob.get();

    float foldKnobValue = mapf(foldKnob, 0, 4096, 0.0625, 16);// C1~C6

    float foldDC = mapf(foldKnobValue, 0.0625, 16, 0.06, 1.0);// C1~C6

    dc1.amplitude(foldDC);


    }

    [ /CODE]

  6. #6
    Senior Member
    Join Date
    Jul 2020
    Posts
    969
    Quote Originally Posted by manatee View Post
    Just tested the wavefolder and sounds great! but i'm having some "clicks" here and there.
    Maybe i'm doing something wrong?
    Sorry for the delay in replying. Recently been tidying up some old branches and spotted this.

    Its a bug in the folder, whenever the folder saw a sample value ending in 0x8000 it was glitching.

    Its fixed in the branch here: https://github.com/MarkTillotson/Aud...wavefolder.cpp

    I'm going to create a pull request for the wave folder effect as I've now added gui and documentation.

  7. #7
    Senior Member
    Join Date
    Jul 2020
    Posts
    969
    I note this has been merged now so should be available in the next Teensyduino release... Thanks manatee for spotting that
    click bug (it was visible on a 'scope occasionally, but easy to miss).

  8. #8
    Member garcho's Avatar
    Join Date
    May 2020
    Location
    Richmond, VA
    Posts
    22
    Thanks for your efforts Mark, I look forward to trying this out, cheers

Posting Permissions

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