Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 375 lines (327 sloc) 9.681 kB
fd65cee @hzeller o add basic zita filter.
authored
1 // -----------------------------------------------------------------------------
2 //
3 // Copyright (C) 2006-2011 Fons Adriaensen <fons@linuxaudio.org>
4 //
75867a2 @hzeller o legalese: add COPYING, provide "Appropriate Legal Notices" and
authored
5 // Modifications to work with Folve
6 // Copyright (C) 2012 Henner Zeller <h.zeller@acm.org>
7 //
fd65cee @hzeller o add basic zita filter.
authored
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 //
22 // -----------------------------------------------------------------------------
23
24
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <math.h>
31 #include <libgen.h>
23b24f0 @hzeller o Write zita config problems to syslog.
authored
32 #include <syslog.h>
33
fd65cee @hzeller o add basic zita filter.
authored
34 #include "zita-audiofile.h"
35 #include "zita-config.h"
36
37 // zita-config
38 #define BSIZE 0x4000
39
40
2fee1d6 @hzeller o extract sound processor
authored
41 static int check_inout (ZitaConfig *cfg, int ip, int op)
fd65cee @hzeller o add basic zita filter.
authored
42 {
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
43 if (!cfg->size) return ERR_NOCONV;
44 if ((ip < 1) || (ip > cfg->ninp)) return ERR_IONUM;
45 if ((op < 1) || (op > cfg->nout)) return ERR_IONUM;
fd65cee @hzeller o add basic zita filter.
authored
46 return 0;
47 }
48
49
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
50 static int readfile (ZitaConfig *cfg,
51 const char *line, int lnum, const char *cdir)
fd65cee @hzeller o add basic zita filter.
authored
52 {
53 unsigned int ip1, op1, k;
54 float gain;
55 unsigned int delay;
56 unsigned int offset;
57 unsigned int length;
58 unsigned int ichan, nchan;
59 int n, ifram, nfram, err;
60 char file [1024];
61 char path [1024];
62 Audiofile audio;
63 float *buff, *p;
64
65 if (sscanf (line, "%u %u %f %u %u %u %u %n",
66 &ip1, &op1, &gain, &delay, &offset, &length, &ichan, &n) != 7) return ERR_PARAM;
67 n = sstring (line + n, file, 1024);
68 if (!n) return ERR_PARAM;
69
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
70 k = cfg->latency;
fd65cee @hzeller o add basic zita filter.
authored
71 if (k)
72 {
73 if (delay >= k)
74 {
75 delay -= k;
76 }
77 else
78 {
79 k -= delay;
80 delay = 0;
81 offset += k;
23b24f0 @hzeller o Write zita config problems to syslog.
authored
82 syslog(LOG_ERR, "%s:%d: First %d frames removed by latency compensation.\n", cfg->config_file, lnum, k);
fd65cee @hzeller o add basic zita filter.
authored
83 }
84 }
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
85 err = check_inout (cfg, ip1, op1);
fd65cee @hzeller o add basic zita filter.
authored
86 if (err) return err;
87
88 if (*file == '/') strcpy (path, file);
89 else
90 {
91 strcpy (path, cdir);
92 strcat (path, "/");
93 strcat (path, file);
94 }
95
96 if (audio.open_read (path))
97 {
23b24f0 @hzeller o Write zita config problems to syslog.
authored
98 syslog(LOG_ERR, "%s:%d: Unable to open '%s' >%s<.\n", cfg->config_file,
99 lnum, path, cdir);
fd65cee @hzeller o add basic zita filter.
authored
100 return ERR_OTHER;
101 }
102
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
103 if (audio.rate () != (int) cfg->fsamp)
fd65cee @hzeller o add basic zita filter.
authored
104 {
23b24f0 @hzeller o Write zita config problems to syslog.
authored
105 syslog(LOG_ERR, "%s:%d: Sample rate (%d) of '%s' does not match.\n",
106 cfg->config_file, lnum, audio.rate (), path);
fd65cee @hzeller o add basic zita filter.
authored
107 }
108
109 nchan = audio.chan ();
110 nfram = audio.size ();
111 if ((ichan < 1) || (ichan > nchan))
112 {
23b24f0 @hzeller o Write zita config problems to syslog.
authored
113 syslog(LOG_ERR, "%s:%d: Channel not available.\n",
114 cfg->config_file, lnum);
fd65cee @hzeller o add basic zita filter.
authored
115 audio.close ();
116 return ERR_OTHER;
117 }
118 if (offset && audio.seek (offset))
119 {
23b24f0 @hzeller o Write zita config problems to syslog.
authored
120 syslog(LOG_ERR, "%s:%d: Can't seek to offset.\n",
121 cfg->config_file, lnum);
fd65cee @hzeller o add basic zita filter.
authored
122 audio.close ();
123 return ERR_OTHER;
124 }
125 if (! length) length = nfram - offset;
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
126 if (length > cfg->size - delay)
fd65cee @hzeller o add basic zita filter.
authored
127 {
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
128 length = cfg->size - delay;
23b24f0 @hzeller o Write zita config problems to syslog.
authored
129 syslog(LOG_ERR, "%s:%d: Data truncated.\n", cfg->config_file, lnum);
fd65cee @hzeller o add basic zita filter.
authored
130 }
131
132 try
133 {
134 buff = new float [BSIZE * nchan];
135 }
136 catch (...)
137 {
138 audio.close ();
139 return ERR_ALLOC;
140 }
141
142 while (length)
143 {
144 nfram = (length > BSIZE) ? BSIZE : length;
145 nfram = audio.read (buff, nfram);
146 if (nfram < 0)
147 {
23b24f0 @hzeller o Write zita config problems to syslog.
authored
148 syslog(LOG_ERR, "%s:%d: Error reading file.\n",
149 cfg->config_file, lnum);
fd65cee @hzeller o add basic zita filter.
authored
150 audio.close ();
151 delete[] buff;
152 return ERR_OTHER;
153 }
154 if (nfram)
155 {
156 p = buff + ichan - 1;
157 for (ifram = 0; ifram < nfram; ifram++) p [ifram * nchan] *= gain;
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
158 if (cfg->convproc->impdata_create (ip1 - 1, op1 - 1, nchan, p, delay, delay + nfram))
fd65cee @hzeller o add basic zita filter.
authored
159 {
160 audio.close ();
161 delete[] buff;
162 return ERR_ALLOC;
163 }
164 delay += nfram;
165 length -= nfram;
166 }
167 }
168
169 audio.close ();
170 delete[] buff;
171 return 0;
172 }
173
174
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
175 static int impdirac (ZitaConfig *cfg, const char *line, int lnum)
fd65cee @hzeller o add basic zita filter.
authored
176 {
2fee1d6 @hzeller o extract sound processor
authored
177 int ip1, op1, k;
178 int delay;
fd65cee @hzeller o add basic zita filter.
authored
179 float gain;
180 int stat;
181
182 if (sscanf (line, "%u %u %f %u", &ip1, &op1, &gain, &delay) != 4) return ERR_PARAM;
183
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
184 stat = check_inout (cfg, ip1, op1);
fd65cee @hzeller o add basic zita filter.
authored
185 if (stat) return stat;
186
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
187 k = cfg->latency;
fd65cee @hzeller o add basic zita filter.
authored
188 if (delay < k)
189 {
23b24f0 @hzeller o Write zita config problems to syslog.
authored
190 syslog(LOG_ERR, "%s:%d: Dirac pulse removed: delay < latency.\n",
191 cfg->config_file, lnum);
fd65cee @hzeller o add basic zita filter.
authored
192 return 0;
193 }
194 delay -= k;
195
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
196 if (delay < cfg->size)
fd65cee @hzeller o add basic zita filter.
authored
197 {
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
198 if (cfg->convproc->impdata_create (ip1 - 1, op1 - 1, 1, &gain, delay, delay + 1))
fd65cee @hzeller o add basic zita filter.
authored
199 {
200 return ERR_ALLOC;
201 }
202 }
203 return 0;
204 }
205
206
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
207 static int imphilbert (ZitaConfig *cfg, const char *line, int lnum)
fd65cee @hzeller o add basic zita filter.
authored
208 {
209 unsigned int ip1, op1;
210 unsigned int delay;
211 unsigned int length;
212 unsigned int i, h, k;
213 float gain, v, w;
214 float *hdata;
215 int stat;
216
217 if (sscanf (line, "%u %u %f %u %u", &ip1, &op1, &gain, &delay, &length) != 5) return ERR_PARAM;
218
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
219 stat = check_inout (cfg, ip1, op1);
fd65cee @hzeller o add basic zita filter.
authored
220 if (stat) return stat;
221
222 if ((length < 64) || (length > 65536))
223 {
224 return ERR_PARAM;
225 }
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
226 k = cfg->latency;
fd65cee @hzeller o add basic zita filter.
authored
227 if (delay < k + length / 2)
228 {
23b24f0 @hzeller o Write zita config problems to syslog.
authored
229 syslog(LOG_ERR, "%s:%d: Hilbert impulse removed: delay < latency + lenght / 2.\n", cfg->config_file, lnum);
fd65cee @hzeller o add basic zita filter.
authored
230 return 0;
231 }
232 delay -= k + length / 2;
233 hdata = new float [length];
234 memset (hdata, 0, length * sizeof (float));
235
236 gain *= 2 / M_PI;
237 h = length / 2;
238 for (i = 1; i < h; i += 2)
239 {
240 v = gain / i;
241 w = 0.43f + 0.57f * cosf (i * M_PI / h);
242 v *= w;
243 hdata [h + i] = -v;
244 hdata [h - i] = v;
245 }
246
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
247 if (cfg->convproc->impdata_create (ip1 - 1, op1 - 1, 1, hdata, delay, delay + length))
fd65cee @hzeller o add basic zita filter.
authored
248 {
249 return ERR_ALLOC;
250 }
251
252 delete[] hdata;
253 return 0;
254 }
255
256
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
257 static int impcopy (ZitaConfig *cfg, const char *line, int lnum)
fd65cee @hzeller o add basic zita filter.
authored
258 {
259 unsigned int ip1, op1, ip2, op2;
260 int stat;
261
262 if (sscanf (line, "%u %u %u %u", &ip1, &op1, &ip2, &op2) != 4) return ERR_PARAM;
263
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
264 stat = check_inout (cfg, ip1, op1) | check_inout (cfg, ip2, op2);
fd65cee @hzeller o add basic zita filter.
authored
265 if (stat) return stat;
266
267 if ((ip1 != ip2) || (op1 != op2))
268 {
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
269 if (cfg->convproc->impdata_copy (ip2 - 1, op2 - 1, ip1 - 1, op1 - 1)) return ERR_ALLOC;
fd65cee @hzeller o add basic zita filter.
authored
270 }
271 else return ERR_PARAM;
272
273 return 0;
274 }
275
276
562b493 @hzeller o Print out config file name while spotting a problem
authored
277 int config (ZitaConfig *cfg, const char *config_file)
fd65cee @hzeller o add basic zita filter.
authored
278 {
279 FILE *F;
280 int stat, lnum;
281 char line [1024];
282 char cdir [1024];
283 char *p, *q;
284
562b493 @hzeller o Print out config file name while spotting a problem
authored
285 if (! (F = fopen (config_file, "r")))
fd65cee @hzeller o add basic zita filter.
authored
286 {
23b24f0 @hzeller o Write zita config problems to syslog.
authored
287 syslog(LOG_ERR, "Can't open '%s' for reading\n", config_file);
fd65cee @hzeller o add basic zita filter.
authored
288 return -1;
289 }
7e756eb @hzeller o Fix problem with re-initializing the convproc. Turns out that the c…
authored
290
562b493 @hzeller o Print out config file name while spotting a problem
authored
291 // dirname() modifies the input
292 char *config_name_copy = strdup(config_file);
7e756eb @hzeller o Fix problem with re-initializing the convproc. Turns out that the c…
authored
293 strcpy (cdir, dirname(config_name_copy));
294 free(config_name_copy);
fd65cee @hzeller o add basic zita filter.
authored
295
562b493 @hzeller o Print out config file name while spotting a problem
authored
296 // Remember this for error output.
297 cfg->config_file = config_file;
fd65cee @hzeller o add basic zita filter.
authored
298 stat = 0;
299 lnum = 0;
300
301 while (! stat && fgets (line, 1024, F))
302 {
303 lnum++;
304 p = line;
305 if (*p != '/')
306 {
307 while (isspace (*p)) p++;
308 if ((*p > ' ') && (*p != '#'))
309 {
310 stat = ERR_SYNTAX;
311 break;
312 }
313 continue;
314 }
315 for (q = p; (*q >= ' ') && !isspace (*q); q++);
316 for (*q++ = 0; (*q >= ' ') && isspace (*q); q++);
317
318 if (! strcmp (p, "/cd"))
319 {
23b24f0 @hzeller o Write zita config problems to syslog.
authored
320 char tmp[1024];
321 if (sstring (q, tmp, 1024) == 0) stat = ERR_PARAM;
322 if (tmp[0] == '/') {
323 strcpy(cdir, tmp);
324 } else {
325 strcat(cdir, "/");
326 strcat(cdir, tmp);
327 }
fd65cee @hzeller o add basic zita filter.
authored
328 }
0edb358 @hzeller o attempt to remove global references in the zita config.
authored
329 else if (! strcmp (p, "/convolver/new")) stat = convnew (cfg, q, lnum);
330 else if (! strcmp (p, "/impulse/read")) stat = readfile (cfg, q, lnum, cdir);
331 else if (! strcmp (p, "/impulse/dirac")) stat = impdirac (cfg, q, lnum);
332 else if (! strcmp (p, "/impulse/hilbert")) stat = imphilbert (cfg, q, lnum);
333 else if (! strcmp (p, "/impulse/copy")) stat = impcopy (cfg, q, lnum);
334 else if (! strcmp (p, "/input/name")) stat = inpname (cfg, q);
335 else if (! strcmp (p, "/output/name")) stat = outname (cfg, q);
fd65cee @hzeller o add basic zita filter.
authored
336 else stat = ERR_COMMAND;
337 }
338
339 fclose (F);
340 if (stat == ERR_OTHER) stat = 0;
341 if (stat)
342 {
23b24f0 @hzeller o Write zita config problems to syslog.
authored
343 syslog(LOG_ERR, "%s:%d: ", config_file, lnum);
fd65cee @hzeller o add basic zita filter.
authored
344 switch (stat)
345 {
346 case ERR_SYNTAX:
23b24f0 @hzeller o Write zita config problems to syslog.
authored
347 syslog(LOG_ERR, "Syntax error.\n");
562b493 @hzeller o Print out config file name while spotting a problem
authored
348 break;
fd65cee @hzeller o add basic zita filter.
authored
349 case ERR_PARAM:
23b24f0 @hzeller o Write zita config problems to syslog.
authored
350 syslog(LOG_ERR, "Bad or missing parameters.\n");
fd65cee @hzeller o add basic zita filter.
authored
351 break;
352 case ERR_ALLOC:
23b24f0 @hzeller o Write zita config problems to syslog.
authored
353 syslog(LOG_ERR, "Out of memory.\n");
fd65cee @hzeller o add basic zita filter.
authored
354 break;
355 case ERR_CANTCD:
23b24f0 @hzeller o Write zita config problems to syslog.
authored
356 syslog(LOG_ERR, "Can't change directory to '%s'.\n", cdir);
fd65cee @hzeller o add basic zita filter.
authored
357 break;
358 case ERR_COMMAND:
23b24f0 @hzeller o Write zita config problems to syslog.
authored
359 syslog(LOG_ERR, "Unknown command.\n");
fd65cee @hzeller o add basic zita filter.
authored
360 break;
361 case ERR_NOCONV:
23b24f0 @hzeller o Write zita config problems to syslog.
authored
362 syslog(LOG_ERR, "No convolver yet defined.\n");
fd65cee @hzeller o add basic zita filter.
authored
363 break;
364 case ERR_IONUM:
23b24f0 @hzeller o Write zita config problems to syslog.
authored
365 syslog(LOG_ERR, "Bad input or output number.\n");
fd65cee @hzeller o add basic zita filter.
authored
366 break;
367 default:
23b24f0 @hzeller o Write zita config problems to syslog.
authored
368 syslog(LOG_ERR, "Unknown error.\n");
fd65cee @hzeller o add basic zita filter.
authored
369 }
370 }
371
372 return stat;
373 }
374
Something went wrong with that request. Please try again.