Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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