• Hallo developers. I do not understand the code of envelope from shruthi.

    With avr gcc I can not make an inline function. How can I program it different.

    Thanks for a little help :)

    Envelope.txt
    6K
  • Hi Rolf,

    Why rewrite something that does the job? If you for some reasons have issues with the inline directive, why not just remove it (I’m pretty sure it’s there for performance reasons)?

    Cheers

  • I want to use the shruthi envelope code in my DE-GENERATOR. My old code is to long. My new envelope code is not function. How use the 8Bit result of render() ??

  • Ok, if you remove the “inline” keyword you can probably use it “as is”

  • I’m understand the return value of render() ???? how use this ??

  • I haven’t looked much at this before but looking at voice.cc you can see how it’s used. From render you get the current envelope value (after advancing the envelope position).

  • I guess you want to use the envelope value as a modulation source (for vca etc), right!?

  • Yes..

    The 16Bit result of envelope calc in render() and the result in value_ ?

    But.. how use the return value from render() ??

  • value_ is a private class variable. You’re not supposed to (try to) access that when using the class. Render returns the value to use externally.

    Edit: as seen in Render the Shruthi envelope resolution is 8 bit

  • Yes..

    The value_ is 16Bit result

  • My problem is: the attack and release phase is not function.

  • 16 bit is only internal resolution. The envelope.render return 8 bit

  • Yes.. that is ok.

    But.. attack and release is not function.

  • Encode: attack value 0 out = 255; Encoder attack value 127 out = 0;

  • I don’t get it. You can set the entire envelope using Update, and the Render return the only value you need (the current), right?

    Edit: the return values from render above seems correct if they’re from the first call to render. Shortest attack (0) -> envelope start at max, Slowest attack (127) -> envelope start at 0

  • Its not function.. Env.value_8 is the 8Bit result value of envelope. Ok ?

    My code here:

    void envelope ()
    {
    uint8_t stage = Env.stage_;
    uint16_t value = Env.value_;
    if (midi_gate_flag == 0 && stage != RELEASE)
    {
    stage = RELEASE;
    }

    Trigger(stage);

    UpdateAttack(Encoder.attack);

    Update(Encoder.attack,Encoder.decay,Encoder.sustain,Encoder.release);

    Env.value_8 = Render();

    }

    If I press a key at any time the stage_ is 0. If i let off the key the stage goes to 3.

  • Yes, in the Shruthi code the envelope.render give the current (8 bit) value of the envelope (and advance envelope position). Sorry if I don’t have the stamina to debug your alternative implementation.

  • That is not a problem. Thanks for your help.. . I found a result for me. I have perseverance ;)

  • i must admit the code above confuse me. Render should be called very x’th sample to get the current envelope value. Trigger should only be called when an envelope is started (new note press). You seem to be restarting the envelope every time and getting the 1st value from the envelope every time, i.e. Not really using the envelope progression at all.

  • Yes.. thats is!

    The trigger() running every time in the envelope(). I’m blind ;)

  • I need a tip!

    I have problems with two envelopes in my code. In your code you change the “value_” and “stage_” for the envelopes ?

    uint8_t stage() { return stage_; }
    uint16_t value() { return value_; }

    Problem: in my code the result value of both envelopes is mixed!

    Env.txt
    3K
  • I think your problem is that you have one single Env variable you use for the computations for both envelopes. So it contains the state for both envelopes!

    You need to have two instances of Env. And what about writing your code in a pseudo-object-oriented style? You pass as an argument the Env that needs to be updated, and you keep two Env in memory.

    Like this:

    uint8_t Envelope_Render(Env* env) { env->phase_ += env->phase_increment_; ...
    }

    void Envelope_Trigger(Env* env) { if (stage == DEAD) {

    env->value_ = 0; } }

    void Envelope_Init(Env* env) { env->stage_target_[ATTACK] = 255; ...
    }

    Then you create two Env structs for both envelopes.

    Env env[ 2 ];

    And you call

    Envelope_Render(&env[ 0 ]);

    Or

    Envelope_Render(&env[ 1 ]);

  • Thanks for your tip. I will think about it :))