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.

232 lines
8.1KB

  1. // Copyright 2015 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. // Filtering and scaling of ADC values + input calibration.
  28. #include "rings/cv_scaler.h"
  29. #include <algorithm>
  30. #include "stmlib/dsp/dsp.h"
  31. #include "stmlib/system/storage.h"
  32. #include "stmlib/utils/random.h"
  33. #include "rings/dsp/part.h"
  34. #include "rings/dsp/patch.h"
  35. namespace rings {
  36. using namespace std;
  37. using namespace stmlib;
  38. /* static */
  39. ChannelSettings CvScaler::channel_settings_[ADC_CHANNEL_LAST] = {
  40. { LAW_LINEAR, true, 1.00f }, // ADC_CHANNEL_CV_FREQUENCY
  41. { LAW_LINEAR, true, 0.1f }, // ADC_CHANNEL_CV_STRUCTURE
  42. { LAW_LINEAR, true, 0.1f }, // ADC_CHANNEL_CV_BRIGHTNESS
  43. { LAW_LINEAR, true, 0.05f }, // ADC_CHANNEL_CV_DAMPING
  44. { LAW_LINEAR, true, 0.01f }, // ADC_CHANNEL_CV_POSITION
  45. { LAW_LINEAR, false, 1.00f }, // ADC_CHANNEL_CV_V_OCT
  46. { LAW_LINEAR, false, 0.01f }, // ADC_CHANNEL_POT_FREQUENCY
  47. { LAW_LINEAR, false, 0.01f }, // ADC_CHANNEL_POT_STRUCTURE
  48. { LAW_LINEAR, false, 0.01f }, // ADC_CHANNEL_POT_BRIGHTNESS
  49. { LAW_LINEAR, false, 0.01f }, // ADC_CHANNEL_POT_DAMPING
  50. { LAW_LINEAR, false, 0.01f }, // ADC_CHANNEL_POT_POSITION
  51. { LAW_QUARTIC_BIPOLAR, false, 0.005f }, // ADC_CHANNEL_ATTENUVERTER_FREQUENCY
  52. { LAW_QUADRATIC_BIPOLAR, false, 0.005f }, //ADC_CHANNEL_ATTENUVERTER_STRUCTURE,
  53. { LAW_QUADRATIC_BIPOLAR, false, 0.005f }, // ADC_CHANNEL_ATTENUVERTER_BRIGHTNESS,
  54. { LAW_QUADRATIC_BIPOLAR, false, 0.005f }, // ADC_CHANNEL_ATTENUVERTER_DAMPING,
  55. { LAW_QUADRATIC_BIPOLAR, false, 0.005f }, // ADC_CHANNEL_ATTENUVERTER_POSITION,
  56. };
  57. void CvScaler::Init(CalibrationData* calibration_data) {
  58. calibration_data_ = calibration_data;
  59. adc_.Init();
  60. trigger_input_.Init();
  61. transpose_ = 0.0f;
  62. fill(&adc_lp_[0], &adc_lp_[ADC_CHANNEL_LAST], 0.0f);
  63. normalization_probe_.Init();
  64. normalization_detector_exciter_.Init(0.01f, 0.5f);
  65. normalization_detector_trigger_.Init(0.05f, 0.9f);
  66. normalization_detector_v_oct_.Init(0.01f, 0.5f);
  67. inhibit_strum_ = 0;
  68. fm_cv_ = 0.0f;
  69. normalization_probe_enabled_ = true;
  70. normalization_probe_forced_state_ = false;
  71. }
  72. void CvScaler::DetectAudioNormalization(Codec::Frame* in, size_t size) {
  73. int32_t count = 0;
  74. short* input_samples = &in->r;
  75. for (size_t i = 0; i < size; i += 8) {
  76. short s = input_samples[i * 2];
  77. if (s > 50 && s < 1500) {
  78. ++count;
  79. } else if (s > -1500 && s < -50) {
  80. --count;
  81. }
  82. }
  83. float y = static_cast<float>(count) / static_cast<float>(size >> 3);
  84. float x = normalization_probe_value_[1] ? -1.0f : 1.0f;
  85. normalization_detector_exciter_.Process(x, y);
  86. if (normalization_detector_exciter_.normalized()) {
  87. for (size_t i = 0; i < size; ++i) {
  88. input_samples[i * 2] = 0;
  89. }
  90. }
  91. }
  92. void CvScaler::DetectNormalization() {
  93. if (normalization_probe_value_[0] == trigger_input_.DummyRead()) {
  94. normalization_detector_trigger_.Process(1.0f, 1.0f);
  95. } else {
  96. normalization_detector_trigger_.Process(1.0f, -1.0f);
  97. }
  98. float x = adc_.float_value(ADC_CHANNEL_CV_V_OCT) - calibration_data_->normalization_detection_threshold;
  99. float y = normalization_probe_value_[0] ? -1.0f : 1.0f;
  100. if (x > -0.5f && x < 0.5f) {
  101. x = x < 0.0f ? -1.0f : 1.0f;
  102. normalization_detector_v_oct_.Process(x, y);
  103. } else {
  104. normalization_detector_v_oct_.Process(0.0f, y);
  105. }
  106. normalization_probe_value_[1] = normalization_probe_value_[0];
  107. normalization_probe_value_[0] = Random::GetWord() >> 31;
  108. bool new_state = normalization_probe_enabled_
  109. ? normalization_probe_value_[0]
  110. : normalization_probe_forced_state_;
  111. normalization_probe_.Write(new_state);
  112. }
  113. #define ATTENUVERT(destination, NAME, min, max) \
  114. { \
  115. float value = adc_lp_[ADC_CHANNEL_CV_ ## NAME]; \
  116. value *= adc_lp_[ADC_CHANNEL_ATTENUVERTER_ ## NAME]; \
  117. value += adc_lp_[ADC_CHANNEL_POT_ ## NAME]; \
  118. CONSTRAIN(value, min, max) \
  119. destination = value; \
  120. }
  121. void CvScaler::Read(Patch* patch, PerformanceState* performance_state) {
  122. // Process all CVs / pots.
  123. for (size_t i = 0; i < ADC_CHANNEL_LAST; ++i) {
  124. const ChannelSettings& settings = channel_settings_[i];
  125. float value = adc_.float_value(i);
  126. if (settings.remove_offset) {
  127. value = calibration_data_->offset[i] - value;
  128. }
  129. switch (settings.law) {
  130. case LAW_QUADRATIC_BIPOLAR:
  131. {
  132. value = value - 0.5f;
  133. float value2 = value * value * 4.0f * 3.3f;
  134. value = value < 0.0f ? -value2 : value2;
  135. }
  136. break;
  137. case LAW_QUARTIC_BIPOLAR:
  138. {
  139. value = value - 0.5f;
  140. float value2 = value * value * 4.0f;
  141. float value4 = value2 * value2 * 3.3f;
  142. value = value < 0.0f ? -value4 : value4;
  143. }
  144. break;
  145. default:
  146. break;
  147. }
  148. adc_lp_[i] += settings.lp_coefficient * (value - adc_lp_[i]);
  149. }
  150. ATTENUVERT(patch->structure, STRUCTURE, 0.0f, 0.9995f);
  151. ATTENUVERT(patch->brightness, BRIGHTNESS, 0.0f, 1.0f);
  152. ATTENUVERT(patch->damping, DAMPING, 0.0f, 1.0f);
  153. ATTENUVERT(patch->position, POSITION, 0.0f, 1.0f);
  154. float fm = adc_lp_[ADC_CHANNEL_CV_FREQUENCY] * 48.0f;
  155. float error = fm - fm_cv_;
  156. if (fabs(error) >= 0.8f) {
  157. fm_cv_ = fm;
  158. } else {
  159. fm_cv_ += 0.02f * error;
  160. }
  161. performance_state->fm = fm_cv_ * adc_lp_[ADC_CHANNEL_ATTENUVERTER_FREQUENCY];
  162. CONSTRAIN(performance_state->fm, -48.0f, 48.0f);
  163. float transpose = 60.0f * adc_lp_[ADC_CHANNEL_POT_FREQUENCY];
  164. float hysteresis = transpose - transpose_ > 0.0f ? -0.3f : +0.3f;
  165. transpose_ = static_cast<int32_t>(transpose + hysteresis + 0.5f);
  166. float note = calibration_data_->pitch_offset;
  167. note += adc_lp_[ADC_CHANNEL_CV_V_OCT] * calibration_data_->pitch_scale;
  168. performance_state->note = note;
  169. performance_state->tonic = 12.0f + transpose_;
  170. DetectNormalization();
  171. // Strumming / internal exciter triggering logic.
  172. bool internal_strum = normalization_detector_trigger_.normalized();
  173. bool internal_exciter = normalization_detector_exciter_.normalized();
  174. bool internal_note = normalization_detector_v_oct_.normalized();
  175. performance_state->internal_exciter = internal_exciter;
  176. performance_state->internal_strum = internal_strum;
  177. performance_state->internal_note = internal_note;
  178. performance_state->strum = trigger_input_.rising_edge();
  179. if (performance_state->internal_note) {
  180. // Remove quantization when nothing is plugged in the V/OCT input.
  181. performance_state->note = 0.0f;
  182. performance_state->tonic = 12.0f + transpose;
  183. }
  184. // Hysteresis on chord.
  185. float chord = calibration_data_->offset[ADC_CHANNEL_CV_STRUCTURE] - \
  186. adc_.float_value(ADC_CHANNEL_CV_STRUCTURE);
  187. chord *= adc_lp_[ADC_CHANNEL_ATTENUVERTER_STRUCTURE];
  188. chord += adc_lp_[ADC_CHANNEL_POT_STRUCTURE];
  189. chord *= static_cast<float>(kNumChords - 1);
  190. hysteresis = chord - chord_ > 0.0f ? -0.1f : +0.1f;
  191. chord_ = static_cast<int32_t>(chord + hysteresis + 0.5f);
  192. CONSTRAIN(chord_, 0, kNumChords - 1);
  193. performance_state->chord = chord_;
  194. adc_.Convert();
  195. trigger_input_.Read();
  196. }
  197. } // namespace rings