source: roaraudio/roarclients/roarvumeter.c @ 5961:06e7fd9e4c25

Last change on this file since 5961:06e7fd9e4c25 was 5961:06e7fd9e4c25, checked in by phi, 10 years ago

Updates of copyright and license headers

File size: 7.9 KB
RevLine 
[2292]1//roarvumeter.c:
[224]2
[669]3/*
[5961]4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2014
[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
[224]26#include <roaraudio.h>
[3024]27#include <libroardsp/libroardsp.h>
[1103]28
29#ifdef ROAR_HAVE_LIBM
30
[224]31#include <math.h>
32
33#define BUFSIZE 1024
34
[3091]35#define LOWPASS_ORDER  6
36
[3027]37#define MODE_NONE  0x00
[3025]38#define MODE_PC    0x01
39#define MODE_DB    0x02
40#define MODE_BEAT  0x04
[1633]41
[224]42void usage (void) {
43 printf("roarvumeter [OPTIONS]...\n");
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 CHANS    - Set number of channels\n"
51        "  --aiprofile PROFILE - Set audio profile\n"
52        "  --samples SAMPLES   - Set number of input samples per block\n"
53        "  --pc                - Use percent scale\n"
54        "  --db                - Use dB scale\n"
55        "  --beat              - Enable beat detection\n"
56        "  --lowpass FREQ      - Use lowpass to filter input (-%idB/dec)\n"
57        "  --help              - Show this help\n",
[3091]58        LOWPASS_ORDER * 20
[224]59       );
60
61}
62
[3024]63int vumeter16bit2ch (struct roar_vio_calls * vio, int samples, int16_t * buf, int mode, struct roardsp_filterchain * fc) {
[3025]64 struct roar_stream    beat_stream[1];
65 struct roardsp_filter beat_lp[1];
66 float                 beat_lpfreq = 1;
[224]67 int i;
68 int samples_half = samples/2;
[2917]69 int64_t suml, sumr;
70 double  rmsl, rmsr;
[3025]71 int run_filters    = roardsp_fchain_num(fc);
72 int beat_detection = mode & MODE_BEAT;
73 char * beat[2]     = {"     ", "Beat!"};
74 char * dbeat       = beat[0];
[3641]75 int     have_beat  = 0;
[3025]76 int16_t beat_val, beat_old;
77
78 if ( beat_detection ) {
79  mode -= MODE_BEAT;
80
81  roar_stream_new(beat_stream, 10, 1, 16, ROAR_CODEC_PCM);
82  roardsp_filter_init(beat_lp, beat_stream, ROARDSP_FILTER_LOWP);
83  roardsp_filter_ctl(beat_lp, ROARDSP_FCTL_FREQ, &beat_lpfreq);
84 }
[224]85
86 printf("\e[s");
87 fflush(stdout);
88
[2918]89 while (roar_vio_read(vio, buf, samples * 2) > 0) {
[224]90  suml = sumr = 0;
91
[3024]92  if ( run_filters ) {
93   roardsp_fchain_calc(fc, buf, samples * 2);
94  }
95
[224]96  for (i = 0; i < samples; i += 2) {
[2917]97   suml += (int64_t) buf[i  ] * (int64_t) buf[i  ];
98   sumr += (int64_t) buf[i+1] * (int64_t) buf[i+1];
[224]99  }
100
[2917]101  rmsl = sqrt((double)suml/(double)samples_half);
102  rmsr = sqrt((double)sumr/(double)samples_half);
[224]103
[3025]104  if ( beat_detection ) {
105   beat_old = beat_val = (rmsl + rmsr) / 2;
106   roardsp_filter_calc(beat_lp, &beat_val, 2);
[3028]107   if ( (float)beat_old > (float)beat_val*1.1f ) {
[3025]108    dbeat = beat[1];
[3027]109    have_beat = 1;
[3025]110   } else {
111    dbeat = beat[0];
[3027]112    have_beat = 0;
[3025]113   }
114  }
115
[1633]116  switch (mode) {
[3027]117   case MODE_NONE: // beat only
118     if ( have_beat )
119      printf("%s\n", dbeat);
120    break;
[1633]121   case MODE_PC:
[3025]122     printf("L: %3i%% R: %3i%% %s          \e[u", (int)(rmsl/327.68), (int)(rmsr/327.68), dbeat);
[1633]123    break;
124   case MODE_DB:
[3025]125     printf("L: %6.2fdB R: %6.2fdB %s          \e[u", 20*log10(rmsl/32768.), 20*log10(rmsr/32768.), dbeat);
[1633]126    break;
127  }
128
[224]129  fflush(stdout);
130 }
[3025]131
[3746]132 if ( beat_detection ) {
133  roardsp_filter_uninit(beat_lp);
134 }
[3025]135
[224]136 return 0;
137}
138
[3024]139int vumeter (struct roar_vio_calls * vio, int samples, int bits, int channels, int mode, struct roardsp_filterchain * fc) {
[5179]140 void * buf = roar_mm_malloc((samples*bits*channels)/8);
[224]141
[5179]142 if ( buf == NULL )
[224]143  return -1;
144
145 if ( bits == 16 ) {
146  if ( channels == 2 ) {
[3024]147   vumeter16bit2ch(vio, samples, (int16_t *) buf, mode, fc);
[5179]148   roar_mm_free(buf);
[224]149   return 0;
150  } else {
[5179]151   roar_mm_free(buf);
[224]152   return -1;
153  }
154 } else {
[5179]155  roar_mm_free(buf);
[224]156  return -1;
157 }
158}
159
160int main (int argc, char * argv[]) {
[3024]161 struct roar_connection       con;
162 struct roar_stream           s;
163 struct roardsp_filterchain   fchain;
164 struct roardsp_filter      * filter;
165 float  lowpass_freq = 0;
[5533]166 struct roar_audio_info info;
[3019]167 int    samples  = -1;
[5534]168 const char * server   = NULL;
169 const char * k;
[2918]170 struct roar_vio_calls stream, re;
[224]171 int    i;
[3025]172 int    mode = 0;
[224]173
[5533]174 if ( roar_profile2info(&info, "default") == -1 )
175  return 1;
176
[224]177 for (i = 1; i < argc; i++) {
178  k = argv[i];
179
180  if ( strcmp(k, "--server") == 0 ) {
[5950]181   ROAR_CKHAVEARGS(1);
[224]182   server = argv[++i];
[5533]183  } else if ( strcmp(k, "--rate") == 0 || strcmp(k, "-R") == 0 ) {
[5950]184   ROAR_CKHAVEARGS(1);
[5533]185   info.rate = roar_str2rate(argv[++i]);
186  } else if ( strcmp(k, "--bits") == 0 || strcmp(k, "-B") == 0 ) {
[5950]187   ROAR_CKHAVEARGS(1);
[5533]188   info.bits = roar_str2bits(argv[++i]);
189  } else if ( strcmp(k, "--channels") == 0 || strcmp(k, "--chans") == 0 || strcmp(k, "-C") == 0 ) {
[5950]190   ROAR_CKHAVEARGS(1);
[5533]191   info.channels = roar_str2channels(argv[++i]);
192  } else if ( !strcmp(k, "--aiprofile") ) {
[5950]193   ROAR_CKHAVEARGS(1);
[5533]194   if ( roar_profile2info(&info, argv[++i]) == -1 ) {
195    fprintf(stderr, "Error: Can not load audio profile: %s: %s\n", argv[i], roar_error2str(roar_error));
196    return 1;
197   }
[224]198  } else if ( strcmp(k, "--samples") == 0 ) {
[5950]199   ROAR_CKHAVEARGS(1);
[224]200   samples = atoi(argv[++i]);
[1633]201  } else if ( strcmp(k, "--db") == 0 ) {
[3091]202   mode |= MODE_PC;
203   mode -= MODE_PC;
[3025]204   mode |= MODE_DB;
[3091]205  } else if ( strcmp(k, "--pc") == 0 ) {
206   mode |= MODE_DB;
207   mode -= MODE_DB;
208   mode |= MODE_PC;
[3025]209  } else if ( strcmp(k, "--beat") == 0 ) {
210   mode |= MODE_BEAT;
[3024]211  } else if ( strcmp(k, "--lowpass") == 0 ) {
[5950]212   ROAR_CKHAVEARGS(1);
[3024]213   lowpass_freq = atof(argv[++i]);
[224]214  } else if ( strcmp(k, "--help") == 0 ) {
215   usage();
216   return 0;
217  } else {
218   fprintf(stderr, "Error: unknown argument: %s\n", k);
219   usage();
220   return 1;
221  }
222 }
223
[3025]224 if ( !mode )
225  mode = MODE_PC;
226
[3019]227 if ( samples == -1 )
[5533]228  samples = info.rate/10;
[3019]229
[3024]230 if ( roar_simple_connect(&con, server, "roarvumeter") == -1 ) {
231  fprintf(stderr, "Error: can not connect to server!\n");
232  return 1;
233 }
234
[5533]235 if ( roar_vio_simple_new_stream_obj(&stream, &con, &s,
236                                     info.rate, info.channels, info.bits, ROAR_CODEC_DEFAULT,
237                                     ROAR_DIR_MONITOR, -1) == -1) {
[2918]238  fprintf(stderr, "Error: can not start monetoring\n");
[224]239  return 1;
240 }
241
[2918]242 if ( roar_vio_open_re(&re, &stream) == -1 ) {
243  roar_vio_close(&stream);
244  fprintf(stderr, "Error: can not open RE VIO layer\n");
245  return 1;
246 }
247
[3024]248 if ( roardsp_fchain_init(&fchain) == -1 ) {
249  roar_vio_close(&re);
250  fprintf(stderr, "Error: can not init filterchain\n");
251  return 1;
252 }
253
254 if ( lowpass_freq > 1 ) {
[3091]255  for (i = 0; i < LOWPASS_ORDER; i++) {
[3026]256   if ( roardsp_filter_new(&filter, &s, ROARDSP_FILTER_LOWP) == -1 ) {
257    fprintf(stderr, "Error: can not open lowpass\n");
258    roar_vio_close(&re);
259    roardsp_fchain_uninit(&fchain);
260    return 1;
261   }
[3024]262
[3026]263   if ( roardsp_filter_ctl(filter, ROARDSP_FCTL_FREQ, &lowpass_freq) == -1 ) {
264    fprintf(stderr, "Error: can not set filter frequency\n");
265    roar_vio_close(&re);
266    roardsp_fchain_uninit(&fchain);
267    return 1;
268   }
[3024]269
[3026]270   if ( roardsp_fchain_add(&fchain, filter) == -1 ) {
271    fprintf(stderr, "Error: can not set filter frequency\n");
272    roar_vio_close(&re);
273    roardsp_fchain_uninit(&fchain);
274    return 1;
275   }
[3024]276  }
277 }
278
[5533]279 vumeter(&re, samples*info.channels, info.bits, info.channels, mode, &fchain);
[224]280
[225]281 printf("\n"); // if the reach this then roard has quited and we should print a newline
282
[2918]283 roar_vio_close(&re);
[224]284
[3024]285 roar_disconnect(&con);
286
287 roardsp_fchain_uninit(&fchain);
288
[224]289 return 0;
290}
291
[1103]292#else
293int main (void) {
294 fprintf(stderr, "Error: No Math library support compiled in.\n");
295 return 1;
296}
297#endif
298
[224]299//ll
Note: See TracBrowser for help on using the repository browser.