FxPremaster.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. При выходе сигнала из диапазона порог компрессора начинает опускаться,
  3. наклонная компрессирования начинает также опускаться. Также в пропорции
  4. ослабляеться сигнал.
  5. in ->[Gain]->[compressor]->[soft limiter]-> out
  6. */
  7. #include "FxPremaster.h"
  8. FxPremaster::FxPremaster()
  9. {
  10. FXRegistrationInfo(FxPremaster, L"Storm engine FxPremaster", L"Spirenkov Maxim");
  11. Assert(c_comp_threshold_up > c_comp_threshold_down);
  12. Assert(c_comp_threshold_down > 0);
  13. Assert(c_comp_threshold_up < 100);
  14. Assert(c_limit_threshold > c_comp_threshold_up);
  15. Assert(c_limit_threshold < 100);
  16. Assert((c_samples_per_block & (c_samples_per_block - 1)) == 0);
  17. Assert(c_samples_per_block >= 16);
  18. Reset();
  19. }
  20. FxPremaster::~FxPremaster()
  21. {
  22. }
  23. //Сбросить параметры
  24. void STDMETHODCALLTYPE FxPremaster::Reset()
  25. {
  26. compressorThreshold = c_comp_threshold_up*0.01f;
  27. compressorThresholdStep = 0.0f;
  28. compressorRatio = 1.0f;
  29. compressorRatioStep = 0.0f;
  30. compressorGain = 1.0f;
  31. compressorGainStep = 0.0f;
  32. softLimitGain = 1.0f;
  33. softLimitNormalizer = 1.0f;
  34. blockPosition = 0;
  35. blockCounter = 0;
  36. for(dword i = 0; i < ARRSIZE(history); i++) history[i] = 0.0f;
  37. }
  38. //Процессировать пришедший буфер
  39. void STDMETHODCALLTYPE FxPremaster::Process(float * __restrict buffer, dword samples)
  40. {
  41. //Расчитываем максимальное значение на каждый блок
  42. dword count = samples << 1;
  43. float maxVolume = 0.0f;
  44. dword counter = blockCounter;
  45. for(dword i = 0; i < count; i++)
  46. {
  47. //Считываем значение и получаем абсолютное
  48. float v = buffer[i];
  49. float absv = fabsf(v);
  50. //Максимальное значение для текущего блока
  51. maxVolume = coremax(absv, maxVolume);
  52. counter++;
  53. if(counter == c_samples_per_block)
  54. {
  55. //Сохраняем громкость блока
  56. history[blockPosition] = maxVolume;
  57. blockPosition = (blockPosition + 1) & (ARRSIZE(history) - 1);
  58. //Вычисляем текущие параметры компрессора
  59. float historyMax = 0.0f;
  60. for(dword j = 0; j < ARRSIZE(history); j++)
  61. {
  62. historyMax = coremax(historyMax, history[j]);
  63. }
  64. //Расчитываем требуемый коэфициент усиления
  65. float compressorGainNew = coremin(1.0f/historyMax, 1.0f);
  66. float blendTimeInSec;
  67. if(compressorGainNew < compressorGain)
  68. {
  69. blendTimeInSec = 2.0f;
  70. }else{
  71. blendTimeInSec = 4.0f;
  72. }
  73. compressorGainStep = (compressorGainNew - compressorGain)/(44100*blendTimeInSec);
  74. //Корректируем максимальное значение в соответствие текущего коэфициента усиления
  75. historyMax *= compressorGain;
  76. //Порог компрессора
  77. float thresholdK = Clampf((historyMax - 1.0f)/(3.0f - 1.0f));
  78. float threshold = c_comp_threshold_up*0.01f + thresholdK*0.01f*(c_comp_threshold_down - c_comp_threshold_up);
  79. compressorThresholdStep = (threshold - compressorThreshold)*(1.0f/c_samples_per_block);
  80. //Коэфициент ослабления сигнала выше порогового уровня
  81. if(historyMax > compressorThreshold)
  82. {
  83. float ratio = (1.0f - compressorThreshold)/(historyMax - compressorThreshold);
  84. compressorRatioStep = (ratio - compressorRatio)*(1.0f/c_samples_per_block);
  85. }else{
  86. compressorRatioStep = 0.0f;
  87. }
  88. //Начинаем расчёт нового блока
  89. maxVolume = 0.0f;
  90. counter = 0;
  91. }
  92. //Ослабление сигнала
  93. absv *= compressorGain;
  94. //Компрессирование сигнала
  95. if(absv > compressorThreshold)
  96. {
  97. absv = (absv - compressorThreshold)*compressorRatio + compressorThreshold;
  98. }
  99. //Константное приведение полного диапазона под лимитер
  100. absv *= c_limit_threshold*0.01f;
  101. //Обновляем параметры компресора
  102. compressorThreshold += compressorThresholdStep;
  103. compressorRatio += compressorRatioStep;
  104. compressorGain += compressorGainStep;
  105. //Лимитирование сигнала
  106. static const float limitThreshold = c_limit_threshold*0.01f;
  107. static const float limitNormalize = 1.0f/(1.0f - c_limit_threshold*0.01f);
  108. static const float limitScale = 1.0f - c_limit_threshold*0.01f;
  109. if(absv > limitThreshold)
  110. {
  111. float limitValue = (absv - limitThreshold)*limitNormalize;
  112. float limitedValue = 1.0f - 1.0f/(1.0f + limitValue);
  113. absv = limitedValue*limitScale + limitThreshold;
  114. }
  115. //Сохраняем полученое значение в соответствие со знаком
  116. if(v >= 0.0f)
  117. {
  118. buffer[i] = absv;
  119. }else{
  120. buffer[i] = -absv;
  121. }
  122. }
  123. blockCounter = counter;
  124. }