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.

153 lines
3.3KB

  1. /*************************************************************************************
  2. * Original code copyright (C) 2012 Steve Folta
  3. * Converted to Juce module (C) 2016 Leo Olivers
  4. * Forked from https://github.com/stevefolta/SFZero
  5. * For license info please see the LICENSE file distributed with this source code
  6. *************************************************************************************/
  7. #include "SFZRegion.h"
  8. #include "SFZSample.h"
  9. namespace sfzero
  10. {
  11. void EGParameters::clear()
  12. {
  13. delay = 0.0;
  14. start = 0.0;
  15. attack = 0.0;
  16. hold = 0.0;
  17. decay = 0.0;
  18. sustain = 100.0;
  19. release = 0.0;
  20. }
  21. void EGParameters::clearMod()
  22. {
  23. // Clear for velocity or other modification.
  24. delay = start = attack = hold = decay = sustain = release = 0.0;
  25. }
  26. Region::Region() { clear(); }
  27. void Region::clear()
  28. {
  29. memset(this, 0, sizeof(*this));
  30. hikey = 127;
  31. hivel = 127;
  32. pitch_keycenter = 60; // C4
  33. pitch_keytrack = 100;
  34. bend_up = 200;
  35. bend_down = -200;
  36. volume = pan = 0.0;
  37. amp_veltrack = 100.0;
  38. ampeg.clear();
  39. ampeg_veltrack.clearMod();
  40. }
  41. void Region::clearForSF2()
  42. {
  43. clear();
  44. pitch_keycenter = -1;
  45. loop_mode = no_loop;
  46. // SF2 defaults in timecents.
  47. ampeg.delay = -12000.0;
  48. ampeg.attack = -12000.0;
  49. ampeg.hold = -12000.0;
  50. ampeg.decay = -12000.0;
  51. ampeg.sustain = 0.0;
  52. ampeg.release = -12000.0;
  53. }
  54. void Region::clearForRelativeSF2()
  55. {
  56. clear();
  57. pitch_keytrack = 0;
  58. amp_veltrack = 0.0;
  59. ampeg.sustain = 0.0;
  60. }
  61. void Region::addForSF2(Region *other)
  62. {
  63. offset += other->offset;
  64. end += other->end;
  65. loop_start += other->loop_start;
  66. loop_end += other->loop_end;
  67. transpose += other->transpose;
  68. tune += other->tune;
  69. pitch_keytrack += other->pitch_keytrack;
  70. volume += other->volume;
  71. pan += other->pan;
  72. ampeg.delay += other->ampeg.delay;
  73. ampeg.attack += other->ampeg.attack;
  74. ampeg.hold += other->ampeg.hold;
  75. ampeg.decay += other->ampeg.decay;
  76. ampeg.sustain += other->ampeg.sustain;
  77. ampeg.release += other->ampeg.release;
  78. }
  79. void Region::sf2ToSFZ()
  80. {
  81. // EG times need to be converted from timecents to seconds.
  82. ampeg.delay = timecents2Secs(static_cast<int>(ampeg.delay));
  83. ampeg.attack = timecents2Secs(static_cast<int>(ampeg.attack));
  84. ampeg.hold = timecents2Secs(static_cast<int>(ampeg.hold));
  85. ampeg.decay = timecents2Secs(static_cast<int>(ampeg.decay));
  86. if (ampeg.sustain < 0.0f)
  87. {
  88. ampeg.sustain = 0.0f;
  89. }
  90. ampeg.sustain = 100.0f * decibelsToGain(-ampeg.sustain / 10.0f);
  91. ampeg.release = timecents2Secs(static_cast<int>(ampeg.release));
  92. // Pin very short EG segments. Timecents don't get to zero, and our EG is
  93. // happier with zero values.
  94. if (ampeg.delay < 0.01f)
  95. {
  96. ampeg.delay = 0.0f;
  97. }
  98. if (ampeg.attack < 0.01f)
  99. {
  100. ampeg.attack = 0.0f;
  101. }
  102. if (ampeg.hold < 0.01f)
  103. {
  104. ampeg.hold = 0.0f;
  105. }
  106. if (ampeg.decay < 0.01f)
  107. {
  108. ampeg.decay = 0.0f;
  109. }
  110. if (ampeg.release < 0.01f)
  111. {
  112. ampeg.release = 0.0f;
  113. }
  114. // Pin values to their ranges.
  115. if (pan < -100.0f)
  116. {
  117. pan = -100.0f;
  118. }
  119. else if (pan > 100.0f)
  120. {
  121. pan = 100.0f;
  122. }
  123. }
  124. water::String Region::dump()
  125. {
  126. water::String info = water::String::formatted("%d - %d, vel %d - %d", lokey, hikey, lovel, hivel);
  127. if (sample)
  128. {
  129. info << sample->getShortName();
  130. }
  131. info << "\n";
  132. return info;
  133. }
  134. float Region::timecents2Secs(int timecents) { return static_cast<float>(pow(2.0, timecents / 1200.0)); }
  135. }