Mercurial > hg > audiostuff
comparison spandsp-0.0.6pre17/tests/line_model_monitor.cpp @ 4:26cd8f1ef0b1
import spandsp-0.0.6pre17
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 15:50:58 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
3:c6c5a16ce2f2 | 4:26cd8f1ef0b1 |
---|---|
1 /* | |
2 * SpanDSP - a series of DSP components for telephony | |
3 * | |
4 * line_model_monitor.cpp - Model activity in a telephone line model, using the FLTK toolkit. | |
5 * | |
6 * Written by Steve Underwood <steveu@coppice.org> | |
7 * | |
8 * Copyright (C) 2006 Steve Underwood | |
9 * | |
10 * All rights reserved. | |
11 * | |
12 * This program is free software; you can redistribute it and/or modify | |
13 * it under the terms of the GNU General Public License version 2, as | |
14 * published by the Free Software Foundation. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU General Public License | |
22 * along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
24 * | |
25 * $Id: line_model_monitor.cpp,v 1.5 2008/09/08 16:10:41 steveu Exp $ | |
26 */ | |
27 | |
28 #ifdef HAVE_CONFIG_H | |
29 #include "config.h" | |
30 #endif | |
31 | |
32 #if defined(HAVE_FL_FL_H) && defined(HAVE_FL_FL_CARTESIAN_H) | |
33 | |
34 #define __STDC_LIMIT_MACROS | |
35 | |
36 #include <inttypes.h> | |
37 #include <stdio.h> | |
38 #include <math.h> | |
39 #include <stdlib.h> | |
40 #include <string.h> | |
41 #include <unistd.h> | |
42 #include <sys/select.h> | |
43 #if defined(HAVE_FFTW3_H) | |
44 #include <fftw3.h> | |
45 #else | |
46 #include <fftw.h> | |
47 #endif | |
48 | |
49 #include <FL/Fl.H> | |
50 #include <FL/Fl_Overlay_Window.H> | |
51 #include <FL/Fl_Light_Button.H> | |
52 #include <FL/Fl_Cartesian.H> | |
53 #include <FL/Fl_Audio_Meter.H> | |
54 #include <FL/fl_draw.H> | |
55 | |
56 #include "spandsp.h" | |
57 #include "line_model_monitor.h" | |
58 | |
59 struct line_model_monitor_s | |
60 { | |
61 Fl_Double_Window *w; | |
62 | |
63 Fl_Audio_Meter *audio_meter; | |
64 | |
65 Fl_Group *c_spec; | |
66 Fl_Group *c_right; | |
67 Fl_Group *c_can; | |
68 Fl_Group *c_line_model; | |
69 | |
70 Ca_Canvas *canvas_spec; | |
71 Ca_X_Axis *spec_freq; | |
72 Ca_Y_Axis *spec_amp; | |
73 Ca_Line *spec_re; | |
74 double spec_re_plot[2*512]; | |
75 | |
76 Ca_Canvas *canvas_can; | |
77 Ca_X_Axis *can_x; | |
78 Ca_Y_Axis *can_y; | |
79 Ca_Line *can_re; | |
80 double can_re_plot[512]; | |
81 | |
82 Ca_Canvas *canvas_line_model; | |
83 Ca_X_Axis *line_model_x; | |
84 Ca_Y_Axis *line_model_y; | |
85 Ca_Line *line_model_re; | |
86 double line_model_re_plot[512]; | |
87 | |
88 int in_ptr; | |
89 #if defined(HAVE_FFTW3_H) | |
90 double in[1024][2]; | |
91 double out[1024][2]; | |
92 #else | |
93 fftw_complex in[1024]; | |
94 fftw_complex out[1024]; | |
95 #endif | |
96 fftw_plan p; | |
97 }; | |
98 | |
99 static int skip = 0; | |
100 static struct line_model_monitor_s model; | |
101 static struct line_model_monitor_s *s = &model; | |
102 | |
103 int line_model_monitor_can_update(const float *coeffs, int len) | |
104 { | |
105 int i; | |
106 float min; | |
107 float max; | |
108 | |
109 if (s->can_re) | |
110 delete s->can_re; | |
111 | |
112 s->canvas_can->current(s->canvas_can); | |
113 i = 0; | |
114 min = coeffs[i]; | |
115 max = coeffs[i]; | |
116 for (i = 0; i < len; i++) | |
117 { | |
118 s->can_re_plot[2*i] = i; | |
119 s->can_re_plot[2*i + 1] = coeffs[i]; | |
120 if (min > coeffs[i]) | |
121 min = coeffs[i]; | |
122 if (max < coeffs[i]) | |
123 max = coeffs[i]; | |
124 } | |
125 s->can_y->maximum((max == min) ? max + 0.2 : max); | |
126 s->can_y->minimum(min); | |
127 s->can_re = new Ca_Line(len, s->can_re_plot, 0, 0, FL_BLUE, CA_NO_POINT); | |
128 if (++skip >= 100) | |
129 { | |
130 skip = 0; | |
131 Fl::check(); | |
132 } | |
133 return 0; | |
134 } | |
135 /*- End of function --------------------------------------------------------*/ | |
136 | |
137 int line_model_monitor_line_model_update(const float *coeffs, int len) | |
138 { | |
139 int i; | |
140 float min; | |
141 float max; | |
142 | |
143 if (s->line_model_re) | |
144 delete s->line_model_re; | |
145 | |
146 s->canvas_line_model->current(s->canvas_line_model); | |
147 i = 0; | |
148 min = coeffs[i]; | |
149 max = coeffs[i]; | |
150 for (i = 0; i < len; i++) | |
151 { | |
152 s->line_model_re_plot[2*i] = i; | |
153 s->line_model_re_plot[2*i + 1] = coeffs[i]; | |
154 if (min > coeffs[i]) | |
155 min = coeffs[i]; | |
156 if (max < coeffs[i]) | |
157 max = coeffs[i]; | |
158 } | |
159 s->line_model_y->maximum((max == min) ? max + 0.2 : max); | |
160 s->line_model_y->minimum(min); | |
161 s->line_model_re = new Ca_Line(len, s->line_model_re_plot, 0, 0, FL_BLUE, CA_NO_POINT); | |
162 if (++skip >= 100) | |
163 { | |
164 skip = 0; | |
165 Fl::check(); | |
166 } | |
167 return 0; | |
168 } | |
169 /*- End of function --------------------------------------------------------*/ | |
170 | |
171 int line_model_monitor_line_spectrum_update(const int16_t amp[], int len) | |
172 { | |
173 int i; | |
174 int x; | |
175 | |
176 for (i = 0; i < len; i++) | |
177 s->audio_meter->sample(amp[i]/32768.0); | |
178 | |
179 if (s->in_ptr + len < 512) | |
180 { | |
181 /* Just add this fragment to the buffer. */ | |
182 for (i = 0; i < len; i++) | |
183 #if defined(HAVE_FFTW3_H) | |
184 s->in[s->in_ptr + i][0] = amp[i]; | |
185 #else | |
186 s->in[s->in_ptr + i].re = amp[i]; | |
187 #endif | |
188 s->in_ptr += len; | |
189 return 0; | |
190 } | |
191 if (len >= 512) | |
192 { | |
193 /* We have enough for a whole block. Use the last 512 samples | |
194 we have. */ | |
195 x = len - 512; | |
196 for (i = 0; i < 512; i++) | |
197 #if defined(HAVE_FFTW3_H) | |
198 s->in[i][0] = amp[x + i]; | |
199 #else | |
200 s->in[i].re = amp[x + i]; | |
201 #endif | |
202 } | |
203 else | |
204 { | |
205 /* We want the last 512 samples. */ | |
206 x = 512 - len; | |
207 for (i = 0; i < x; i++) | |
208 #if defined(HAVE_FFTW3_H) | |
209 s->in[i][0] = s->in[s->in_ptr - x + i][0]; | |
210 #else | |
211 s->in[i].re = s->in[s->in_ptr - x + i].re; | |
212 #endif | |
213 for (i = x; i < 512; i++) | |
214 #if defined(HAVE_FFTW3_H) | |
215 s->in[i][0] = amp[i - x]; | |
216 #else | |
217 s->in[i].re = amp[i - x]; | |
218 #endif | |
219 } | |
220 s->in_ptr = 0; | |
221 #if defined(HAVE_FFTW3_H) | |
222 fftw_execute(s->p); | |
223 #else | |
224 fftw_one(s->p, s->in, s->out); | |
225 #endif | |
226 if (s->spec_re) | |
227 delete s->spec_re; | |
228 s->canvas_spec->current(s->canvas_spec); | |
229 for (i = 0; i < 512; i++) | |
230 { | |
231 s->spec_re_plot[2*i] = i*4000.0/512.0; | |
232 #if defined(HAVE_FFTW3_H) | |
233 s->spec_re_plot[2*i + 1] = 20.0*log10(sqrt(s->out[i][0]*s->out[i][0] + s->out[i][1]*s->out[i][1])/(256.0*32768)) + 3.14; | |
234 #else | |
235 s->spec_re_plot[2*i + 1] = 20.0*log10(sqrt(s->out[i].re*s->out[i].re + s->out[i].im*s->out[i].im)/(256.0*32768)) + 3.14; | |
236 #endif | |
237 } | |
238 s->spec_re = new Ca_Line(512, s->spec_re_plot, 0, 0, FL_BLUE, CA_NO_POINT); | |
239 Fl::check(); | |
240 return 0; | |
241 } | |
242 /*- End of function --------------------------------------------------------*/ | |
243 | |
244 int start_line_model_monitor(int len) | |
245 { | |
246 char buf[132 + 1]; | |
247 float x; | |
248 float y; | |
249 int i; | |
250 | |
251 s->w = new Fl_Double_Window(850, 400, "Telephone line model monitor"); | |
252 | |
253 s->c_spec = new Fl_Group(0, 0, 380, 400); | |
254 s->c_spec->box(FL_DOWN_BOX); | |
255 s->c_spec->align(FL_ALIGN_TOP | FL_ALIGN_INSIDE); | |
256 | |
257 s->canvas_spec = new Ca_Canvas(60, 30, 300, 300, "Spectrum"); | |
258 s->canvas_spec->box(FL_PLASTIC_DOWN_BOX); | |
259 s->canvas_spec->color(7); | |
260 s->canvas_spec->align(FL_ALIGN_TOP); | |
261 s->canvas_spec->border(15); | |
262 | |
263 s->spec_freq = new Ca_X_Axis(65, 330, 290, 30, "Freq (Hz)"); | |
264 s->spec_freq->align(FL_ALIGN_BOTTOM); | |
265 s->spec_freq->minimum(0); | |
266 s->spec_freq->maximum(4000); | |
267 s->spec_freq->label_format("%g"); | |
268 s->spec_freq->minor_grid_color(fl_gray_ramp(20)); | |
269 s->spec_freq->major_grid_color(fl_gray_ramp(15)); | |
270 s->spec_freq->label_grid_color(fl_gray_ramp(10)); | |
271 s->spec_freq->grid_visible(CA_LABEL_GRID | CA_ALWAYS_VISIBLE); | |
272 s->spec_freq->minor_grid_style(FL_DOT); | |
273 s->spec_freq->major_step(5); | |
274 s->spec_freq->label_step(1); | |
275 s->spec_freq->axis_color(FL_BLACK); | |
276 s->spec_freq->axis_align(CA_BOTTOM | CA_LINE); | |
277 | |
278 s->spec_amp = new Ca_Y_Axis(20, 35, 40, 290, "Amp (dBmO)"); | |
279 s->spec_amp->align(FL_ALIGN_LEFT); | |
280 s->spec_amp->minimum(-80.0); | |
281 s->spec_amp->maximum(10.0); | |
282 s->spec_amp->minor_grid_color(fl_gray_ramp(20)); | |
283 s->spec_amp->major_grid_color(fl_gray_ramp(15)); | |
284 s->spec_amp->label_grid_color(fl_gray_ramp(10)); | |
285 //s->spec_amp->grid_visible(CA_MINOR_TICK | CA_MAJOR_TICK | CA_LABEL_GRID | CA_ALWAYS_VISIBLE); | |
286 s->spec_amp->grid_visible(CA_LABEL_GRID | CA_ALWAYS_VISIBLE); | |
287 s->spec_amp->minor_grid_style(FL_DOT); | |
288 s->spec_amp->major_step(5); | |
289 s->spec_amp->label_step(1); | |
290 s->spec_amp->axis_color(FL_BLACK); | |
291 | |
292 s->spec_amp->current(); | |
293 s->spec_re = NULL; | |
294 | |
295 s->c_spec->end(); | |
296 | |
297 s->c_right = new Fl_Group(440, 0, 465, 405); | |
298 | |
299 s->c_can = new Fl_Group(380, 0, 415, 200); | |
300 s->c_can->box(FL_DOWN_BOX); | |
301 s->c_can->align(FL_ALIGN_TOP | FL_ALIGN_INSIDE); | |
302 s->c_can->current(); | |
303 | |
304 s->canvas_can = new Ca_Canvas(460, 35, 300, 100, "??? coefficients"); | |
305 s->canvas_can->box(FL_PLASTIC_DOWN_BOX); | |
306 s->canvas_can->color(7); | |
307 s->canvas_can->align(FL_ALIGN_TOP); | |
308 Fl_Group::current()->resizable(s->canvas_can); | |
309 s->canvas_can->border(15); | |
310 | |
311 s->can_x = new Ca_X_Axis(465, 135, 290, 30, "Tap"); | |
312 s->can_x->align(FL_ALIGN_BOTTOM); | |
313 s->can_x->minimum(0.0); | |
314 s->can_x->maximum((float) len); | |
315 s->can_x->label_format("%g"); | |
316 s->can_x->minor_grid_color(fl_gray_ramp(20)); | |
317 s->can_x->major_grid_color(fl_gray_ramp(15)); | |
318 s->can_x->label_grid_color(fl_gray_ramp(10)); | |
319 s->can_x->grid_visible(CA_LABEL_GRID | CA_ALWAYS_VISIBLE); | |
320 s->can_x->minor_grid_style(FL_DOT); | |
321 s->can_x->major_step(5); | |
322 s->can_x->label_step(1); | |
323 s->can_x->axis_align(CA_BOTTOM | CA_LINE); | |
324 s->can_x->axis_color(FL_BLACK); | |
325 s->can_x->current(); | |
326 | |
327 s->can_y = new Ca_Y_Axis(420, 40, 40, 90, "Amp"); | |
328 s->can_y->align(FL_ALIGN_LEFT); | |
329 s->can_y->minimum(-0.1); | |
330 s->can_y->maximum(0.1); | |
331 s->can_y->minor_grid_color(fl_gray_ramp(20)); | |
332 s->can_y->major_grid_color(fl_gray_ramp(15)); | |
333 s->can_y->label_grid_color(fl_gray_ramp(10)); | |
334 s->can_y->grid_visible(CA_LABEL_GRID | CA_ALWAYS_VISIBLE); | |
335 s->can_y->minor_grid_style(FL_DOT); | |
336 s->can_y->major_step(5); | |
337 s->can_y->label_step(1); | |
338 s->can_y->axis_color(FL_BLACK); | |
339 s->can_y->current(); | |
340 | |
341 s->c_can->end(); | |
342 | |
343 s->can_re = NULL; | |
344 | |
345 s->c_line_model = new Fl_Group(380, 200, 415, 200); | |
346 s->c_line_model->box(FL_DOWN_BOX); | |
347 s->c_line_model->align(FL_ALIGN_TOP | FL_ALIGN_INSIDE); | |
348 s->c_line_model->current(); | |
349 | |
350 s->canvas_line_model = new Ca_Canvas(460, 235, 300, 100, "Line impulse response model"); | |
351 s->canvas_line_model->box(FL_PLASTIC_DOWN_BOX); | |
352 s->canvas_line_model->color(7); | |
353 s->canvas_line_model->align(FL_ALIGN_TOP); | |
354 Fl_Group::current()->resizable(s->canvas_line_model); | |
355 s->canvas_line_model->border(15); | |
356 | |
357 s->line_model_x = new Ca_X_Axis(465, 335, 290, 30, "Tap"); | |
358 s->line_model_x->align(FL_ALIGN_BOTTOM); | |
359 s->line_model_x->minimum(0.0); | |
360 s->line_model_x->maximum((float) len); | |
361 s->line_model_x->label_format("%g"); | |
362 s->line_model_x->minor_grid_color(fl_gray_ramp(20)); | |
363 s->line_model_x->major_grid_color(fl_gray_ramp(15)); | |
364 s->line_model_x->label_grid_color(fl_gray_ramp(10)); | |
365 s->line_model_x->grid_visible(CA_LABEL_GRID | CA_ALWAYS_VISIBLE); | |
366 s->line_model_x->minor_grid_style(FL_DOT); | |
367 s->line_model_x->major_step(5); | |
368 s->line_model_x->label_step(1); | |
369 s->line_model_x->axis_align(CA_BOTTOM | CA_LINE); | |
370 s->line_model_x->axis_color(FL_BLACK); | |
371 s->line_model_x->current(); | |
372 | |
373 s->line_model_y = new Ca_Y_Axis(420, 240, 40, 90, "Amp"); | |
374 s->line_model_y->align(FL_ALIGN_LEFT); | |
375 s->line_model_y->minimum(-0.1); | |
376 s->line_model_y->maximum(0.1); | |
377 s->line_model_y->minor_grid_color(fl_gray_ramp(20)); | |
378 s->line_model_y->major_grid_color(fl_gray_ramp(15)); | |
379 s->line_model_y->label_grid_color(fl_gray_ramp(10)); | |
380 s->line_model_y->grid_visible(CA_LABEL_GRID | CA_ALWAYS_VISIBLE); | |
381 s->line_model_y->minor_grid_style(FL_DOT); | |
382 s->line_model_y->major_step(5); | |
383 s->line_model_y->label_step(1); | |
384 s->line_model_y->axis_color(FL_BLACK); | |
385 s->line_model_y->current(); | |
386 s->line_model_re = NULL; | |
387 | |
388 s->c_line_model->end(); | |
389 | |
390 s->audio_meter = new Fl_Audio_Meter(810, 40, 10, 250, ""); | |
391 s->audio_meter->box(FL_PLASTIC_UP_BOX); | |
392 s->audio_meter->type(FL_VERT_AUDIO_METER); | |
393 | |
394 s->c_right->end(); | |
395 | |
396 Fl_Group::current()->resizable(s->c_right); | |
397 s->w->end(); | |
398 s->w->show(); | |
399 | |
400 #if defined(HAVE_FFTW3_H) | |
401 s->p = fftw_plan_dft_1d(1024, s->in, s->out, FFTW_BACKWARD, FFTW_ESTIMATE); | |
402 for (i = 0; i < 1024; i++) | |
403 { | |
404 s->in[i][0] = 0.0; | |
405 s->in[i][1] = 0.0; | |
406 } | |
407 #else | |
408 s->p = fftw_create_plan(1024, FFTW_BACKWARD, FFTW_ESTIMATE); | |
409 for (i = 0; i < 1024; i++) | |
410 { | |
411 s->in[i].re = 0.0; | |
412 s->in[i].im = 0.0; | |
413 } | |
414 #endif | |
415 s->in_ptr = 0; | |
416 | |
417 Fl::check(); | |
418 return 0; | |
419 } | |
420 /*- End of function --------------------------------------------------------*/ | |
421 | |
422 void line_model_monitor_wait_to_end(void) | |
423 { | |
424 fd_set rfds; | |
425 int res; | |
426 struct timeval tv; | |
427 | |
428 fprintf(stderr, "Processing complete. Press the <enter> key to end\n"); | |
429 do | |
430 { | |
431 usleep(100000); | |
432 Fl::check(); | |
433 FD_ZERO(&rfds); | |
434 FD_SET(0, &rfds); | |
435 tv.tv_usec = 100000; | |
436 tv.tv_sec = 0; | |
437 res = select(1, &rfds, NULL, NULL, &tv); | |
438 } | |
439 while (res <= 0); | |
440 } | |
441 /*- End of function --------------------------------------------------------*/ | |
442 | |
443 void line_model_monitor_update_display(void) | |
444 { | |
445 Fl::check(); | |
446 Fl::check(); | |
447 Fl::check(); | |
448 Fl::check(); | |
449 Fl::check(); | |
450 Fl::check(); | |
451 Fl::check(); | |
452 Fl::check(); | |
453 Fl::check(); | |
454 Fl::check(); | |
455 Fl::check(); | |
456 Fl::check(); | |
457 } | |
458 /*- End of function --------------------------------------------------------*/ | |
459 #endif | |
460 /*- End of file ------------------------------------------------------------*/ |