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.

139 lines
4.2KB

  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. // Variable resolution quantizer.
  28. #include "marbles/random/quantizer.h"
  29. #include "stmlib/dsp/dsp.h"
  30. #include <cmath>
  31. #include <algorithm>
  32. namespace marbles {
  33. using namespace std;
  34. void Quantizer::Init(const Scale& scale) {
  35. int n = scale.num_degrees;
  36. // We don't want garbage scale data here...
  37. if (!n || n > kMaxDegrees || scale.base_interval == 0.0f) {
  38. return;
  39. }
  40. num_degrees_ = n;
  41. base_interval_ = scale.base_interval;
  42. base_interval_reciprocal_ = 1.0f / scale.base_interval;
  43. uint8_t second_largest_threshold = 0;
  44. for (int i = 0; i < n; ++i) {
  45. voltage_[i] = scale.degree[i].voltage;
  46. if (scale.degree[i].weight != 255 && \
  47. scale.degree[i].weight >= second_largest_threshold) {
  48. second_largest_threshold = scale.degree[i].weight;
  49. }
  50. }
  51. uint8_t thresholds_[kNumThresholds] = {
  52. 0, 16, 32, 64, 128, 192, 255
  53. };
  54. if (second_largest_threshold > 192) {
  55. // Be more selective to only include the notes at rank 1 and 2 at
  56. // the last but one position.
  57. thresholds_[kNumThresholds - 2] = second_largest_threshold;
  58. }
  59. for (int t = 0; t < kNumThresholds; ++t) {
  60. uint16_t bitmask = 0;
  61. uint8_t first = 0xff;
  62. uint8_t last = 0;
  63. for (int i = 0; i < n; ++i) {
  64. if (scale.degree[i].weight >= thresholds_[t]) {
  65. bitmask |= 1 << i;
  66. if (first == 0xff) first = i;
  67. last = i;
  68. }
  69. }
  70. level_[t].bitmask = bitmask;
  71. level_[t].first = first;
  72. level_[t].last = last;
  73. }
  74. level_quantizer_.Init();
  75. fill(&feedback_[0], &feedback_[kNumThresholds], 0.0f);
  76. }
  77. float Quantizer::Process(float value, float amount, bool hysteresis) {
  78. int level = level_quantizer_.Process(amount, kNumThresholds + 1);
  79. float quantized_voltage = value;
  80. if (level > 0) {
  81. level -= 1;
  82. float raw_value = value;
  83. if (hysteresis) {
  84. value += feedback_[level];
  85. }
  86. const float note = value * base_interval_reciprocal_;
  87. MAKE_INTEGRAL_FRACTIONAL(note);
  88. if (value < 0.0f) {
  89. note_integral -= 1;
  90. note_fractional += 1.0f;
  91. }
  92. note_fractional *= base_interval_;
  93. // Search for the tightest upper/lower bound in the set of available
  94. // voltages. stl::upper_bound / stl::lower_bound wouldn't work here
  95. // because some entries are masked.
  96. Level l = level_[level];
  97. float a = voltage_[l.last] - base_interval_;
  98. float b = voltage_[l.first] + base_interval_;
  99. uint16_t bitmask = l.bitmask;
  100. for (int i = 0; i < num_degrees_; ++i) {
  101. if (bitmask & 1) {
  102. float v = voltage_[i];
  103. if (note_fractional > v) {
  104. a = v;
  105. } else {
  106. b = v;
  107. break;
  108. }
  109. }
  110. bitmask >>= 1;
  111. }
  112. quantized_voltage = note_fractional < (a + b) * 0.5f ? a : b;
  113. quantized_voltage += static_cast<float>(note_integral) * base_interval_;
  114. feedback_[level] = (quantized_voltage - raw_value) * 0.25f;
  115. }
  116. return quantized_voltage;
  117. }
  118. } // namespace marbles