source: roaraudio/roarclients/roarfilt.c @ 1507:ff0c9920a154

Last change on this file since 1507:ff0c9920a154 was 1507:ff0c9920a154, checked in by phi, 15 years ago

fixed bug reported by Ionic to add short options as stated in the manpage and added esdfilt compatible options to roarfilt

File size: 7.7 KB
Line 
1//roarfilt.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008
5 *
6 *  This file is part of roarclients a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25#include <roaraudio.h>
26#include <libroardsp/libroardsp.h>
27
28#ifdef ROAR_HAVE_LIBM
29#include <math.h>
30#endif
31
32#define BUFSIZE 1024
33#ifdef ROAR_HAVE_LIBM
34struct {
35 uint16_t a, b;
36 int16_t  old[ROAR_MAX_CHANNELS];
37} g_lowpass;
38#endif
39
40void usage (void) {
41 printf("roarfilt [OPTIONS]...\n");
42
43 printf("\nOptions:\n\n");
44
45 printf("  --server SERVER    - Set server hostname\n"
46        "  --rate   RATE      - Set sample rate\n"
47        "  --bits   BITS      - Set bits per sample\n"
48        "  --chans  CHANNELS  - Set number of channels\n"
49        "  --help             - Show this help\n"
50        "\n"
51        "  --half             - half the volume\n"
52        "  --double           - double the volume\n"
53        "  --amp VAL          - Set amplification\n"
54        "  --mul VAL          - Set mul\n"
55        "  --div VAL          - Set div\n"
56#ifdef ROAR_HAVE_LIBM
57        "  --lowpass freq     - lowpass filter\n"
58#endif
59        "  --filter  name     - add filter name\n"
60        "  --ffreq   freq     - set filter freq\n"
61        "  --fmul    mult     - set filter multiplier\n"
62        "  --fdiv    div      - set filter divider\n"
63        "  --fn      N        - set filter N parameter\n"
64        "  --flimit  limit    - set filter limit parameter\n"
65        "  --fmode   mode     - set filter mode parameter\n"
66        "  --fq      Q        - set filter quality\n"
67       );
68
69}
70
71void vol2 (void * data, int mul, int div, int len) {
72 int16_t * samples = (int16_t *) data;
73 int i;
74
75 len /= 2;
76
77 for (i = 0; i < len; i++)
78  samples[i] = ((int) samples[i] * mul) / div;
79}
80
81void vol1 (void * data, int mul, int div, int len) {
82 int8_t * samples = (int8_t *) data;
83 int i;
84
85 for (i = 0; i < len; i++)
86  samples[i] = ((int) samples[i] * mul) / div;
87}
88
89#ifdef ROAR_HAVE_LIBM
90void logs2 (void * data, float scale, int len) {
91 int16_t * samples = (int16_t *) data;
92 int i;
93 float div = logf(scale);
94 float scalemul = scale - 1;
95 int neg;
96
97 len /= 2;
98
99 //printf("logs2(data=%p, scale=%f, len=%i): scalemul=%f, div=%f\n", data, scale, len, scalemul, div);
100
101 for (i = 0; i < len; i++) {
102  if ( (neg = (samples[i] < 0)) )
103   samples[i] = abs(samples[i]);
104
105
106  samples[i] = (neg ? 32768.0 : 32767.0)*logf(1 + (scalemul*(float)samples[i]/(neg ? 32768.0 : 32767.0))) / div;
107
108  if ( neg )
109   samples[i] *= -1;
110 }
111}
112
113void lowpass2 (void * data, int len, int channels) {
114 int16_t * samples = (int16_t *) data;
115 register int32_t s;
116 int i, c;
117
118 if ( channels > ROAR_MAX_CHANNELS )
119  return;
120
121 len /= 2 * channels;
122
123//  *      output[N] = input[N] * A + output[N-1] * B
124
125 for (i = 0; i < len; i++) {
126  for (c = 0; c < channels; c++) {
127   s = samples[i*channels + c] * g_lowpass.a + g_lowpass.old[c] * g_lowpass.b;
128
129   s /= 65536;
130
131   samples[i*channels + c] = s;
132   g_lowpass.old[       c] = s;
133  }
134 }
135}
136#endif
137
138int main (int argc, char * argv[]) {
139 int    rate     = 44100;
140 int    bits     = 16;
141 int    channels = 2;
142 int    codec    = ROAR_CODEC_DEFAULT;
143 char * server   = NULL;
144 char * k;
145 int    fh;
146 int    i;
147 int    mul = 1, div = 1;
148 int32_t tmp;
149 float  logscale = 0;
150 float  lp       = 0;
151 char buf[BUFSIZE];
152 struct roardsp_filterchain fc;
153 struct roardsp_filter      filter_real[8];
154 struct roardsp_filter    * filter = filter_real - 1;
155 struct roar_stream         stream;
156
157#ifdef ROAR_HAVE_LIBM
158 memset(&g_lowpass, 0, sizeof(g_lowpass));
159#endif
160
161 roardsp_fchain_init(&fc);
162
163 for (i = 1; i < argc; i++) {
164  k = argv[i];
165
166  if ( strcmp(k, "--server") == 0 ) {
167   server = argv[++i];
168  } else if ( strcmp(k, "--rate") == 0 || strcmp(k, "-R") == 0 || strcmp(k, "-r") == 0 ) {
169   rate = atoi(argv[++i]);
170  } else if ( strcmp(k, "--bits") == 0 || strcmp(k, "-B") == 0 ) {
171   bits = atoi(argv[++i]);
172  } else if ( strcmp(k, "--channels") == 0 || strcmp(k, "--chans") == 0 || strcmp(k, "-C") == 0 ) {
173   channels = atoi(argv[++i]);
174  } else if ( strcmp(k, "-b") == 0 ) {
175   bits = 8;
176  } else if ( strcmp(k, "-m") == 0 ) {
177   channels = 1;
178  } else if ( strcmp(k, "--half") == 0 || strcmp(k, "-half") == 0 ) {
179   div *= 2;
180  } else if ( strcmp(k, "--double") == 0 || strcmp(k, "-double") == 0 ) {
181   mul *= 2;
182  } else if ( strcmp(k, "--amp") == 0 ) {
183   mul *= atoi(argv[++i]);
184  } else if ( strcmp(k, "--mul") == 0 ) {
185   mul  = atoi(argv[++i]);
186  } else if ( strcmp(k, "--div") == 0 ) {
187   div  = atoi(argv[++i]);
188  } else if ( strcmp(k, "--log") == 0 ) {
189   logscale = atof(argv[++i]);
190#ifdef ROAR_HAVE_LIBM
191  } else if ( strcmp(k, "--lowpass") == 0 ) {
192   lp = exp(-2 * M_PI * atof(argv[++i]) / rate) * 65536;
193   g_lowpass.b = lp;
194   g_lowpass.a = 65536 - lp;
195#endif
196//   printf("lowpass: A=%i, B=%i\n", g_lowpass.a, g_lowpass.b);
197  } else if ( strcmp(k, "--filter") == 0 ) {
198   stream.info.channels = channels;
199   stream.info.bits     = bits;
200   stream.info.rate     = rate;
201   filter++;
202   roardsp_filter_init(filter, &stream, roardsp_filter_str2id(argv[++i]));
203   roardsp_fchain_add(&fc, filter);
204  } else if ( strcmp(k, "--ffreq") == 0 ) {
205   lp = atof(argv[++i]);
206   roardsp_filter_ctl(filter, ROARDSP_FCTL_FREQ, &lp);
207  } else if ( strcmp(k, "--fmul") == 0 ) {
208   tmp = atoi(argv[++i]);
209   roardsp_filter_ctl(filter, ROARDSP_FCTL_MUL, &tmp);
210  } else if ( strcmp(k, "--fdiv") == 0 ) {
211   tmp = atoi(argv[++i]);
212   roardsp_filter_ctl(filter, ROARDSP_FCTL_DIV, &tmp);
213  } else if ( strcmp(k, "--fn") == 0 ) {
214   tmp = atoi(argv[++i]);
215   roardsp_filter_ctl(filter, ROARDSP_FCTL_N, &tmp);
216  } else if ( strcmp(k, "--fq") == 0 ) {
217   tmp = atoi(argv[++i]);
218   roardsp_filter_ctl(filter, ROARDSP_FCTL_Q, &tmp);
219  } else if ( strcmp(k, "--flimit") == 0 ) {
220   tmp = atoi(argv[++i]);
221   roardsp_filter_ctl(filter, ROARDSP_FCTL_LIMIT, &tmp);
222  } else if ( strcmp(k, "--fmode") == 0 ) {
223   tmp = atoi(argv[++i]);
224   roardsp_filter_ctl(filter, ROARDSP_FCTL_MODE, &tmp);
225  } else if ( strcmp(k, "--help") == 0 ) {
226   usage();
227   return 0;
228  } else {
229   fprintf(stderr, "Error: unknown argument: %s\n", k);
230   usage();
231   return 1;
232  }
233 }
234
235 if ( (fh = roar_simple_filter(rate, channels, bits, codec, server, "roarifilt")) == -1 ) {
236  fprintf(stderr, "Error: can not start playback\n");
237  return 1;
238 }
239
240 if ( mul == div &&
241#ifdef ROAR_HAVE_LIBM
242      logscale == 0 && g_lowpass.a == 0 &&
243#endif
244      roardsp_fchain_num(&fc) == 0 ) {
245  fprintf(stderr, "Error: filter is useless!\n");
246  return 0;
247 }
248
249 if ( bits == 16 ) {
250  while((i = read(fh, buf, BUFSIZE))) {
251   if ( mul != div )
252    vol2((void*)buf, mul, div, i);
253#ifdef ROAR_HAVE_LIBM
254   if ( logscale )
255    logs2((void*)buf, logscale, i);
256   if ( g_lowpass.a )
257    lowpass2((void*)buf, i, channels);
258#endif
259   roardsp_fchain_calc(&fc, (void*)buf, (8*i)/bits);
260   if (write(fh, buf, i) != i)
261    break;
262  }
263 } else if ( bits == 8 ) {
264  while((i = read(fh, buf, BUFSIZE))) {
265   vol1((void*)buf, mul, div, i);
266   if (write(fh, buf, i) != i)
267    break;
268  }
269 } else {
270  fprintf(stderr, "Error: %i bits per sample is not supported!\n", bits);
271  return 1;
272 }
273
274 roar_simple_close(fh);
275
276 roardsp_fchain_uninit(&fc);
277
278 return 0;
279}
280
281//ll
Note: See TracBrowser for help on using the repository browser.