summaryrefslogtreecommitdiff
path: root/libs/resampler-table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/resampler-table.cc')
-rw-r--r--libs/resampler-table.cc161
1 files changed, 161 insertions, 0 deletions
diff --git a/libs/resampler-table.cc b/libs/resampler-table.cc
new file mode 100644
index 0000000..daaf9f3
--- /dev/null
+++ b/libs/resampler-table.cc
@@ -0,0 +1,161 @@
+// ----------------------------------------------------------------------------
+//
+// 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>
+
+
+int zita_resampler_major_version (void)
+{
+ return ZITA_RESAMPLER_MAJOR_VERSION;
+}
+
+
+int zita_resampler_minor_version (void)
+{
+ return ZITA_RESAMPLER_MINOR_VERSION;
+}
+
+
+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::_list = 0;
+Resampler_mutex Resampler_table::_mutex;
+
+
+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 ();
+}
+
+
+void Resampler_table::print_list (void)
+{
+ Resampler_table *P;
+
+ printf ("Resampler table\n----\n");
+ for (P = _list; P; P = P->_next)
+ {
+ printf ("refc = %3d fr = %10.6lf hl = %4d np = %4d\n", P->_refc, P->_fr, P->_hl, P->_np);
+ }
+ printf ("----\n\n");
+}
+