source: roaraudio/roarclients/roarfilt.c @ 5289:ddb3677af4d0

Last change on this file since 5289:ddb3677af4d0 was 5289:ddb3677af4d0, checked in by phi, 12 years ago

use support to set mixer ID up at least one API layer

File size: 8.8 KB
Line 
1//roarfilt.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2011
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, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include <roaraudio.h>
27#include <libroardsp/libroardsp.h>
28
29#ifdef ROAR_HAVE_LIBM
30#include <math.h>
31#endif
32
33#define BUFFERSIZE 1024
34
35#ifdef ROAR_HAVE_LIBM
36struct {
37 uint16_t a, b;
38 int16_t  old[ROAR_MAX_CHANNELS];
39} g_lowpass;
40#endif
41
42void usage (void) {
43 printf("roarfilt [OPTIONS]...\n");
44
45 printf("\nOptions:\n\n");
46
47 printf("  --server SERVER    - Set server hostname\n"
48        "  --rate   RATE      - Set sample rate\n"
49        "  --bits   BITS      - Set bits per sample\n"
50        "  --chans  CHANNELS  - Set number of channels\n"
51        "  --help             - Show this help\n"
52        "\n"
53        "  --half             - half the volume\n"
54        "  --double           - double the volume\n"
55        "  --amp VAL          - Set amplification\n"
56        "  --mul VAL          - Set mul\n"
57        "  --div VAL          - Set div\n"
58#ifdef ROAR_HAVE_LIBM
59        "  --lowpass freq     - lowpass filter (obsolete)\n"
60#endif
61        "  --filter  name     - add filter name\n"
62        "  --ffreq   freq     - set filter freq\n"
63        "  --fmul    mult     - set filter multiplier\n"
64        "  --fdiv    div      - set filter divider\n"
65        "  --fn      N        - set filter N parameter\n"
66        "  --flimit  limit    - set filter limit parameter\n"
67        "  --fmode   mode     - set filter mode parameter\n"
68        "  --fq      Q        - set filter quality\n"
69       );
70
71}
72
73#define _volX(bits,twobits,sf) \
74void vol##bits (void * data, int32_t mul, int32_t div, size_t len) { \
75 int##bits##_t * samples = (int##bits##_t *) data; \
76 size_t i; \
77\
78 len /= sf; \
79\
80 for (i = 0; i < len; i++) \
81  samples[i] = ((int##twobits##_t) samples[i] * mul) / div; \
82}
83
84_volX( 8,16,1)
85_volX(16,32,2)
86_volX(32,64,4)
87
88#ifdef ROAR_HAVE_LIBM
89void logs2 (void * data, float scale, int len) {
90 int16_t * samples = (int16_t *) data;
91 int i;
92 float div = logf(scale);
93 float scalemul = scale - 1;
94 int neg;
95
96 len /= 2;
97
98 //printf("logs2(data=%p, scale=%f, len=%i): scalemul=%f, div=%f\n", data, scale, len, scalemul, div);
99
100 for (i = 0; i < len; i++) {
101  if ( (neg = (samples[i] < 0)) )
102   samples[i] = abs(samples[i]);
103
104
105  samples[i] = (neg ? 32768.0 : 32767.0)*logf(1 + (scalemul*(float)samples[i]/(neg ? 32768.0 : 32767.0))) / div;
106
107  if ( neg )
108   samples[i] *= -1;
109 }
110}
111
112void lowpass2 (void * data, int len, int channels) {
113 int16_t * samples = (int16_t *) data;
114 register int32_t s;
115 int i, c;
116
117 if ( channels > ROAR_MAX_CHANNELS )
118  return;
119
120 len /= 2 * channels;
121
122//  *      output[N] = input[N] * A + output[N-1] * B
123
124 for (i = 0; i < len; i++) {
125  for (c = 0; c < channels; c++) {
126   s = samples[i*channels + c] * g_lowpass.a + g_lowpass.old[c] * g_lowpass.b;
127
128   s /= 65536;
129
130   samples[i*channels + c] = s;
131   g_lowpass.old[       c] = s;
132  }
133 }
134}
135#endif
136
137int main (int argc, char * argv[]) {
138 struct roar_audio_info info;
139 char  * server   = NULL;
140 char  * k;
141 int     i;
142 int32_t mul = 1, div = 1;
143 int     filter_id;
144 int32_t tmp;
145 float   logscale = 0;
146 float   lp       = 0;
147 char    buf[BUFFERSIZE];
148 struct roardsp_filterchain fc;
149 struct roardsp_filter      filter_real[8];
150 struct roardsp_filter    * filter = filter_real - 1;
151 struct roar_stream         stream;
152 struct roar_vio_calls      svio;
153
154 _LIBROAR_IGNORE_RET(roar_profile2info(&info, "default-server"));
155 info.codec = ROAR_CODEC_DEFAULT;
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 || strcmp(k, "-s") == 0 ) {
167   server = argv[++i];
168  } else if ( strcmp(k, "--rate") == 0 || strcmp(k, "-R") == 0 || strcmp(k, "-r") == 0 ) {
169   info.rate = roar_str2rate(argv[++i]);
170  } else if ( strcmp(k, "--bits") == 0 || strcmp(k, "-B") == 0 ) {
171   info.bits = roar_str2bits(argv[++i]);
172  } else if ( strcmp(k, "--channels") == 0 || strcmp(k, "--chans") == 0 || strcmp(k, "-C") == 0 ) {
173   info.channels = roar_str2channels(argv[++i]);
174  } else if ( strcmp(k, "-b") == 0 ) {
175   info.bits = 8;
176  } else if ( strcmp(k, "-m") == 0 ) {
177   info.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   ROAR_WARN("The logscaler is obsolete and will be removed soon.");
190   logscale = atof(argv[++i]);
191#ifdef ROAR_HAVE_LIBM
192  } else if ( strcmp(k, "--lowpass") == 0 ) {
193   ROAR_WARN("The builtin lowpass is obsolete and will be removed soon. Use --filter lowpass.");
194   lp = exp(-2 * M_PI * atof(argv[++i]) / info.rate) * 65536;
195   g_lowpass.b = lp;
196   g_lowpass.a = 65536 - lp;
197#endif
198//   printf("lowpass: A=%i, B=%i\n", g_lowpass.a, g_lowpass.b);
199  } else if ( strcmp(k, "--filter") == 0 ) {
200   stream.info = info;
201   filter_id = roardsp_filter_str2id(argv[++i]);
202   if ( filter_id == -1 ) {
203    ROAR_WARN("Can not add filter as filter ID is unknown: %s: %s", argv[i], roar_error2str(roar_error));
204   } else {
205    filter++;
206    if ( roardsp_filter_init(filter, &stream, filter_id) == -1 ) {
207     ROAR_WARN("Can not add filter: %s: %s", argv[i], roar_error2str(roar_error));
208     filter--;
209    } else {
210     roardsp_fchain_add(&fc, filter);
211    }
212   }
213  } else if ( strcmp(k, "--ffreq") == 0 ) {
214   lp = atof(argv[++i]);
215   roardsp_filter_ctl(filter, ROARDSP_FCTL_FREQ, &lp);
216  } else if ( strcmp(k, "--fmul") == 0 ) {
217   tmp = atoi(argv[++i]);
218   roardsp_filter_ctl(filter, ROARDSP_FCTL_MUL, &tmp);
219  } else if ( strcmp(k, "--fdiv") == 0 ) {
220   tmp = atoi(argv[++i]);
221   roardsp_filter_ctl(filter, ROARDSP_FCTL_DIV, &tmp);
222  } else if ( strcmp(k, "--fn") == 0 ) {
223   tmp = atoi(argv[++i]);
224   roardsp_filter_ctl(filter, ROARDSP_FCTL_N, &tmp);
225  } else if ( strcmp(k, "--fq") == 0 ) {
226   tmp = atoi(argv[++i]);
227   roardsp_filter_ctl(filter, ROARDSP_FCTL_Q, &tmp);
228  } else if ( strcmp(k, "--flimit") == 0 ) {
229   tmp = atoi(argv[++i]);
230   roardsp_filter_ctl(filter, ROARDSP_FCTL_LIMIT, &tmp);
231  } else if ( strcmp(k, "--fmode") == 0 ) {
232   tmp = atoi(argv[++i]);
233   roardsp_filter_ctl(filter, ROARDSP_FCTL_MODE, &tmp);
234  } else if ( strcmp(k, "--help") == 0 || strcmp(k, "-h") == 0 ) {
235   usage();
236   return 0;
237  } else {
238   fprintf(stderr, "Error: unknown argument: %s\n", k);
239   usage();
240   return 1;
241  }
242 }
243
244 if ( roar_vio_simple_stream(&svio,
245                             info.rate, info.channels, info.bits, info.codec,
246                             server, ROAR_DIR_FILTER, "roarfilt", -1) == -1 ) {
247  fprintf(stderr, "Error: can not start playback\n");
248  return 1;
249 }
250
251 if ( mul == div &&
252#ifdef ROAR_HAVE_LIBM
253      logscale == 0 && g_lowpass.a == 0 &&
254#endif
255      roardsp_fchain_num(&fc) == 0 ) {
256  fprintf(stderr, "Error: filter is useless!\n");
257  return 0;
258 }
259
260 switch (info.bits) {
261  case 8:
262    while((i = roar_vio_read(&svio, buf, sizeof(buf)))) {
263     vol8((void*)buf, mul, div, i);
264     roardsp_fchain_calc(&fc, (void*)buf, (8*i)/info.bits);
265     if (roar_vio_write(&svio, buf, i) != i)
266      break;
267    }
268   break;
269  case 16:
270    while((i = roar_vio_read(&svio, buf, sizeof(buf)))) {
271     if ( mul != div )
272      vol16((void*)buf, mul, div, i);
273#ifdef ROAR_HAVE_LIBM
274     if ( logscale )
275      logs2((void*)buf, logscale, i);
276     if ( g_lowpass.a )
277      lowpass2((void*)buf, i, info.channels);
278#endif
279     roardsp_fchain_calc(&fc, (void*)buf, (8*i)/info.bits);
280     if (roar_vio_write(&svio, buf, i) != i)
281      break;
282    }
283   break;
284  case 32:
285    while((i = roar_vio_read(&svio, buf, sizeof(buf)))) {
286     vol32((void*)buf, mul, div, i);
287     roardsp_fchain_calc(&fc, (void*)buf, (8*i)/info.bits);
288     if (roar_vio_write(&svio, buf, i) != i)
289      break;
290    }
291   break;
292  default:
293    fprintf(stderr, "Error: %i bits per sample is not supported!\n", (int)info.bits);
294    return 1;
295 }
296
297 roar_vio_close(&svio);
298
299 roardsp_fchain_uninit(&fc);
300
301 return 0;
302}
303
304//ll
Note: See TracBrowser for help on using the repository browser.