Audio plugin host https://kx.studio/carla
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.

260 lines
5.8KB

  1. // ----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 2006-2012 Fons Adriaensen <fons@linuxaudio.org>
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. //
  18. // ----------------------------------------------------------------------------
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <math.h>
  23. #include "resampler.h"
  24. static unsigned int gcd (unsigned int a, unsigned int b)
  25. {
  26. if (a == 0) return b;
  27. if (b == 0) return a;
  28. while (1)
  29. {
  30. if (a > b)
  31. {
  32. a = a % b;
  33. if (a == 0) return b;
  34. if (a == 1) return 1;
  35. }
  36. else
  37. {
  38. b = b % a;
  39. if (b == 0) return a;
  40. if (b == 1) return 1;
  41. }
  42. }
  43. return 1;
  44. }
  45. Resampler::Resampler (void) noexcept :
  46. _table (0),
  47. _nchan (0),
  48. _buff (0)
  49. {
  50. reset ();
  51. }
  52. Resampler::~Resampler (void)
  53. {
  54. clear ();
  55. }
  56. int Resampler::setup (unsigned int fs_inp,
  57. unsigned int fs_out,
  58. unsigned int nchan,
  59. unsigned int hlen)
  60. {
  61. if ((hlen < 8) || (hlen > 96)) return 1;
  62. return setup (fs_inp, fs_out, nchan, hlen, 1.0 - 2.6 / hlen);
  63. }
  64. int Resampler::setup (unsigned int fs_inp,
  65. unsigned int fs_out,
  66. unsigned int nchan,
  67. unsigned int hlen,
  68. double frel)
  69. {
  70. unsigned int g, h, k, n, s;
  71. double r;
  72. float *B = 0;
  73. Resampler_table *T = 0;
  74. k = s = 0;
  75. if (fs_inp && fs_out && nchan)
  76. {
  77. r = (double) fs_out / (double) fs_inp;
  78. g = gcd (fs_out, fs_inp);
  79. n = fs_out / g;
  80. s = fs_inp / g;
  81. if ((16 * r >= 1) && (n <= 1000))
  82. {
  83. h = hlen;
  84. k = 250;
  85. if (r < 1)
  86. {
  87. frel *= r;
  88. h = (unsigned int)(ceil (h / r));
  89. k = (unsigned int)(ceil (k / r));
  90. }
  91. T = Resampler_table::create (frel, h, n);
  92. B = new float [nchan * (2 * h - 1 + k)];
  93. }
  94. }
  95. clear ();
  96. if (T)
  97. {
  98. _table = T;
  99. _buff = B;
  100. _nchan = nchan;
  101. _inmax = k;
  102. _pstep = s;
  103. return reset ();
  104. }
  105. return 1;
  106. }
  107. void Resampler::clear (void)
  108. {
  109. Resampler_table::destroy (_table);
  110. delete[] _buff;
  111. _buff = 0;
  112. _table = 0;
  113. _nchan = 0;
  114. _inmax = 0;
  115. _pstep = 0;
  116. reset ();
  117. }
  118. double Resampler::inpdist (void) const noexcept
  119. {
  120. if (!_table) return 0;
  121. return (int)(_table->_hl + 1 - _nread) - (double)_phase / _table->_np;
  122. }
  123. unsigned int Resampler::inpsize (void) const noexcept
  124. {
  125. if (!_table) return 0;
  126. return 2 * _table->_hl;
  127. }
  128. bool Resampler::reset (void) noexcept
  129. {
  130. if (!_table) return false;
  131. inp_count = 0;
  132. out_count = 0;
  133. inp_data = nullptr;
  134. out_data = nullptr;
  135. _index = 0;
  136. _nread = 0;
  137. _nzero = 0;
  138. _phase = 0;
  139. _nread = 2 * _table->_hl;
  140. return true;
  141. }
  142. bool Resampler::process (void)
  143. {
  144. unsigned int hl, ph, np, dp, in, nr, nz, i, n, c;
  145. float *p1, *p2;
  146. if (!_table) return false;
  147. hl = _table->_hl;
  148. np = _table->_np;
  149. dp = _pstep;
  150. in = _index;
  151. nr = _nread;
  152. ph = _phase;
  153. nz = _nzero;
  154. n = (2 * hl - nr) * _nchan;
  155. p1 = _buff + in * _nchan;
  156. p2 = p1 + n;
  157. while (out_count)
  158. {
  159. if (nr)
  160. {
  161. if (inp_count == 0) break;
  162. if (inp_data)
  163. {
  164. for (c = 0; c < _nchan; c++) p2 [c] = inp_data [c];
  165. inp_data += _nchan;
  166. nz = 0;
  167. }
  168. else
  169. {
  170. for (c = 0; c < _nchan; c++) p2 [c] = 0;
  171. if (nz < 2 * hl) nz++;
  172. }
  173. nr--;
  174. p2 += _nchan;
  175. inp_count--;
  176. }
  177. else
  178. {
  179. if (out_data)
  180. {
  181. if (nz < 2 * hl)
  182. {
  183. float *c1 = _table->_ctab + hl * ph;
  184. float *c2 = _table->_ctab + hl * (np - ph);
  185. for (c = 0; c < _nchan; c++)
  186. {
  187. float *q1 = p1 + c;
  188. float *q2 = p2 + c;
  189. float s = 1e-20f;
  190. for (i = 0; i < hl; i++)
  191. {
  192. q2 -= _nchan;
  193. s += *q1 * c1 [i] + *q2 * c2 [i];
  194. q1 += _nchan;
  195. }
  196. *out_data++ = s - 1e-20f;
  197. }
  198. }
  199. else
  200. {
  201. for (c = 0; c < _nchan; c++) *out_data++ = 0;
  202. }
  203. }
  204. out_count--;
  205. ph += dp;
  206. if (ph >= np)
  207. {
  208. nr = ph / np;
  209. ph -= nr * np;
  210. in += nr;
  211. p1 += nr * _nchan;;
  212. if (in >= _inmax)
  213. {
  214. n = (2 * hl - nr) * _nchan;
  215. memcpy (_buff, p1, n * sizeof (float));
  216. in = 0;
  217. p1 = _buff;
  218. p2 = p1 + n;
  219. }
  220. }
  221. }
  222. }
  223. _index = in;
  224. _nread = nr;
  225. _phase = ph;
  226. _nzero = nz;
  227. return true;
  228. }