Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

4 роки тому
4 роки тому
4 роки тому
4 роки тому
4 роки тому
4 роки тому
4 роки тому
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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. #ifndef resampler_h_
  30. #define resampler_h_
  31. #include "Arduino.h"
  32. //#define DEBUG_RESAMPLER //activates debug output
  33. #define MAX_FILTER_SAMPLES 40961 //=1024*20 +1
  34. #define NO_EXACT_KAISER_SAMPLES 1025
  35. #define MAX_HALF_FILTER_LENGTH 80
  36. #define MAX_NO_CHANNELS 8
  37. class Resampler {
  38. public:
  39. struct StepAdaptionParameters {
  40. StepAdaptionParameters(){}
  41. double alpha =0.2; //exponential smoothing parameter
  42. double maxAdaption = 0.01; //maximum relative allowed adaption of resampler step 0.01 = 1%
  43. double kp= 0.6;
  44. double ki=0.00012;
  45. double kd= 1.8;
  46. };
  47. Resampler(float attenuation=100, int32_t minHalfFilterLength=20, int32_t maxHalfFilterLength=80, StepAdaptionParameters settings=StepAdaptionParameters());
  48. void reset();
  49. ///@param attenuation target attenuation [dB] of the anti-aliasing filter. Only used if newFs<fs. The attenuation can't be reached if the needed filter length exceeds 2*MAX_FILTER_SAMPLES+1
  50. ///@param minHalfFilterLength If newFs >= fs, the filter length of the resampling filter is 2*minHalfFilterLength+1. If fs y newFs the filter is maybe longer to reach the desired attenuation
  51. void configure(float fs, float newFs);
  52. ///@param input0 first input array/ channel
  53. ///@param input1 second input array/ channel
  54. ///@param inputLength length of each input array
  55. ///@param processedLength number of samples of the input that were resampled to fill the output array
  56. ///@param output0 first output array/ channel
  57. ///@param output1 second output array/ channel
  58. ///@param outputLength length of each output array
  59. ///@param outputCount number of samples of each output array, that were filled with data
  60. void resample(float* input0, float* input1, uint16_t inputLength, uint16_t& processedLength, float* output0, float* output1,uint16_t outputLength, uint16_t& outputCount);
  61. bool addToSampleDiff(double diff);
  62. double getXPos() const;
  63. double getStep() const;
  64. void addToPos(double val);
  65. void fixStep();
  66. bool initialized() const;
  67. double getAttenuation() const;
  68. int32_t getHalfFilterLength() const;
  69. //resampling NOCHANNELS channels. Performance is increased a lot if the number of channels is known at compile time -> the number of channels is a template argument
  70. template <uint8_t NOCHANNELS>
  71. inline void resample(float** inputs, uint16_t inputLength, uint16_t& processedLength, float** outputs, uint16_t outputLength, uint16_t& outputCount){
  72. outputCount=0;
  73. int32_t successorIndex=(int32_t)(ceil(_cPos)); //negative number -> currently the _buffer0 of the last iteration is used
  74. float* ip[NOCHANNELS];
  75. float* fPtr;
  76. float si0[NOCHANNELS];
  77. float* si0Ptr;
  78. float si1[NOCHANNELS];
  79. float* si1Ptr;
  80. while (floor(_cPos + _halfFilterLength) < inputLength && outputCount < outputLength){
  81. float dist=successorIndex-_cPos;
  82. float distScaled=dist*_overSamplingFactor;
  83. int32_t rightIndex=abs((int32_t)(ceil(distScaled))-_overSamplingFactor*_halfFilterLength);
  84. const int32_t indexData=successorIndex-_halfFilterLength;
  85. if (indexData>=0){
  86. for (uint8_t i =0; i< NOCHANNELS; i++){
  87. ip[i]=inputs[i]+indexData;
  88. }
  89. }
  90. else {
  91. for (uint8_t i =0; i< NOCHANNELS; i++){
  92. ip[i]=_buffer[i]+indexData+_filterLength;
  93. }
  94. }
  95. fPtr=filter+rightIndex;
  96. memset(si0, 0, NOCHANNELS*sizeof(float));
  97. if (rightIndex==_overSamplingFactor*_halfFilterLength){
  98. si1Ptr=si1;
  99. for (uint8_t i=0; i< NOCHANNELS; i++){
  100. *(si1Ptr++)=*ip[i]++**fPtr;
  101. }
  102. fPtr-=_overSamplingFactor;
  103. rightIndex=(int32_t)(ceil(distScaled))+_overSamplingFactor; //needed below
  104. }
  105. else {
  106. memset(si1, 0, NOCHANNELS*sizeof(float));
  107. rightIndex=(int32_t)(ceil(distScaled)); //needed below
  108. }
  109. for (uint16_t i =0 ; i<_halfFilterLength; i++){
  110. if(ip[0]==_endOfBuffer[0]){
  111. for (uint8_t i =0; i< NOCHANNELS; i++){
  112. ip[i]=inputs[i];
  113. }
  114. }
  115. const float fPtrSucc=*(fPtr+1);
  116. si0Ptr=si0;
  117. si1Ptr=si1;
  118. for (uint8_t i =0; i< NOCHANNELS; i++){
  119. *(si0Ptr++)+=*ip[i]*fPtrSucc;
  120. *(si1Ptr++)+=*ip[i]**fPtr;
  121. ++ip[i];
  122. }
  123. fPtr-=_overSamplingFactor;
  124. }
  125. fPtr=filter+rightIndex-1;
  126. for (uint16_t i =0 ; i<_halfFilterLength; i++){
  127. if(ip[0]==_endOfBuffer[0]){
  128. for (uint8_t i =0; i< NOCHANNELS; i++){
  129. ip[i]=inputs[i];
  130. }
  131. }
  132. const float fPtrSucc=*(fPtr+1);
  133. si0Ptr=si0;
  134. si1Ptr=si1;
  135. for (uint8_t i =0; i< NOCHANNELS; i++){
  136. *(si0Ptr++)+=*ip[i]**fPtr;
  137. *(si1Ptr++)+=*ip[i]*fPtrSucc;
  138. ++ip[i];
  139. }
  140. fPtr+=_overSamplingFactor;
  141. }
  142. const float w0=ceil(distScaled)-distScaled;
  143. const float w1=1.-w0;
  144. si0Ptr=si0;
  145. si1Ptr=si1;
  146. for (uint8_t i =0; i< NOCHANNELS; i++){
  147. *outputs[i]++=*(si0Ptr++)*w0 + *(si1Ptr++)*w1;
  148. }
  149. outputCount++;
  150. _cPos+=_stepAdapted;
  151. while (_cPos >successorIndex){
  152. successorIndex++;
  153. }
  154. }
  155. if(outputCount < outputLength){
  156. //ouput vector not full -> we ran out of input samples
  157. processedLength=inputLength;
  158. }
  159. else{
  160. processedLength=min(inputLength, (int16_t)floor(_cPos + _halfFilterLength));
  161. }
  162. //fill _buffer
  163. const int32_t indexData=processedLength-_filterLength;
  164. if (indexData>=0){
  165. const unsigned long long bytesToCopy= _filterLength*sizeof(float);
  166. float** inPtr=inputs;
  167. for (uint8_t i =0; i< NOCHANNELS; i++){
  168. memcpy((void *)_buffer[i], (void *)((*inPtr)+indexData), bytesToCopy);
  169. ++inPtr;
  170. }
  171. }
  172. else {
  173. float** inPtr=inputs;
  174. for (uint8_t i =0; i< NOCHANNELS; i++){
  175. float* b=_buffer[i];
  176. float* ip=b+indexData+_filterLength;
  177. for (uint16_t j =0; j< _filterLength; j++){
  178. if(ip==_endOfBuffer[i]){
  179. ip=*inPtr;
  180. }
  181. *b++ = *ip++;
  182. }
  183. ++inPtr;
  184. }
  185. }
  186. _cPos-=processedLength;
  187. if (_cPos < -_halfFilterLength){
  188. _cPos=-_halfFilterLength;
  189. }
  190. }
  191. private:
  192. void getKaiserExact(float beta);
  193. void setKaiserWindow(float beta, int32_t noSamples);
  194. void setFilter(int32_t halfFiltLength,int32_t overSampling, float cutOffFrequ, float kaiserBeta);
  195. float filter[MAX_FILTER_SAMPLES];
  196. double kaiserWindowSamples[NO_EXACT_KAISER_SAMPLES];
  197. double tempRes[NO_EXACT_KAISER_SAMPLES-1];
  198. double kaiserWindowXsq[NO_EXACT_KAISER_SAMPLES-1];
  199. float _buffer[MAX_NO_CHANNELS][MAX_HALF_FILTER_LENGTH*2];
  200. float* _endOfBuffer[MAX_NO_CHANNELS];
  201. int32_t _minHalfFilterLength;
  202. int32_t _maxHalfFilterLength;
  203. int32_t _overSamplingFactor;
  204. int32_t _halfFilterLength;
  205. int32_t _filterLength;
  206. bool _initialized=false;
  207. const double _settledThrs = 1e-6;
  208. StepAdaptionParameters _settings;
  209. double _configuredStep;
  210. double _step;
  211. double _stepAdapted;
  212. double _cPos;
  213. double _sum;
  214. double _oldDiffs[2];
  215. double _attenuation=0;
  216. float _targetAttenuation=100;
  217. };
  218. #endif