Audio plugin host https://kx.studio/carla
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.

SynthNote.cpp 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #include "SynthNote.h"
  2. #include "../globals.h"
  3. #include <cstring>
  4. #include <new>
  5. #include <iostream>
  6. SynthNote::SynthNote(SynthParams &pars)
  7. :memory(pars.memory),
  8. legato(pars.synth, pars.frequency, pars.velocity, pars.portamento,
  9. pars.note, pars.quiet), ctl(pars.ctl), synth(pars.synth), time(pars.time)
  10. {}
  11. SynthNote::Legato::Legato(const SYNTH_T &synth_, float freq, float vel, int port,
  12. int note, bool quiet)
  13. :synth(synth_)
  14. {
  15. // Initialise some legato-specific vars
  16. msg = LM_Norm;
  17. fade.length = (int)(synth.samplerate_f * 0.005f); // 0.005f seems ok.
  18. if(fade.length < 1)
  19. fade.length = 1; // (if something's fishy)
  20. fade.step = (1.0f / fade.length);
  21. decounter = -10;
  22. param.freq = freq;
  23. param.vel = vel;
  24. param.portamento = port;
  25. param.midinote = note;
  26. lastfreq = 0.0f;
  27. silent = quiet;
  28. }
  29. int SynthNote::Legato::update(LegatoParams pars)
  30. {
  31. if(pars.externcall)
  32. msg = LM_Norm;
  33. if(msg != LM_CatchUp) {
  34. lastfreq = param.freq;
  35. param.freq = pars.frequency;
  36. param.vel = pars.velocity;
  37. param.portamento = pars.portamento;
  38. param.midinote = pars.midinote;
  39. if(msg == LM_Norm) {
  40. if(silent) {
  41. fade.m = 0.0f;
  42. msg = LM_FadeIn;
  43. }
  44. else {
  45. fade.m = 1.0f;
  46. msg = LM_FadeOut;
  47. return 1;
  48. }
  49. }
  50. if(msg == LM_ToNorm)
  51. msg = LM_Norm;
  52. }
  53. return 0;
  54. }
  55. void SynthNote::Legato::apply(SynthNote &note, float *outl, float *outr)
  56. {
  57. if(silent) // Silencer
  58. if(msg != LM_FadeIn) {
  59. memset(outl, 0, synth.bufferbytes);
  60. memset(outr, 0, synth.bufferbytes);
  61. }
  62. try {
  63. switch (msg) {
  64. case LM_CatchUp: // Continue the catch-up...
  65. if (decounter == -10)
  66. decounter = fade.length;
  67. //Yea, could be done without the loop...
  68. for (int i = 0; i < synth.buffersize; ++i) {
  69. decounter--;
  70. if (decounter < 1) {
  71. // Catching-up done, we can finally set
  72. // the note to the actual parameters.
  73. decounter = -10;
  74. msg = LM_ToNorm;
  75. LegatoParams pars{param.freq, param.vel, param.portamento,
  76. param.midinote, false};
  77. note.legatonote(pars);
  78. break;
  79. }
  80. }
  81. break;
  82. case LM_FadeIn: // Fade-in
  83. if (decounter == -10)
  84. decounter = fade.length;
  85. silent = false;
  86. for (int i = 0; i < synth.buffersize; ++i) {
  87. decounter--;
  88. if (decounter < 1) {
  89. decounter = -10;
  90. msg = LM_Norm;
  91. break;
  92. }
  93. fade.m += fade.step;
  94. outl[i] *= fade.m;
  95. outr[i] *= fade.m;
  96. }
  97. break;
  98. case LM_FadeOut: // Fade-out, then set the catch-up
  99. if (decounter == -10)
  100. decounter = fade.length;
  101. for (int i = 0; i < synth.buffersize; ++i) {
  102. decounter--;
  103. if (decounter < 1) {
  104. for (int j = i; j < synth.buffersize; ++j) {
  105. outl[j] = 0.0f;
  106. outr[j] = 0.0f;
  107. }
  108. decounter = -10;
  109. silent = true;
  110. // Fading-out done, now set the catch-up :
  111. decounter = fade.length;
  112. msg = LM_CatchUp;
  113. //This freq should make this now silent note to catch-up/resync
  114. //with the heard note for the same length it stayed at the
  115. //previous freq during the fadeout.
  116. float catchupfreq = param.freq * (param.freq / lastfreq);
  117. LegatoParams pars{catchupfreq, param.vel, param.portamento,
  118. param.midinote, false};
  119. note.legatonote(pars);
  120. break;
  121. }
  122. fade.m -= fade.step;
  123. outl[i] *= fade.m;
  124. outr[i] *= fade.m;
  125. }
  126. break;
  127. default:
  128. break;
  129. }
  130. } catch (std::bad_alloc &ba) {
  131. std::cerr << "failed to apply legato: " << ba.what() << std::endl;
  132. }
  133. }
  134. void SynthNote::setVelocity(float velocity_) {
  135. legato.setSilent(true); //Let legato.update(...) returns 0.
  136. LegatoParams pars{legato.getFreq(), velocity_,
  137. legato.getPortamento(), legato.getMidinote(), true};
  138. try {
  139. legatonote(pars);
  140. } catch (std::bad_alloc &ba) {
  141. std::cerr << "failed to set velocity to legato note: " << ba.what() << std::endl;
  142. }
  143. legato.setDecounter(0); //avoid chopping sound due fade-in
  144. }