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.

163 lines
4.2KB

  1. // Copyright 2012 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. // Oscillator - analog style waveforms.
  28. #ifndef BRAIDS_ANALOG_OSCILLATOR_H_
  29. #define BRAIDS_ANALOG_OSCILLATOR_H_
  30. #include "stmlib/stmlib.h"
  31. #include <cstring>
  32. #include <cstdio>
  33. #include "braids/resources.h"
  34. namespace braids {
  35. enum AnalogOscillatorShape {
  36. OSC_SHAPE_SAW,
  37. OSC_SHAPE_VARIABLE_SAW,
  38. OSC_SHAPE_CSAW,
  39. OSC_SHAPE_SQUARE,
  40. OSC_SHAPE_TRIANGLE,
  41. OSC_SHAPE_SINE,
  42. OSC_SHAPE_TRIANGLE_FOLD,
  43. OSC_SHAPE_SINE_FOLD,
  44. OSC_SHAPE_BUZZ
  45. };
  46. enum SyncMode {
  47. OSCILLATOR_SYNC_MODE_OFF,
  48. OSCILLATOR_SYNC_MODE_MASTER,
  49. OSCILLATOR_SYNC_MODE_SLAVE
  50. };
  51. class AnalogOscillator {
  52. public:
  53. typedef void (AnalogOscillator::*RenderFn)(
  54. const uint8_t*,
  55. int16_t*,
  56. uint8_t*,
  57. size_t);
  58. AnalogOscillator() { }
  59. ~AnalogOscillator() { }
  60. inline void Init() {
  61. phase_ = 0;
  62. phase_increment_ = 1;
  63. high_ = false;
  64. parameter_ = previous_parameter_ = 0;
  65. aux_parameter_ = 0;
  66. discontinuity_depth_ = -16383;
  67. pitch_ = 60 << 7;
  68. next_sample_ = 0;
  69. }
  70. inline void set_shape(AnalogOscillatorShape shape) {
  71. shape_ = shape;
  72. }
  73. inline void set_pitch(int16_t pitch) {
  74. pitch_ = pitch;
  75. }
  76. inline void set_parameter(int16_t parameter) {
  77. parameter_ = parameter;
  78. }
  79. inline void set_aux_parameter(int16_t parameter) {
  80. aux_parameter_ = parameter;
  81. }
  82. inline uint32_t phase_increment() const {
  83. return phase_increment_;
  84. }
  85. inline void Reset() {
  86. phase_ = -phase_increment_;
  87. }
  88. void Render(
  89. const uint8_t* sync_in,
  90. int16_t* buffer,
  91. uint8_t* sync_out,
  92. size_t size);
  93. private:
  94. void RenderSquare(const uint8_t*, int16_t*, uint8_t*, size_t);
  95. void RenderSaw(const uint8_t*, int16_t*, uint8_t*, size_t);
  96. void RenderVariableSaw(const uint8_t*, int16_t*, uint8_t*, size_t);
  97. void RenderCSaw(const uint8_t*, int16_t*, uint8_t*, size_t);
  98. void RenderTriangle(const uint8_t*, int16_t*, uint8_t*, size_t);
  99. void RenderSine(const uint8_t*, int16_t*, uint8_t*, size_t);
  100. void RenderTriangleFold(const uint8_t*, int16_t*, uint8_t*, size_t);
  101. void RenderSineFold(const uint8_t*, int16_t*, uint8_t*, size_t);
  102. void RenderBuzz(const uint8_t*, int16_t*, uint8_t*, size_t);
  103. uint32_t ComputePhaseIncrement(int16_t midi_pitch);
  104. inline int32_t ThisBlepSample(uint32_t t) {
  105. if (t > 65535) {
  106. t = 65535;
  107. }
  108. return t * t >> 18;
  109. }
  110. inline int32_t NextBlepSample(uint32_t t) {
  111. if (t > 65535) {
  112. t = 65535;
  113. }
  114. t = 65535 - t;
  115. return -static_cast<int32_t>(t * t >> 18);
  116. }
  117. uint32_t phase_;
  118. uint32_t phase_increment_;
  119. uint32_t previous_phase_increment_;
  120. bool high_;
  121. int16_t parameter_;
  122. int16_t previous_parameter_;
  123. int16_t aux_parameter_;
  124. int16_t discontinuity_depth_;
  125. int16_t pitch_;
  126. int32_t next_sample_;
  127. AnalogOscillatorShape shape_;
  128. AnalogOscillatorShape previous_shape_;
  129. static RenderFn fn_table_[];
  130. DISALLOW_COPY_AND_ASSIGN(AnalogOscillator);
  131. };
  132. } // namespace braids
  133. #endif // BRAIDS_ANALOG_OSCILLATOR_H_