summaryrefslogtreecommitdiff
path: root/libs/zita-resampler/resampler-table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/zita-resampler/resampler-table.cc')
-rw-r--r--libs/zita-resampler/resampler-table.cc123
1 files changed, 123 insertions, 0 deletions
diff --git a/libs/zita-resampler/resampler-table.cc b/libs/zita-resampler/resampler-table.cc
new file mode 100644
index 0000000000..ca4cdb69b8
--- /dev/null
+++ b/libs/zita-resampler/resampler-table.cc
@@ -0,0 +1,123 @@
+// ----------------------------------------------------------------------------
+//
+// Copyright (C) 2006-2012 Fons Adriaensen <fons@linuxaudio.org>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// ----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "zita-resampler/resampler-table.h"
+
+using namespace ArdourZita;
+
+Resampler_table *Resampler_table::_list = 0;
+Resampler_mutex Resampler_table::_mutex;
+
+static double sinc (double x)
+{
+ x = fabs (x);
+ if (x < 1e-6) return 1.0;
+ x *= M_PI;
+ return sin (x) / x;
+}
+
+static double wind (double x)
+{
+ x = fabs (x);
+ if (x >= 1.0) return 0.0f;
+ x *= M_PI;
+ return 0.384 + 0.500 * cos (x) + 0.116 * cos (2 * x);
+}
+
+Resampler_table::Resampler_table (double fr, unsigned int hl, unsigned int np)
+ : _next (0)
+ , _refc (0)
+ , _fr (fr)
+ , _hl (hl)
+ , _np (np)
+{
+ unsigned int i, j;
+ double t;
+ float *p;
+
+ _ctab = new float [hl * (np + 1)];
+ p = _ctab;
+ for (j = 0; j <= np; j++) {
+ t = (double) j / (double) np;
+ for (i = 0; i < hl; i++) {
+ p [hl - i - 1] = (float)(fr * sinc (t * fr) * wind (t / hl));
+ t += 1;
+ }
+ p += hl;
+ }
+}
+
+Resampler_table::~Resampler_table (void)
+{
+ delete[] _ctab;
+}
+
+Resampler_table*
+Resampler_table::create (double fr, unsigned int hl, unsigned int np)
+{
+ Resampler_table *P;
+
+ _mutex.lock ();
+ P = _list;
+ while (P) {
+ if ((fr >= P->_fr * 0.999) && (fr <= P->_fr * 1.001) && (hl == P->_hl) && (np == P->_np)) {
+ P->_refc++;
+ _mutex.unlock ();
+ return P;
+ }
+ P = P->_next;
+ }
+ P = new Resampler_table (fr, hl, np);
+ P->_refc = 1;
+ P->_next = _list;
+ _list = P;
+ _mutex.unlock ();
+ return P;
+}
+
+void
+Resampler_table::destroy (Resampler_table *T)
+{
+ Resampler_table *P, *Q;
+
+ _mutex.lock ();
+ if (T) {
+ T->_refc--;
+ if (T->_refc == 0) {
+ P = _list;
+ Q = 0;
+ while (P) {
+ if (P == T) {
+ if (Q) Q->_next = T->_next;
+ else _list = T->_next;
+ break;
+ }
+ Q = P;
+ P = P->_next;
+ }
+ delete T;
+ }
+ }
+ _mutex.unlock ();
+}