PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

232 líneas
7.7KB

  1. /* Audio Library for Teensy 3.X
  2. * Copyright (c) 2019, 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. /*
  27. by Alexander Walch
  28. */
  29. #include "Quantizer.h"
  30. #define SAMPLEINVALID(sample) (!isfinite(sample) || abs(sample) >= 1.2) //use only for floating point samples (\in [-1.,1.])
  31. Quantizer::Quantizer(float audio_sample_rate){
  32. #ifdef DEBUG_QUANTIZER
  33. while(!Serial);
  34. #endif
  35. randomSeed(1);
  36. if(audio_sample_rate==44100.f){
  37. _noiseSFilter[0]=-0.06935825f;
  38. _noiseSFilter[1]=0.52540845f;
  39. _noiseSFilter[2]= -1.20537028f;
  40. _noiseSFilter[3]= 2.09422811f;
  41. _noiseSFilter[4]= -3.2177438f;
  42. _noiseSFilter[5]= 4.04852027f;
  43. _noiseSFilter[6]= -3.83872701f;
  44. _noiseSFilter[7]= 3.30584589f;
  45. _noiseSFilter[8]= -2.38682527f;
  46. // all coefficients in correct order:
  47. // {1. , -2.38682527, 3.30584589, -3.83872701, 4.04852027,
  48. // -3.2177438 , 2.09422811, -1.20537028, 0.52540845, -0.06935825};
  49. } else if(audio_sample_rate==48000.f){
  50. _noiseSFilter[0]=0.1967454f;
  51. _noiseSFilter[1]=-0.30086406f;
  52. _noiseSFilter[2]= 0.09575588f;
  53. _noiseSFilter[3]= 0.58209648f;
  54. _noiseSFilter[4]= -1.88579617f;
  55. _noiseSFilter[5]= 3.37325788f;
  56. _noiseSFilter[6]= -3.88076402f;
  57. _noiseSFilter[7]= 3.58558504f;
  58. _noiseSFilter[8]= -2.54334066f;
  59. // all coefficients in correct order:
  60. // {1. , -2.54334066, 3.58558504, -3.88076402, 3.37325788,
  61. // -1.88579617, 0.58209648, 0.09575588, -0.30086406, 0.1967454};
  62. // }
  63. }
  64. else {
  65. _noiseSFilter[0]=0.f;
  66. _noiseSFilter[1]=0.f;
  67. _noiseSFilter[2]=0.f;
  68. _noiseSFilter[3]=0.f;
  69. _noiseSFilter[4]=0.f;
  70. _noiseSFilter[5]=0.f;
  71. _noiseSFilter[6]=0.f;
  72. _noiseSFilter[7]=0.f;
  73. _noiseSFilter[8]=0.f;
  74. }
  75. _bufferEnd0=&_buffer0[NOISE_SHAPE_F_LENGTH];
  76. reset();
  77. }
  78. void Quantizer::configure(bool noiseShaping, bool dither, float factor){
  79. _noiseShaping=noiseShaping;
  80. _dither=dither;
  81. _factor=factor;
  82. reset();
  83. }
  84. void Quantizer::reset(){
  85. _bPtr0=_buffer0;
  86. _bPtr1=_buffer1;
  87. _fOutputLastIt0=0.;
  88. _fOutputLastIt1=0.;
  89. memset(_buffer0, 0, NOISE_SHAPE_F_LENGTH*sizeof(float));
  90. memset(_buffer1, 0, NOISE_SHAPE_F_LENGTH*sizeof(float));
  91. }
  92. void Quantizer::quantize(float* input, int16_t* output, uint16_t length){
  93. float xn, xnD, error;
  94. const float f2 = 1.f/1000000.f;
  95. #ifdef DEBUG_QUANTIZER
  96. float debugFF=1024.f;
  97. const float factor=(powf(2.f, 15.f)-1.f)/debugFF;
  98. #endif
  99. for (uint16_t i =0; i< length; i++){
  100. xn= SAMPLEINVALID(*input) ? 0. : *input*_factor; //-_fOutputLastIt0 according to paper
  101. ++input;
  102. if (_noiseShaping){
  103. xn+=_fOutputLastIt0;
  104. }
  105. if(_dither){
  106. const uint32_t r0=random(1000000);
  107. const uint32_t r1=random(1000000);
  108. xnD=xn + (r0 + r1)*f2-1.f;
  109. }
  110. else {
  111. xnD=xn;
  112. }
  113. float xnDR=round(xnD);
  114. if (_noiseShaping){
  115. //compute quatization error:
  116. error=xnDR- xn;
  117. *_bPtr0++=error;
  118. if (_bPtr0==_bufferEnd0){
  119. _bPtr0=_buffer0;
  120. }
  121. float* f=_noiseSFilter;
  122. _fOutputLastIt0=(*_bPtr0++ * *f++);
  123. if (_bPtr0==_bufferEnd0){
  124. _bPtr0=_buffer0;
  125. }
  126. for (uint16_t j =1; j< NOISE_SHAPE_F_LENGTH; j++){
  127. _fOutputLastIt0+=(*_bPtr0++ * *f++);
  128. if (_bPtr0==_bufferEnd0){
  129. _bPtr0=_buffer0;
  130. }
  131. }
  132. }
  133. #ifdef DEBUG_QUANTIZER
  134. xnDR*=debugFF;
  135. #endif
  136. if (xnDR > _factor){
  137. *output=(int16_t)_factor;
  138. }
  139. else if (xnDR < -_factor){
  140. *output=(int16_t)_factor;
  141. }
  142. else {
  143. *output=(int16_t)xnDR;
  144. }
  145. ++output;
  146. }
  147. }
  148. void Quantizer::quantize(float* input0, float* input1, int32_t* outputInterleaved, uint16_t length){
  149. float xn0, xnD0, error0,xnDR0, xn1, xnD1, error1,xnDR1;
  150. const float f2 = 1.f/1000000.f;
  151. #ifdef DEBUG_QUANTIZER
  152. float debugFF=1024.f;
  153. const float factor=(powf(2.f, 15.f)-1.f)/debugFF;
  154. #endif
  155. for (uint16_t i =0; i< length; i++){
  156. xn0= SAMPLEINVALID(*input0) ? 0. : *input0*_factor; //-_fOutputLastIt0 according to paper
  157. ++input0;
  158. xn1= SAMPLEINVALID(*input1) ? 0. : *input1*_factor; //-_fOutputLastIt0 according to paper
  159. ++input1;
  160. if (_noiseShaping){
  161. xn0+=_fOutputLastIt0;
  162. xn1+=_fOutputLastIt1;
  163. }
  164. if(_dither){
  165. uint32_t r0=random(1000000);
  166. uint32_t r1=random(1000000);
  167. xnD0=xn0 + (r0 + r1)*f2-1.f;
  168. r0=random(1000000);
  169. r1=random(1000000);
  170. xnD1=xn1 + (r0 + r1)*f2-1.f;
  171. }
  172. else {
  173. xnD0=xn0;
  174. xnD1=xn1;
  175. }
  176. xnDR0=round(xnD0);
  177. xnDR1=round(xnD1);
  178. if (_noiseShaping){
  179. //compute quatization error0:
  180. error0=xnDR0- xn0;
  181. error1=xnDR1- xn1;
  182. *_bPtr0++=error0;
  183. *_bPtr1++=error1;
  184. if (_bPtr0==_bufferEnd0){
  185. _bPtr0=_buffer0;
  186. _bPtr1=_buffer1;
  187. }
  188. float* f=_noiseSFilter;
  189. _fOutputLastIt0=(*_bPtr0++ * *f);
  190. _fOutputLastIt1=(*_bPtr1++ * *f++);
  191. if (_bPtr0==_bufferEnd0){
  192. _bPtr0=_buffer0;
  193. _bPtr1=_buffer1;
  194. }
  195. for (uint16_t j =1 ; j< NOISE_SHAPE_F_LENGTH; j++){
  196. _fOutputLastIt0+=(*_bPtr0++ * *f);
  197. _fOutputLastIt1+=(*_bPtr1++ * *f++);
  198. if (_bPtr0==_bufferEnd0){
  199. _bPtr0=_buffer0;
  200. _bPtr1=_buffer1;
  201. }
  202. }
  203. }
  204. #ifdef DEBUG_QUANTIZER
  205. xnDR0*=debugFF;
  206. #endif
  207. if (xnDR0 > _factor){
  208. *outputInterleaved++=(int32_t)_factor;
  209. }
  210. else if (xnDR0 < -_factor){
  211. *outputInterleaved++=-(int32_t)_factor;
  212. }
  213. else {
  214. *outputInterleaved++=(int32_t)xnDR0;
  215. }
  216. if (xnDR1 > _factor){
  217. *outputInterleaved++=(int32_t)_factor;
  218. }
  219. else if (xnDR1 < -_factor){
  220. *outputInterleaved++=-(int32_t)_factor;
  221. }
  222. else {
  223. *outputInterleaved++=(int32_t)xnDR1;
  224. }
  225. }
  226. }