No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

envelope.c 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #include <math.h>
  2. #include "envelope.h"
  3. #include "config.h"
  4. void envelope_init(struct Envelope *env) {
  5. envelope_reset(env);
  6. envelope_set_attack_rate(env, 0);
  7. envelope_set_decay_rate(env, 0);
  8. envelope_set_release_rate(env, 0);
  9. envelope_set_sustain_level(env, 1.0);
  10. envelope_set_target_ratio_a(env, 0.3);
  11. envelope_set_target_ratio_dr(env, 0.0001);
  12. }
  13. void envelope_reset(struct Envelope *env) {
  14. env->state = EnvNone;
  15. env->output = 0.0;
  16. }
  17. void envelope_start(struct Envelope *env) {
  18. env->state = EnvAttack;
  19. }
  20. void envelope_stop(struct Envelope *env) {
  21. if (env->state != EnvNone)
  22. env->state = EnvRelease;
  23. }
  24. static inline float calc_coef(float rate, float target_ratio) {
  25. return (rate <= 0) ? 0.0 : exp(-log((1.0 + target_ratio) / target_ratio) / rate);
  26. }
  27. void envelope_set_attack_rate(struct Envelope *env, float rate) {
  28. env->attack_rate = rate;
  29. env->attack_coef = calc_coef(rate, env->target_ratio_a);
  30. env->attack_base = (1.0 + env->target_ratio_a) * (1.0 - env->attack_coef);
  31. }
  32. void envelope_set_decay_rate(struct Envelope *env, float rate) {
  33. env->decay_rate = rate;
  34. env->decay_coef = calc_coef(rate, env->target_ratio_dr);
  35. env->decay_base = (env->sustain_level - env->target_ratio_dr) * (1.0 - env->decay_coef);
  36. }
  37. void envelope_set_release_rate(struct Envelope *env, float rate) {
  38. env->release_rate = rate;
  39. env->release_coef = calc_coef(rate, env->target_ratio_dr);
  40. env->release_base = -env->target_ratio_dr * (1.0 - env->release_coef);
  41. }
  42. void envelope_set_sustain_level(struct Envelope *env, float level) {
  43. env->sustain_level = level;
  44. env->decay_base = (env->sustain_level - env->target_ratio_dr) * (1.0 - env->decay_coef);
  45. }
  46. void envelope_set_target_ratio_a(struct Envelope *env, float target_ratio) {
  47. if (target_ratio < 0.000000001)
  48. target_ratio = 0.000000001; // -180 dB
  49. env->target_ratio_a = target_ratio;
  50. env->attack_coef = calc_coef(env->attack_rate, target_ratio);
  51. env->attack_base = (1.0 + env->target_ratio_a) * (1.0 - env->attack_coef);
  52. }
  53. void envelope_set_target_ratio_dr(struct Envelope *env, float target_ratio) {
  54. if (target_ratio < 0.000000001)
  55. target_ratio = 0.000000001; // -180 dB
  56. env->target_ratio_dr = target_ratio;
  57. env->decay_coef = calc_coef(env->decay_rate, env->target_ratio_dr);
  58. env->release_coef = calc_coef(env->release_rate, env->target_ratio_dr);
  59. env->decay_base = (env->sustain_level - env->target_ratio_dr) * (1.0 - env->decay_coef);
  60. env->release_base = -env->target_ratio_dr * (1.0 - env->release_coef);
  61. }
  62. float envelope_sample(struct Envelope *env) {
  63. switch(env->state) {
  64. case EnvAttack:
  65. env->output = env->attack_base + env->output * env->attack_coef;
  66. if (env->output >= 1.0) {
  67. env->output = 1.0;
  68. env->state = EnvDecay;
  69. }
  70. break;
  71. case EnvDecay:
  72. env->output = env->decay_base + env->output * env->decay_coef;
  73. if (env->output <= env->sustain_level) {
  74. env->output = env->sustain_level;
  75. env->state = EnvSustain;
  76. }
  77. break;
  78. case EnvSustain:
  79. break;
  80. case EnvRelease:
  81. env->output = env->release_base + env->output * env->release_coef;
  82. if (env->output <= 0.0) {
  83. env->output = 0.0;
  84. env->state = EnvNone;
  85. }
  86. break;
  87. }
  88. return env->output;
  89. }