         if(release_time)
         {
           uint16_t elapsed = millis() - release_time;
-          if(elapsed < adsr_values.R)
+          if(elapsed < adsr_values.R * ENV_RELEASE_HOLD)
           {
             // release
-            cv_current = (1.0 - float(elapsed) / float(adsr_values.R)) * cv_released;
+            cv_current = exp(ENV_RELEASE_COEFF * (float(elapsed) / float(adsr_values.R))) * cv_released;
           }
           else
           {

        if(elapsed < adsr_values.A)
        {
          // attack
          cv_current = (float(elapsed) / float(adsr_values.A)) * 10.0;
        }
        else if(elapsed < adsr_values.A + adsr_values.D)
        {
          // decay
          cv_current = adsr_values.S + (1.0 - float(elapsed - adsr_values.A) / float(adsr_values.D))
                       * (10.0 - adsr_values.S);
        }
        else
        {
          // sustain
          cv_current = adsr_values.S;
        }
      }
      else

          adsr_values.D = uint16_t(v[selected]) * 24;
          break;
        case 2:
          adsr_values.S = (float(v[selected]) / 46.0) * ENV_PEAK;
          break;
        case 3:
          adsr_values.R = uint16_t(v[selected]) * 24;
