Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

synth_dc.h 4.4KB

10 anos atrás
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /* Audio Library for Teensy 3.X
  2. * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com
  3. *
  4. * Development of this audio library was funded by PJRC.COM, LLC by sales of
  5. * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop
  6. * open source software by purchasing Teensy or other PJRC products.
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice, development funding notice, and this permission
  16. * notice shall be included in all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #ifndef synth_dc_h_
  27. #define synth_dc_h_
  28. #include "AudioStream.h"
  29. #include "utility/dspinst.h"
  30. // compute (a - b) / c
  31. // handling 32 bit interger overflow at every step
  32. // without resorting to slow 64 bit math
  33. #if 0
  34. // TODO: write this in assembly....
  35. static inline int32_t substract_32_then_divide(int32_t a, int32_t b, int32_t c) __attribute__((always_inline, unused));
  36. static inline int32_t substract_32_then_divide(int32_t a, int32_t b, int32_t c)
  37. {
  38. int32_t diff = substract_32_saturate(a, b);
  39. // if only C language provided a way to test Q status bit....
  40. if (diff != 0x7FFFFFFF && diff != 0x80000000) {
  41. return diff / c;
  42. } else {
  43. diff = substract_32_saturate(a/2, b/2);
  44. if (c == 1 || c == -1) c *= 2; // <-- horrible, incorrect hack
  45. return (diff / c) * 2;
  46. }
  47. }
  48. #else
  49. // compute (a - b) / c ... handling 32 bit interger overflow without slow 64 bit math
  50. static inline int32_t substract_int32_then_divide_int32(int32_t a, int32_t b, int32_t c) __attribute__((always_inline, unused));
  51. static inline int32_t substract_int32_then_divide_int32(int32_t a, int32_t b, int32_t c)
  52. {
  53. uint32_t diff;
  54. uint8_t negative;
  55. if (a >= 0) {
  56. if (b >= 0) {
  57. return (a - b) / c; // no overflow if both a & b are positive
  58. } else {
  59. diff = a + (b * -1); // assumes 0x80000000 * -1 == 0x80000000
  60. negative = 0;
  61. }
  62. } else {
  63. if (b >= 0) {
  64. diff = (a * -1) + b; // assumes 0x80000000 * -1 == 0x80000000
  65. negative = 1;
  66. } else {
  67. return (a - b) / c; // no overflow if both a & b are negative
  68. }
  69. }
  70. if (c >= 0) {
  71. diff = diff / (uint32_t)c;
  72. } else {
  73. diff = diff / (uint32_t)(c * -1);
  74. negative ^= 1;
  75. }
  76. if (negative) {
  77. if (diff > 0x7FFFFFFF) return 0x80000000;
  78. return (int32_t)diff * -1;
  79. } else {
  80. if (diff > 0x7FFFFFFF) return 0x7FFFFFFF;
  81. return (int32_t)diff;
  82. }
  83. }
  84. #endif
  85. class AudioSynthWaveformDc : public AudioStream
  86. {
  87. public:
  88. AudioSynthWaveformDc() : AudioStream(0, NULL), state(0), magnitude(0) {}
  89. // immediately jump to the new DC level
  90. void amplitude(float n) {
  91. if (n > 1.0) n = 1.0;
  92. else if (n < -1.0) n = -1.0;
  93. int32_t m = (int32_t)(n * 2147418112.0);
  94. __disable_irq();
  95. magnitude = m;
  96. state = 0;
  97. __enable_irq();
  98. }
  99. // slowly transition to the new DC level
  100. void amplitude(float n, float milliseconds) {
  101. if (milliseconds <= 0.0) {
  102. amplitude(n);
  103. return;
  104. }
  105. if (n > 1.0) n = 1.0;
  106. else if (n < -1.0) n = -1.0;
  107. int32_t c = (int32_t)(milliseconds*(AUDIO_SAMPLE_RATE_EXACT/1000.0));
  108. if (c == 0) {
  109. amplitude(n);
  110. return;
  111. }
  112. int32_t t = (int32_t)(n * 2147418112.0);
  113. __disable_irq();
  114. target = t;
  115. if (target == magnitude) {
  116. state = 0;
  117. __enable_irq();
  118. return;
  119. }
  120. increment = substract_int32_then_divide_int32(target, magnitude, c);
  121. if (increment == 0) {
  122. increment = (target > magnitude) ? 1 : -1;
  123. }
  124. state = 1;
  125. __enable_irq();
  126. }
  127. virtual void update(void);
  128. private:
  129. uint8_t state; // 0=steady output, 1=transitioning
  130. int32_t magnitude; // current output
  131. int32_t target; // designed output (while transitiong)
  132. int32_t increment; // adjustment per sample (while transitiong)
  133. };
  134. #endif