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