source: roaraudio/roarclients/roarfilt.c @ 5179:f9480d9e89e3

Last change on this file since 5179:f9480d9e89e3 was 5179:f9480d9e89e3, checked in by phi, 13 years ago

make use of roar_str2*() and some other minor changes

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