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.

131 lines
4.6KB

  1. // Copyright 2014 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. // See http://creativecommons.org/licenses/MIT/ for more information.
  24. //
  25. // -----------------------------------------------------------------------------
  26. //
  27. // Vocoder.
  28. #include "warps/dsp/vocoder.h"
  29. #include <algorithm>
  30. #include "stmlib/dsp/cosine_oscillator.h"
  31. #include "stmlib/dsp/units.h"
  32. namespace warps {
  33. using namespace std;
  34. using namespace stmlib;
  35. void Vocoder::Init(float sample_rate) {
  36. modulator_filter_bank_.Init(sample_rate);
  37. carrier_filter_bank_.Init(sample_rate);
  38. limiter_.Init();
  39. release_time_ = 0.5f;
  40. formant_shift_ = 0.5f;
  41. BandGain zero;
  42. zero.carrier = 0.0f;
  43. zero.vocoder = 0.0f;
  44. fill(&previous_gain_[0], &previous_gain_[kNumBands], zero);
  45. fill(&gain_[0], &gain_[kNumBands], zero);
  46. for (int32_t i = 0; i < kNumBands; ++i) {
  47. follower_[i].Init();
  48. }
  49. }
  50. void Vocoder::Process(
  51. const float* modulator,
  52. const float* carrier,
  53. float* out,
  54. size_t size) {
  55. // Run through filter banks.
  56. modulator_filter_bank_.Analyze(modulator, size);
  57. carrier_filter_bank_.Analyze(carrier, size);
  58. // Set the attack/release release_time of envelope followers.
  59. float f = 80.0f * SemitonesToRatio(-72.0f * release_time_);
  60. for (int32_t i = 0; i < kNumBands; ++i) {
  61. float decay = f / modulator_filter_bank_.band(i).sample_rate;
  62. follower_[i].set_attack(decay * 2.0f);
  63. follower_[i].set_decay(decay * 0.5f);
  64. follower_[i].set_freeze(release_time_ > 0.995f);
  65. f *= 1.2599f; // 2 ** (4/12.0), a third octave.
  66. }
  67. // Compute the amplitude (or modulation amount) in all bands.
  68. float formant_shift_amount = 2.0f * fabs(formant_shift_ - 0.5f);
  69. formant_shift_amount *= (2.0f - formant_shift_amount);
  70. formant_shift_amount *= (2.0f - formant_shift_amount);
  71. float envelope_increment = 4.0f * SemitonesToRatio(-48.0f * formant_shift_);
  72. float envelope = 0.0f;
  73. const float kLastBand = kNumBands - 1.0001f;
  74. for (int32_t i = 0; i < kNumBands; ++i) {
  75. float source_band = envelope;
  76. CONSTRAIN(source_band, 0.0f, kLastBand);
  77. MAKE_INTEGRAL_FRACTIONAL(source_band);
  78. float a = follower_[source_band_integral].peak();
  79. float b = follower_[source_band_integral + 1].peak();
  80. float band_gain = (a + (b - a) * source_band_fractional);
  81. float attenuation = envelope - kLastBand;
  82. if (attenuation >= 0.0f) {
  83. band_gain *= 1.0f / (1.0f + 1.0f * attenuation);
  84. }
  85. envelope += envelope_increment;
  86. gain_[i].carrier = band_gain * formant_shift_amount;
  87. gain_[i].vocoder = 1.0f - formant_shift_amount;
  88. }
  89. for (int32_t i = 0; i < kNumBands; ++i) {
  90. size_t band_size = size / modulator_filter_bank_.band(i).decimation_factor;
  91. const float step = 1.0f / static_cast<float>(band_size);
  92. float* carrier = carrier_filter_bank_.band(i).samples;
  93. float* modulator = modulator_filter_bank_.band(i).samples;
  94. float* envelope = tmp_;
  95. follower_[i].Process(modulator, envelope, band_size);
  96. float vocoder_gain = previous_gain_[i].vocoder;
  97. float vocoder_gain_increment = (gain_[i].vocoder - vocoder_gain) * step;
  98. float carrier_gain = previous_gain_[i].carrier;
  99. float carrier_gain_increment = (gain_[i].carrier - carrier_gain) * step;
  100. for (size_t j = 0; j < band_size; ++j) {
  101. carrier[j] *= (carrier_gain + vocoder_gain * envelope[j]);
  102. vocoder_gain += vocoder_gain_increment;
  103. carrier_gain += carrier_gain_increment;
  104. }
  105. previous_gain_[i] = gain_[i];
  106. }
  107. carrier_filter_bank_.Synthesize(out, size);
  108. limiter_.Process(out, 1.4f, size);
  109. }
  110. } // namespace warps