1 // ----------------------------------------------------------------------------
2 //
3 //  Copyright (C) 2006-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/vresampler.h"
26 
27 using namespace ArdourZita;
28 
VResampler(void)29 VResampler::VResampler (void)
30 	: _table (0)
31   , _nchan (0)
32   , _buff  (0)
33   , _c1 (0)
34   , _c2 (0)
35 {
36 	reset ();
37 }
38 
~VResampler(void)39 VResampler::~VResampler (void)
40 {
41 	clear ();
42 }
43 
44 int
setup(double ratio,unsigned int nchan,unsigned int hlen)45 VResampler::setup (double       ratio,
46                    unsigned int nchan,
47                    unsigned int hlen)
48 {
49 	if ((hlen < 8) || (hlen > 96) || (16 * ratio < 1) || (ratio > 256)) return 1;
50 	return setup (ratio, nchan, hlen, 1.0 - 2.6 / hlen);
51 }
52 
53 int
setup(double ratio,unsigned int nchan,unsigned int hlen,double frel)54 VResampler::setup (double       ratio,
55                    unsigned int nchan,
56                    unsigned int hlen,
57                    double       frel)
58 {
59 	unsigned int       h, k, n;
60 	double             s;
61 	Resampler_table    *T = 0;
62 
63 	if (! nchan) return 1;
64 	n = NPHASE;
65 	s = n / ratio;
66 	h = hlen;
67 	k = 250;
68 	if (ratio < 1) {
69 		frel *= ratio;
70 		h = (unsigned int)(ceil (h / ratio));
71 		k = (unsigned int)(ceil (k / ratio));
72 	}
73 	T = Resampler_table::create (frel, h, n);
74 	clear ();
75 	if (T) {
76 		_table = T;
77 		_buff  = new float [nchan * (2 * h - 1 + k)];
78 		_c1 = new float [2 * h];
79 		_c2 = new float [2 * h];
80 		_nchan = nchan;
81 		_inmax = k;
82 		_ratio = ratio;
83 		_pstep = s;
84 		_qstep = s;
85 		_wstep = 1;
86 		return reset ();
87 	}
88 	else return 1;
89 }
90 
91 void
clear(void)92 VResampler::clear (void)
93 {
94 	Resampler_table::destroy (_table);
95 	delete[] _buff;
96 	delete[] _c1;
97 	delete[] _c2;
98 	_buff  = 0;
99 	_c1 = 0;
100 	_c2 = 0;
101 	_table = 0;
102 	_nchan = 0;
103 	_inmax = 0;
104 	_pstep = 0;
105 	_qstep = 0;
106 	_wstep = 1;
107 	reset ();
108 }
109 
110 void
set_phase(double p)111 VResampler::set_phase (double p)
112 {
113 	if (!_table) return;
114 	_phase = (p - floor (p)) * _table->_np;
115 }
116 
117 void
set_rrfilt(double t)118 VResampler::set_rrfilt (double t)
119 {
120 	if (!_table) return;
121 	_wstep =  (t < 1) ? 1 : 1 - exp (-1 / t);
122 }
123 
124 void
set_rratio(double r)125 VResampler::set_rratio (double r)
126 {
127 	if (!_table) return;
128 	if (r > 16.0) r = 16.0;
129 	if (r < 0.95) r = 0.95;
130 	_qstep = _table->_np / (_ratio * r);
131 }
132 
133 double
inpdist(void) const134 VResampler::inpdist (void) const
135 {
136 	if (!_table) return 0;
137 	return (int)(_table->_hl + 1 - _nread) - _phase / _table->_np;
138 }
139 
140 int
inpsize(void) const141 VResampler::inpsize (void) const
142 {
143 	if (!_table) return 0;
144 	return 2 * _table->_hl;
145 }
146 
147 int
reset(void)148 VResampler::reset (void)
149 {
150 	if (!_table) return 1;
151 
152 	inp_count = 0;
153 	out_count = 0;
154 	inp_data = 0;
155 	out_data = 0;
156 	_index = 0;
157 	_phase = 0;
158 	_nread = 2 * _table->_hl;
159 	_nzero = 0;
160 	return 0;
161 }
162 
163 int
process(void)164 VResampler::process (void)
165 {
166 	unsigned int   k, np, in, nr, n, c;
167 	int            i, hl, nz;
168 	double         ph, dp, dd;
169 	float          a, b, *p1, *p2, *q1, *q2;
170 
171 	if (!_table) return 1;
172 
173 	hl = _table->_hl;
174 	np = _table->_np;
175 	in = _index;
176 	nr = _nread;
177 	nz = _nzero;
178 	ph = _phase;
179 	dp = _pstep;
180 	n = (2 * hl - nr) * _nchan;
181 	p1 = _buff + in * _nchan;
182 	p2 = p1 + n;
183 
184 	while (out_count) {
185 		if (nr) {
186 			if (inp_count == 0) break;
187 			if (inp_data) {
188 				for (c = 0; c < _nchan; c++) p2 [c] = inp_data [c];
189 				inp_data += _nchan;
190 				nz = 0;
191 			} else {
192 				for (c = 0; c < _nchan; c++) p2 [c] = 0;
193 				if (nz < 2 * hl) nz++;
194 			}
195 			nr--;
196 			p2 += _nchan;
197 			inp_count--;
198 		} else {
199 			if (out_data) {
200 				if (nz < 2 * hl) {
201 					k = (unsigned int) ph;
202 					b = (float)(ph - k);
203 					a = 1.0f - b;
204 					q1 = _table->_ctab + hl * k;
205 					q2 = _table->_ctab + hl * (np - k);
206 					for (i = 0; i < hl; i++) {
207 						_c1 [i] = a * q1 [i] + b * q1 [i + hl];
208 						_c2 [i] = a * q2 [i] + b * q2 [i - hl];
209 					}
210 					for (c = 0; c < _nchan; c++) {
211 						q1 = p1 + c;
212 						q2 = p2 + c;
213 						a = 1e-25f;
214 						for (i = 0; i < hl; i++) {
215 							q2 -= _nchan;
216 							a += *q1 * _c1 [i] + *q2 * _c2 [i];
217 							q1 += _nchan;
218 						}
219 						*out_data++ = a - 1e-25f;
220 					}
221 				} else {
222 					for (c = 0; c < _nchan; c++) *out_data++ = 0;
223 				}
224 			}
225 			out_count--;
226 
227 			dd =  _qstep - dp;
228 			if (fabs (dd) < 1e-30) dp = _qstep;
229 			else dp += _wstep * dd;
230 			ph += dp;
231 			if (ph >= np) {
232 				nr = (unsigned int) floor( ph / np);
233 				ph -= nr * np;;
234 				in += nr;
235 				p1 += nr * _nchan;;
236 				if (in >= _inmax) {
237 					n = (2 * hl - nr) * _nchan;
238 					memcpy (_buff, p1, n * sizeof (float));
239 					in = 0;
240 					p1 = _buff;
241 					p2 = p1 + n;
242 				}
243 			}
244 		}
245 	}
246 	_index = in;
247 	_nread = nr;
248 	_phase = ph;
249 	_pstep = dp;
250 	_nzero = nz;
251 
252 	return 0;
253 }
254