source: roaraudio/roarclients/roarfilt.c @ 682:6cf3ae19ffd3

Last change on this file since 682:6cf3ae19ffd3 was 682:6cf3ae19ffd3, checked in by phi, 16 years ago

added support for libroardsp filter chains

File size: 6.0 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#include <math.h>
28
29#define BUFSIZE 1024
30struct {
31 uint16_t a, b;
32 int16_t  old[ROAR_MAX_CHANNELS];
33} g_lowpass;
34
35void usage (void) {
36 printf("roarfilt [OPTIONS]...\n");
37
38 printf("\nOptions:\n\n");
39
40 printf("  --server SERVER    - Set server hostname\n"
41        "  --rate   RATE      - Set sample rate\n"
42        "  --bits   BITS      - Set bits per sample\n"
43        "  --chans  CHANNELS  - Set number of channels\n"
44        "  --help             - Show this help\n"
45        "\n"
46        "  --half             - half the volume\n"
47        "  --double           - double the volume\n"
48        "  --amp VAL          - Set amplification\n"
49        "  --mul VAL          - Set mul\n"
50        "  --div VAL          - Set div\n"
51        "  --lowpass freq     - lowpass filter\n"
52        "  --filter  name     - add filter name\n"
53        "  --ffreq   freq     - set filter freq\n"
54       );
55
56}
57
58void vol2 (void * data, int mul, int div, int len) {
59 int16_t * samples = (int16_t *) data;
60 int i;
61
62 len /= 2;
63
64 for (i = 0; i < len; i++)
65  samples[i] = ((int) samples[i] * mul) / div;
66}
67
68void vol1 (void * data, int mul, int div, int len) {
69 int8_t * samples = (int8_t *) data;
70 int i;
71
72 for (i = 0; i < len; i++)
73  samples[i] = ((int) samples[i] * mul) / div;
74}
75
76void logs2 (void * data, float scale, int len) {
77 int16_t * samples = (int16_t *) data;
78 int i;
79 float div = logf(scale);
80 float scalemul = scale - 1;
81 int neg;
82
83 len /= 2;
84
85 //printf("logs2(data=%p, scale=%f, len=%i): scalemul=%f, div=%f\n", data, scale, len, scalemul, div);
86
87 for (i = 0; i < len; i++) {
88  if ( (neg = (samples[i] < 0)) )
89   samples[i] = abs(samples[i]);
90
91
92  samples[i] = (neg ? 32768.0 : 32767.0)*logf(1 + (scalemul*(float)samples[i]/(neg ? 32768.0 : 32767.0))) / div;
93
94  if ( neg )
95   samples[i] *= -1;
96 }
97}
98
99void lowpass2 (void * data, int len, int channels) {
100 int16_t * samples = (int16_t *) data;
101 register int32_t s;
102 int i, c;
103
104 if ( channels > ROAR_MAX_CHANNELS )
105  return;
106
107 len /= 2 * channels;
108
109//  *      output[N] = input[N] * A + output[N-1] * B
110
111 for (i = 0; i < len; i++) {
112  for (c = 0; c < channels; c++) {
113   s = samples[i*channels + c] * g_lowpass.a + g_lowpass.old[c] * g_lowpass.b;
114
115   s /= 65536;
116
117   samples[i*channels + c] = s;
118   g_lowpass.old[       c] = s;
119  }
120 }
121}
122
123int main (int argc, char * argv[]) {
124 int    rate     = 44100;
125 int    bits     = 16;
126 int    channels = 2;
127 int    codec    = ROAR_CODEC_DEFAULT;
128 char * server   = NULL;
129 char * k;
130 int    fh;
131 int    i;
132 int    mul = 1, div = 1;
133 float  logscale = 0;
134 float  lp       = 0;
135 char buf[BUFSIZE];
136 struct roardsp_filterchain fc;
137 struct roardsp_filter      filter;
138 struct roar_stream         stream;
139
140 memset(&g_lowpass, 0, sizeof(g_lowpass));
141
142 roardsp_fchain_init(&fc);
143
144 for (i = 1; i < argc; i++) {
145  k = argv[i];
146
147  if ( strcmp(k, "--server") == 0 ) {
148   server = argv[++i];
149  } else if ( strcmp(k, "--rate") == 0 ) {
150   rate = atoi(argv[++i]);
151  } else if ( strcmp(k, "--bits") == 0 ) {
152   bits = atoi(argv[++i]);
153  } else if ( strcmp(k, "--channels") == 0 || strcmp(k, "--chans") == 0 ) {
154   channels = atoi(argv[++i]);
155  } else if ( strcmp(k, "--half") == 0 ) {
156   div *= 2;
157  } else if ( strcmp(k, "--double") == 0 ) {
158   mul *= 2;
159  } else if ( strcmp(k, "--amp") == 0 ) {
160   mul *= atoi(argv[++i]);
161  } else if ( strcmp(k, "--mul") == 0 ) {
162   mul  = atoi(argv[++i]);
163  } else if ( strcmp(k, "--div") == 0 ) {
164   div  = atoi(argv[++i]);
165  } else if ( strcmp(k, "--log") == 0 ) {
166   logscale = atof(argv[++i]);
167  } else if ( strcmp(k, "--lowpass") == 0 ) {
168   lp = exp(-2 * M_PI * atof(argv[++i]) / rate) * 65536;
169   g_lowpass.b = lp;
170   g_lowpass.a = 65536 - lp;
171//   printf("lowpass: A=%i, B=%i\n", g_lowpass.a, g_lowpass.b);
172  } else if ( strcmp(k, "--filter") == 0 ) {
173   stream.info.channels = channels;
174   stream.info.bits     = bits;
175   stream.info.rate     = rate;
176   roardsp_filter_init(&filter, &stream, roardsp_filter_str2id(argv[++i]));
177   roardsp_fchain_add(&fc, &filter);
178  } else if ( strcmp(k, "--ffreq") == 0 ) {
179   lp = atof(argv[++i]);
180   roardsp_filter_ctl(&filter, ROARDSP_FCTL_FREQ, &lp);
181  } else if ( strcmp(k, "--help") == 0 ) {
182   usage();
183   return 0;
184  } else {
185   fprintf(stderr, "Error: unknown argument: %s\n", k);
186   usage();
187   return 1;
188  }
189 }
190
191 if ( (fh = roar_simple_filter(rate, channels, bits, codec, server, "roarifilt")) == -1 ) {
192  fprintf(stderr, "Error: can not start playback\n");
193  return 1;
194 }
195
196 if ( mul == div && logscale == 0 && g_lowpass.a == 0 && roardsp_fchain_num(&fc) == 0 ) {
197  fprintf(stderr, "Error: filter is useless!\n");
198  return 0;
199 }
200
201 if ( bits == 16 ) {
202  while((i = read(fh, buf, BUFSIZE))) {
203   if ( mul != div )
204    vol2((void*)buf, mul, div, i);
205   if ( logscale )
206    logs2((void*)buf, logscale, i);
207   if ( g_lowpass.a )
208    lowpass2((void*)buf, i, channels);
209   roardsp_fchain_calc(&fc, (void*)buf, (8*i)/bits);
210   if (write(fh, buf, i) != i)
211    break;
212  }
213 } else if ( bits == 8 ) {
214  while((i = read(fh, buf, BUFSIZE))) {
215   vol1((void*)buf, mul, div, i);
216   if (write(fh, buf, i) != i)
217    break;
218  }
219 } else {
220  fprintf(stderr, "Error: %i bits per sample is not supported!\n", bits);
221  return 1;
222 }
223
224 roar_simple_close(fh);
225
226 roardsp_fchain_uninit(&fc);
227
228 return 0;
229}
230
231//ll
Note: See TracBrowser for help on using the repository browser.