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.

193 lines
3.5KB

  1. // ----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 2013 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 "cresampler.h"
  24. CResampler::CResampler (void) :
  25. _nchan (0),
  26. _buff (0)
  27. {
  28. reset ();
  29. }
  30. CResampler::~CResampler (void)
  31. {
  32. clear ();
  33. }
  34. int CResampler::setup (double ratio,
  35. unsigned int nchan)
  36. {
  37. if (! nchan) return 1;
  38. clear ();
  39. _inmax = 50;
  40. _buff = new float [nchan * (3 + _inmax)];
  41. _nchan = nchan;
  42. _pstep = 1 / ratio;
  43. return reset ();
  44. }
  45. void CResampler::clear (void)
  46. {
  47. delete[] _buff;
  48. _buff = 0;
  49. _nchan = 0;
  50. _inmax = 0;
  51. _pstep = 0;
  52. reset ();
  53. }
  54. void CResampler::set_phase (double p)
  55. {
  56. _phase = p - floor (p);
  57. }
  58. void CResampler::set_ratio (double r)
  59. {
  60. _pstep = 1.0 / r;
  61. }
  62. double CResampler::inpdist (void) const
  63. {
  64. return (int)(3 - _nread) - _phase;
  65. }
  66. int CResampler::inpsize (void) const
  67. {
  68. return 4;
  69. }
  70. int CResampler::reset (void)
  71. {
  72. inp_count = 0;
  73. out_count = 0;
  74. inp_data = 0;
  75. out_data = 0;
  76. _index = 0;
  77. _phase = 0;
  78. _nread = 4;
  79. _nzero = 0;
  80. return 0;
  81. }
  82. int CResampler::process (void)
  83. {
  84. unsigned int in, nr, n, c;
  85. int nz;
  86. double ph;
  87. float *pb, a, b, d, m0, m1, m2, m3;
  88. in = _index;
  89. nr = _nread;
  90. nz = _nzero;
  91. ph = _phase;
  92. pb = _buff + in * _nchan;
  93. while (out_count)
  94. {
  95. if (nr)
  96. {
  97. if (inp_count == 0) break;
  98. n = (4 - nr) * _nchan;
  99. if (inp_data)
  100. {
  101. for (c = 0; c < _nchan; c++) pb [n + c] = inp_data [c];
  102. inp_data += _nchan;
  103. nz = 0;
  104. }
  105. else
  106. {
  107. for (c = 0; c < _nchan; c++) pb [n + c] = 0;
  108. if (nz < 4) nz++;
  109. }
  110. nr--;
  111. inp_count--;
  112. }
  113. else
  114. {
  115. n = _nchan;
  116. if (out_data)
  117. {
  118. if (nz < 4)
  119. {
  120. a = ph;
  121. b = 1 - a;
  122. d = a * b / 2;
  123. m0 = -d * b;
  124. m1 = b + (3 * b - 1) * d;
  125. m2 = a + (3 * a - 1) * d;
  126. m3 = -d * a;
  127. for (c = 0; c < n; c++)
  128. {
  129. *out_data++ = m0 * pb [0]
  130. + m1 * pb [n]
  131. + m2 * pb [2 * n]
  132. + m3 * pb [3 * n];
  133. pb++;
  134. }
  135. pb -= n;
  136. }
  137. else
  138. {
  139. for (c = 0; c < n; c++) *out_data++ = 0;
  140. }
  141. }
  142. out_count--;
  143. ph += _pstep;
  144. if (ph >= 1.0)
  145. {
  146. nr = (unsigned int) floor (ph);
  147. ph -= nr;
  148. in += nr;
  149. pb += nr * _nchan;
  150. if (in >= _inmax)
  151. {
  152. memcpy (_buff, pb, (4 - nr) * _nchan * sizeof (float));
  153. in = 0;
  154. pb = _buff;
  155. }
  156. }
  157. }
  158. }
  159. _index = in;
  160. _nread = nr;
  161. _nzero = nz;
  162. _phase = ph;
  163. return 0;
  164. }