Wavefolder possible?

Status
Not open for further replies.
effect waveshaper might be a possible approach, but I think this really needs a custom object to do the folding simply
and efficiently.
 
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/Audio/blob/wave_folder/effect_waveshaper.h
https://github.com/MarkTillotson/Audio/blob/wave_folder/effect_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:
wavefolder_1.png
wavefolder_2.png


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);
}
 
I only saw it today, thank you for putting an effort on this !
Will try it later today, when i'm back home.
 
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]
 
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/Audio/blob/wave_folder/effect_wavefolder.cpp

I'm going to create a pull request for the wave folder effect as I've now added gui and documentation.
 
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).
 
Status
Not open for further replies.
Back
Top