source: roaraudio/roarclients/roarfilt.c @ 5533:42f48072307c

Last change on this file since 5533:42f48072307c was 5533:42f48072307c, checked in by phi, 12 years ago

Fixed usage of -R/-B/-C/-E as well as --aiprofile in roarclients (Closes: #176)

File size: 9.1 KB
RevLine 
[126]1//roarfilt.c:
2
[669]3/*
[5381]4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2012
[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
[5533]47 printf("  --server SERVER     - Set server hostname\n"
48        "  --rate  -R RATE     - Set sample rate\n"
49        "  --bits  -B BITS     - Set bits per sample\n"
50        "  --chans -C CHANNELS - Set number of channels\n"
51        "  --aiprofile PROFILE - Set audio profile\n"
52        "  --help              - Show this help\n"
[128]53        "\n"
[5533]54        "  --half              - half the volume\n"
55        "  --double            - double the volume\n"
56        "  --amp VAL           - Set amplification\n"
57        "  --mul VAL           - Set mul\n"
58        "  --div VAL           - Set div\n"
[1103]59#ifdef ROAR_HAVE_LIBM
[5533]60        "  --lowpass freq      - lowpass filter (obsolete)\n"
[1103]61#endif
[5533]62        "  --filter  name      - add filter name\n"
63        "  --ffreq   freq      - set filter freq\n"
64        "  --fmul    mult      - set filter multiplier\n"
65        "  --fdiv    div       - set filter divider\n"
66        "  --fn      N         - set filter N parameter\n"
67        "  --flimit  limit     - set filter limit parameter\n"
68        "  --fmode   mode      - set filter mode parameter\n"
69        "  --fq      Q         - set filter quality\n"
[126]70       );
71
72}
73
[5180]74#define _volX(bits,twobits,sf) \
75void vol##bits (void * data, int32_t mul, int32_t div, size_t len) { \
76 int##bits##_t * samples = (int##bits##_t *) data; \
77 size_t i; \
78\
79 len /= sf; \
80\
81 for (i = 0; i < len; i++) \
82  samples[i] = ((int##twobits##_t) samples[i] * mul) / div; \
[128]83}
84
[5180]85_volX( 8,16,1)
86_volX(16,32,2)
87_volX(32,64,4)
[130]88
[1103]89#ifdef ROAR_HAVE_LIBM
[140]90void logs2 (void * data, float scale, int len) {
[130]91 int16_t * samples = (int16_t *) data;
92 int i;
93 float div = logf(scale);
[140]94 float scalemul = scale - 1;
[130]95 int neg;
96
[128]97 len /= 2;
98
[140]99 //printf("logs2(data=%p, scale=%f, len=%i): scalemul=%f, div=%f\n", data, scale, len, scalemul, div);
[130]100
101 for (i = 0; i < len; i++) {
102  if ( (neg = (samples[i] < 0)) )
103   samples[i] = abs(samples[i]);
104
105
[140]106  samples[i] = (neg ? 32768.0 : 32767.0)*logf(1 + (scalemul*(float)samples[i]/(neg ? 32768.0 : 32767.0))) / div;
[130]107
108  if ( neg )
109   samples[i] *= -1;
110 }
[128]111}
112
[646]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}
[1103]136#endif
[646]137
[126]138int main (int argc, char * argv[]) {
[5180]139 struct roar_audio_info info;
140 char  * server   = NULL;
141 char  * k;
142 int     i;
143 int32_t mul = 1, div = 1;
144 int     filter_id;
[884]145 int32_t tmp;
[5180]146 float   logscale = 0;
147 float   lp       = 0;
148 char    buf[BUFFERSIZE];
[682]149 struct roardsp_filterchain fc;
[884]150 struct roardsp_filter      filter_real[8];
151 struct roardsp_filter    * filter = filter_real - 1;
[682]152 struct roar_stream         stream;
[2846]153 struct roar_vio_calls      svio;
[126]154
[5180]155 _LIBROAR_IGNORE_RET(roar_profile2info(&info, "default-server"));
156 info.codec = ROAR_CODEC_DEFAULT;
157
[1103]158#ifdef ROAR_HAVE_LIBM
[646]159 memset(&g_lowpass, 0, sizeof(g_lowpass));
[1103]160#endif
[646]161
[682]162 roardsp_fchain_init(&fc);
163
[126]164 for (i = 1; i < argc; i++) {
165  k = argv[i];
166
[1635]167  if ( strcmp(k, "--server") == 0 || strcmp(k, "-s") == 0 ) {
[126]168   server = argv[++i];
[1507]169  } else if ( strcmp(k, "--rate") == 0 || strcmp(k, "-R") == 0 || strcmp(k, "-r") == 0 ) {
[5180]170   info.rate = roar_str2rate(argv[++i]);
[1507]171  } else if ( strcmp(k, "--bits") == 0 || strcmp(k, "-B") == 0 ) {
[5180]172   info.bits = roar_str2bits(argv[++i]);
[1507]173  } else if ( strcmp(k, "--channels") == 0 || strcmp(k, "--chans") == 0 || strcmp(k, "-C") == 0 ) {
[5180]174   info.channels = roar_str2channels(argv[++i]);
[1507]175  } else if ( strcmp(k, "-b") == 0 ) {
[5180]176   info.bits = 8;
[1507]177  } else if ( strcmp(k, "-m") == 0 ) {
[5180]178   info.channels = 1;
[5533]179  } else if ( !strcmp(k, "--aiprofile") ) {
180   if ( roar_profile2info(&info, argv[++i]) == -1 ) {
181    fprintf(stderr, "Error: Can not load audio profile: %s: %s\n", argv[i], roar_error2str(roar_error));
182    return 1;
183   }
184   info.codec = ROAR_CODEC_DEFAULT;
[1507]185  } else if ( strcmp(k, "--half") == 0 || strcmp(k, "-half") == 0 ) {
[128]186   div *= 2;
[1507]187  } else if ( strcmp(k, "--double") == 0 || strcmp(k, "-double") == 0 ) {
[128]188   mul *= 2;
[130]189  } else if ( strcmp(k, "--amp") == 0 ) {
190   mul *= atoi(argv[++i]);
191  } else if ( strcmp(k, "--mul") == 0 ) {
192   mul  = atoi(argv[++i]);
193  } else if ( strcmp(k, "--div") == 0 ) {
194   div  = atoi(argv[++i]);
195  } else if ( strcmp(k, "--log") == 0 ) {
[5180]196   ROAR_WARN("The logscaler is obsolete and will be removed soon.");
[140]197   logscale = atof(argv[++i]);
[1103]198#ifdef ROAR_HAVE_LIBM
[646]199  } else if ( strcmp(k, "--lowpass") == 0 ) {
[5180]200   ROAR_WARN("The builtin lowpass is obsolete and will be removed soon. Use --filter lowpass.");
201   lp = exp(-2 * M_PI * atof(argv[++i]) / info.rate) * 65536;
[646]202   g_lowpass.b = lp;
203   g_lowpass.a = 65536 - lp;
[1103]204#endif
[648]205//   printf("lowpass: A=%i, B=%i\n", g_lowpass.a, g_lowpass.b);
[682]206  } else if ( strcmp(k, "--filter") == 0 ) {
[5180]207   stream.info = info;
[5172]208   filter_id = roardsp_filter_str2id(argv[++i]);
209   if ( filter_id == -1 ) {
210    ROAR_WARN("Can not add filter as filter ID is unknown: %s: %s", argv[i], roar_error2str(roar_error));
211   } else {
212    filter++;
213    if ( roardsp_filter_init(filter, &stream, filter_id) == -1 ) {
214     ROAR_WARN("Can not add filter: %s: %s", argv[i], roar_error2str(roar_error));
215     filter--;
216    } else {
217     roardsp_fchain_add(&fc, filter);
218    }
219   }
[682]220  } else if ( strcmp(k, "--ffreq") == 0 ) {
221   lp = atof(argv[++i]);
[884]222   roardsp_filter_ctl(filter, ROARDSP_FCTL_FREQ, &lp);
223  } else if ( strcmp(k, "--fmul") == 0 ) {
224   tmp = atoi(argv[++i]);
225   roardsp_filter_ctl(filter, ROARDSP_FCTL_MUL, &tmp);
226  } else if ( strcmp(k, "--fdiv") == 0 ) {
227   tmp = atoi(argv[++i]);
228   roardsp_filter_ctl(filter, ROARDSP_FCTL_DIV, &tmp);
[985]229  } else if ( strcmp(k, "--fn") == 0 ) {
230   tmp = atoi(argv[++i]);
231   roardsp_filter_ctl(filter, ROARDSP_FCTL_N, &tmp);
[1005]232  } else if ( strcmp(k, "--fq") == 0 ) {
233   tmp = atoi(argv[++i]);
234   roardsp_filter_ctl(filter, ROARDSP_FCTL_Q, &tmp);
[985]235  } else if ( strcmp(k, "--flimit") == 0 ) {
236   tmp = atoi(argv[++i]);
237   roardsp_filter_ctl(filter, ROARDSP_FCTL_LIMIT, &tmp);
[1005]238  } else if ( strcmp(k, "--fmode") == 0 ) {
239   tmp = atoi(argv[++i]);
240   roardsp_filter_ctl(filter, ROARDSP_FCTL_MODE, &tmp);
[1635]241  } else if ( strcmp(k, "--help") == 0 || strcmp(k, "-h") == 0 ) {
[126]242   usage();
243   return 0;
244  } else {
245   fprintf(stderr, "Error: unknown argument: %s\n", k);
246   usage();
247   return 1;
248  }
249 }
250
[5180]251 if ( roar_vio_simple_stream(&svio,
252                             info.rate, info.channels, info.bits, info.codec,
[5289]253                             server, ROAR_DIR_FILTER, "roarfilt", -1) == -1 ) {
[126]254  fprintf(stderr, "Error: can not start playback\n");
255  return 1;
256 }
257
[1103]258 if ( mul == div &&
259#ifdef ROAR_HAVE_LIBM
260      logscale == 0 && g_lowpass.a == 0 &&
261#endif
262      roardsp_fchain_num(&fc) == 0 ) {
[128]263  fprintf(stderr, "Error: filter is useless!\n");
264  return 0;
265 }
266
[5180]267 switch (info.bits) {
[5176]268  case 8:
[5178]269    while((i = roar_vio_read(&svio, buf, sizeof(buf)))) {
[5180]270     vol8((void*)buf, mul, div, i);
271     roardsp_fchain_calc(&fc, (void*)buf, (8*i)/info.bits);
[5176]272     if (roar_vio_write(&svio, buf, i) != i)
273      break;
274    }
275   break;
[2847]276  case 16:
[5178]277    while((i = roar_vio_read(&svio, buf, sizeof(buf)))) {
[2847]278     if ( mul != div )
[5180]279      vol16((void*)buf, mul, div, i);
[1103]280#ifdef ROAR_HAVE_LIBM
[2847]281     if ( logscale )
282      logs2((void*)buf, logscale, i);
283     if ( g_lowpass.a )
[5180]284      lowpass2((void*)buf, i, info.channels);
[1103]285#endif
[5180]286     roardsp_fchain_calc(&fc, (void*)buf, (8*i)/info.bits);
[2847]287     if (roar_vio_write(&svio, buf, i) != i)
288      break;
289    }
290   break;
[5176]291  case 32:
[5178]292    while((i = roar_vio_read(&svio, buf, sizeof(buf)))) {
[5180]293     vol32((void*)buf, mul, div, i);
294     roardsp_fchain_calc(&fc, (void*)buf, (8*i)/info.bits);
[2847]295     if (roar_vio_write(&svio, buf, i) != i)
296      break;
297    }
298   break;
299  default:
[5180]300    fprintf(stderr, "Error: %i bits per sample is not supported!\n", (int)info.bits);
[2847]301    return 1;
[128]302 }
[126]303
[2846]304 roar_vio_close(&svio);
[126]305
[682]306 roardsp_fchain_uninit(&fc);
307
[126]308 return 0;
309}
310
311//ll
Note: See TracBrowser for help on using the repository browser.