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

Thread: Exponential envelope generator object

  1. #1
    Senior Member
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    117

    Exponential envelope generator object

    Hi folks

    As part of familarising myself with the Audio ecosystem I've made a slightly different envelope generator which can be found at: https://github.com/h4yn0nnym0u5e/Aud...es/expEnvelope . It attempts to emulate the old-school analogue envelopes based on RC circuits, which therefore had exponential transitions rather than the linear ones provided by the existing AudioEffectEnvelope. As such it consumes a bit more CPU than the linear one (I estimate about twice as much), but I've tried to make it more forgiving of noteOn / noteOff calls and parameter changes while the envelope is running.
    • attack, decay and release have a new optional "shape" parameter
    • releaseNoteOn no longer exists (in this object - the linear one still has it, of course)

    I think I've updated the GUI, keywords and header files OK.

    For some reason my clone of the original repo seems also to have cloned PJRC's "issues" template (I really don't grok github) - I'll try to figure out how to fix that...

    If anyone cares to try it out please report back here or via github. If enough people like it I might even be motivated to maintain it!

    Cheers

    Jonathan

  2. #2
    Senior Member
    Join Date
    Apr 2019
    Posts
    158
    Hello, I'm giving it a try on a Teensy4.1 based synth. The effect is good and CPU usage doesn't appear much different to me. It's probably exactly what I'm looking for. However, I'm getting noise at irregular times followed by audio problems. Looking at audio memory usage with
    Code:
    Serial.println(AudioMemoryUsageMax());
    it's all over the place and hits 65535(!) even though the memory size is set to 100 which is slightly higher than I normally use.

    Click image for larger version. 

Name:	Capture.PNG 
Views:	31 
Size:	20.2 KB 
ID:	24527
    Last edited by UHF; 04-22-2021 at 12:56 PM.

  3. #3
    Senior Member
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    117
    That's odd. I haven't thrashed it in a busy system, so there could easily be gremlins that I didn't catch in testing, but the outer skin is effectively exactly the same as the original linear envelope, so the memory usage in particular is strange, it should still be one block in, one block out. Noise could be because I've lost sync somewhere with the 8-bytes-at-a-time processing ... hmm ... or if I overran the end of the buffer and corrupted the next one ... that'd do it.

    I'll take a look. Can you post a minimal stand-alone piece of code that reproduces the problem?

    Cheers

    Jonathan

  4. #4
    Senior Member
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    117
    OK, I've taken a look and made a minor change to some code that "should never happen", but might have caused problems if it did. Please give https://github.com/h4yn0nnym0u5e/Aud...es/expEnvelope a try (you should only need to download effect_expenvelope.cpp, in fact). If the "should never happen" event does occur, you'll find notes releasing unexpectedly, or at least starting to do so, but the noise should no longer happen, and the memory use should remain sane.

    [Technical explanation] I had a case in the envelope state machine that was supposed to catch non-existent states, despite the fact that the code never assigns a value other than one from the normal set of delay, attack, hold, decay, sustain, release, idle, and a special "rising decay" (which happens if you raise the sustain level above the current level while the decay phase is in progress). This default case set two samples to 0, whereas all other cases always process 8 samples, so if that happened momentarily when 120 samples had been processed, the next loop would start at 122, and if the state then became valid, the update would terminate with 130 samples processed, which would be a Bad Thing. I still can't see how a nonexistent state can occur, so this may not (a) fix your problem, or (b) be necessary.

    A reproducible example would still help, if you can figure one out.

    Cheers

    Jonathan

  5. #5
    Junior Member
    Join Date
    Mar 2021
    Posts
    18
    Oh great, I can't wait to try this! What is the behavour of the envelope if you retrigger it while the output is non-zero (i.e. During any of the ADSR stages)? The default library envelope resets to zero which creates a volume ducking effect. I think it would be more musical for the envelope to start from its current value if you retrigger it.

  6. #6
    Senior Member
    Join Date
    Apr 2019
    Posts
    158
    No, it's still there. Significantly, it only occurs on left or right channels, not both at the same time. Also it's polyphonic. I'll try and produce some cut down code.

  7. #7
    Senior Member
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    117
    Quote Originally Posted by TigerBalm2 View Post
    Oh great, I can't wait to try this! What is the behavour of the envelope if you retrigger it while the output is non-zero (i.e. During any of the ADSR stages)? The default library envelope resets to zero which creates a volume ducking effect. I think it would be more musical for the envelope to start from its current value if you retrigger it.
    I’ve tried to make the behaviour when retriggerings as logical as possible, so it does start from the prevailing value, unless it’s in the Attack or Hold stages when the retrigger is ignored (you’d hear no difference anyway!). It also tries to do the right thing if a parameter is changed while in that stage, or a “related“ stage, in the case of changing Sustain level during Decay.

    Please do give it a go, though it sounds like I still have a bug in there...

    Cheers

    Jonathan

  8. #8
    Senior Member
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    117
    Quote Originally Posted by UHF View Post
    No, it's still there. Significantly, it only occurs on left or right channels, not both at the same time. Also it's polyphonic. I'll try and produce some cut down code.
    Thanks. Not understanding the left/right/polyphonic part of your post - the envelope is a monophonic object

    Is it more likely at very fast or slow A/D/R speeds, do you know? I probably haven’t tested those as much as I should have...

    Cheers

    Jonathan

  9. #9
    Senior Member
    Join Date
    Apr 2019
    Posts
    158
    I'm playing a polyphonic synth with 12 envelopes. The noise is either on the left or right channel. I'm using A/D/R from 1ms to 12s and sustain 0 to 1. I'm using your envelope as a replacement for the existing one with no changes.

    Click image for larger version. 

Name:	Capture.PNG 
Views:	24 
Size:	81.2 KB 
ID:	24543

    Audio file

  10. #10
    Senior Member
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    117
    Quote Originally Posted by UHF View Post
    I'm playing a polyphonic synth with 12 envelopes. The noise is either on the left or right channel. I'm using A/D/R from 1ms to 12s and sustain 0 to 1. I'm using your envelope as a replacement for the existing one with no changes.

    Click image for larger version. 

Name:	Capture.PNG 
Views:	24 
Size:	81.2 KB 
ID:	24543

    Audio file
    That's pretty clear. If I grab your Tsynth from github and replace the envelopes, that's what you're running, yes? Do I need to change parameters in real time, or is there a fixed set that will reproduce the problem? Could I cut the polyphony down and still get the problem? Do you have a MIDI file that produces the problem when played, or could it be done entirely with a fixed piece of code to start and stop notes in a 100% predictable manner?

    I won't be able to get back to this until this evening at the earliest, I'm afraid.

    Oh, one more question: which Teensy are you using for this? I only have a T4.1.

    Cheers

    Jonathan

  11. #11
    Senior Member
    Join Date
    Apr 2019
    Posts
    158
    Yes it's T4.1. If you want to use the current TSynth code, you can comment out three lines in the loop() like this so that it doesn't try to read non-existent pots and switches:

    Code:
    void loop() {
      //USB HOST MIDI Class Compliant
      myusb.Task();
      midi1.read(midiChannel);
      //USB Client MIDI
      usbMIDI.read(midiChannel);
      //MIDI 5 Pin DIN
      MIDI.read(midiChannel);
      //checkMux();  //THIS LINE
     // checkSwitches(); //THIS LINE
      //checkEncoder(); //THIS LINE
      //CPUMonitor();
    }

    and send MIDI via the USB from your pc, and make parameter changes with MIDI CC messages - see MidiCC.h. It should work fine. If you don't have the Audio Board soldered on, you can get digital audio through the same USB connection - the Teensy will appear as a soundcard.

  12. #12
    Senior Member
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    117
    Found it! It was a block overrun, as I suspected, but not where I suspected... Grab the latest commit from https://github.com/h4yn0nnym0u5e/Aud...es/expEnvelope and see how you go, sounds OK to me though. I've implemented the TSynth close() function to save you a bit of pain, though it's not what I'd call elegant!

    I'll do a separate post relating to my experiences getting TSynth working in "headless" mode.

    Cheers

    Jonathan

  13. #13
    Senior Member
    Join Date
    Apr 2021
    Location
    Cambridgeshire, UK
    Posts
    117
    Quote Originally Posted by UHF View Post
    Yes it's T4.1. If you want to use the current TSynth code, you can comment out three lines in the loop() like this so that it doesn't try to read non-existent pots and switches:

    Code:
    void loop() {
      //USB HOST MIDI Class Compliant
      myusb.Task();
      midi1.read(midiChannel);
      //USB Client MIDI
      usbMIDI.read(midiChannel);
      //MIDI 5 Pin DIN
      MIDI.read(midiChannel);
      //checkMux();  //THIS LINE
     // checkSwitches(); //THIS LINE
      //checkEncoder(); //THIS LINE
      //CPUMonitor();
    }

    and send MIDI via the USB from your pc, and make parameter changes with MIDI CC messages - see MidiCC.h. It should work fine. If you don't have the Audio Board soldered on, you can get digital audio through the same USB connection - the Teensy will appear as a soundcard.
    I found a few issues following the above advice, and when making changes to figure out the bug in ExpEnvelope:
    • you can't just comment out checkMux(), as it has to run once to enable the sound output at all
    • cutting down the polyphony by simply changing NO_OF_VOICES in Constants.h doesn't work, it breaks ST7735Display.h (definition of colour[] at line 41, and assumption of 12 voices in lines 174-188: could be more, I didn't look further); also TSynth.ino, voices[] on line 84
    • I suspect it needs a constant value assigned for system volume - I put one in as the first line of checkVolumePot(), as I don't have anything wired to VOLUME_POT
    • I had problems with the duplicated synth_waveform.cpp and data_bandlimit_step.c, and had to rename them temporarily to get the system to compile: this could be due to me using the Arduino IDE


    For users like me, who might want to check out TSynth before investing in the hardware, it might be worth the effort to have a #define TSYNTH_HEADLESS_MODE option which if enabled will make it simple for them to get a minimal system up and running without making a lot of obscure changes.

    Cheers

    Jonathan

  14. #14
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin, TX
    Posts
    110
    Hey just thought I'd mention I got my shapeable envelope working much more quickly now. UHF tested the previous version w TSynth but I'd like to know if this one works for y'all.
    https://github.com/BleepLabs/adjusta...velope_example

Posting Permissions

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