1 /*
2  * SpanDSP - a series of DSP components for telephony
3  *
4  * test_sig_tone.c
5  *
6  * Written by Steve Underwood <steveu@coppice.org>
7  *
8  * Copyright (C) 2004 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: sig_tone_tests.c,v 1.20 2008/05/13 13:17:26 steveu Exp $
26  */
27 
28 /*! \file */
29 
30 /*! \page sig_tone_tests_page The signaling tone processor tests
31 \section sig_tone_tests_sec_1 What does it do?
32 ???.
33 
34 \section sig_tone_tests_sec_2 How does it work?
35 ???.
36 */
37 
38 #if defined(HAVE_CONFIG_H)
39 #include "config.h"
40 #endif
41 
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <memory.h>
45 #include <audiofile.h>
46 
47 #include "spandsp.h"
48 
49 #define OUT_FILE_NAME   "sig_tone.wav"
50 
51 static int sampleno = 0;
52 static int tone_1_present = 0;
53 static int tone_2_present = 0;
54 static int ping = 0;
55 
56 void map_frequency_response(sig_tone_state_t *s);
57 
handler(void * user_data,int what)58 static int handler(void *user_data, int what)
59 {
60     //printf("What - %d\n", what);
61     if ((what & SIG_TONE_1_CHANGE))
62     {
63         tone_1_present = what & SIG_TONE_1_PRESENT;
64         printf("Tone 1 is %s after %d samples\n", (tone_1_present)  ?  "on"  : "off", (what >> 16) & 0xFFFF);
65     }
66     /*endif*/
67     if ((what & SIG_TONE_2_CHANGE))
68     {
69         tone_2_present = what & SIG_TONE_2_PRESENT;
70         printf("Tone 2 is %s after %d samples\n", (tone_2_present)  ?  "on"  : "off", (what >> 16) & 0xFFFF);
71     }
72     /*endif*/
73     if ((what & SIG_TONE_UPDATE_REQUEST))
74     {
75         /* The signaling processor wants to know what to do next */
76         if (sampleno < 800)
77         {
78             /* 100ms off-hook */
79             printf("100ms off-hook - %d samples\n", 800 - sampleno);
80             return 0x02 | ((800 - sampleno) << 16) | SIG_TONE_RX_PASSTHROUGH;
81         }
82         /*endif*/
83         if (sampleno < 4800)
84         {
85             /* 500ms idle */
86             printf("500ms idle - %d samples\n", 4800 - sampleno);
87             return 0x02 | SIG_TONE_1_PRESENT | ((4800 - sampleno) << 16) | SIG_TONE_RX_PASSTHROUGH;
88         }
89         /*endif*/
90         if (sampleno < 5600)
91         {
92             /* 100ms seize */
93             printf("100ms seize - %d samples\n", 5600 - sampleno);
94             return 0x02 | ((5600 - sampleno) << 16) | SIG_TONE_RX_PASSTHROUGH;
95         }
96         /*endif*/
97         if (ping)
98         {
99             printf("33ms break - 262 samples\n");
100             ping = !ping;
101             return 0x02 | (262 << 16) | SIG_TONE_RX_PASSTHROUGH;
102         }
103         else
104         {
105             printf("67ms make - 528 samples\n");
106             ping = !ping;
107             return 0x02 |  SIG_TONE_1_PRESENT | (528 << 16) | SIG_TONE_RX_PASSTHROUGH;
108         }
109         /*endif*/
110     }
111     /*endif*/
112     return 0;
113 }
114 /*- End of function --------------------------------------------------------*/
115 
map_frequency_response(sig_tone_state_t * s)116 void map_frequency_response(sig_tone_state_t *s)
117 {
118     int16_t buf[8192];
119     awgn_state_t noise_source;
120     int i;
121     int f;
122     uint32_t phase_acc;
123     int32_t phase_rate;
124     int32_t scaling;
125     double sum;
126 
127     /* Things like noise don't highlight the frequency response of the high Q notch
128        very well. We use a slowly swept frequency to check it. */
129     awgn_init_dbm0(&noise_source, 1234567, -10.0f);
130     for (f = 1;  f < 4000;  f++)
131     {
132         phase_rate = dds_phase_rate(f);
133         scaling = dds_scaling_dbm0(-10);
134         phase_acc = 0;
135         for (i = 0;  i < 8192;  i++)
136             buf[i] = dds_mod(&phase_acc, phase_rate, scaling, 0);
137         /*endfor*/
138         sig_tone_rx(s, buf, 8192);
139         sum = 0.0;
140         for (i = 1000;  i < 8192;  i++)
141             sum += (double) buf[i]*(double) buf[i];
142         /*endfor*/
143         sum = sqrt(sum);
144         printf("%7d %f\n", f, sum);
145     }
146     /*endfor*/
147 }
148 /*- End of function --------------------------------------------------------*/
149 
main(int argc,char * argv[])150 int main(int argc, char *argv[])
151 {
152     int16_t amp[160];
153     int16_t out_amp[2*160];
154     AFfilehandle outhandle;
155     AFfilesetup filesetup;
156     int outframes;
157     int i;
158     int rx_samples;
159     int tx_samples;
160     sig_tone_state_t state;
161     awgn_state_t noise_source;
162 
163     filesetup = afNewFileSetup();
164     if (filesetup == AF_NULL_FILESETUP)
165     {
166         fprintf(stderr, "    Failed to create file setup\n");
167         exit(2);
168     }
169     /*endif*/
170     afInitSampleFormat(filesetup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16);
171     afInitRate(filesetup, AF_DEFAULT_TRACK, (float) SAMPLE_RATE);
172     afInitFileFormat(filesetup, AF_FILE_WAVE);
173     afInitChannels(filesetup, AF_DEFAULT_TRACK, 2);
174 
175     outhandle = afOpenFile(OUT_FILE_NAME, "w", filesetup);
176     if (outhandle == AF_NULL_FILEHANDLE)
177     {
178         fprintf(stderr, "    Cannot create wave file '%s'\n", OUT_FILE_NAME);
179         exit(2);
180     }
181     /*endif*/
182 
183     awgn_init_dbm0(&noise_source, 1234567, -30.0f);
184 
185     printf("2400Hz/26000Hz tests.\n");
186     sig_tone_init(&state, SIG_TONE_2400HZ_2600HZ, handler, NULL);
187     state.current_tx_tone |= SIG_TONE_RX_PASSTHROUGH;
188 
189     map_frequency_response(&state);
190 
191     for (sampleno = 0;  sampleno < 20000;  sampleno += 160)
192     {
193         tx_samples = 160;
194         for (i = 0;  i < tx_samples;  i++)
195             amp[i] = alaw_to_linear(linear_to_alaw(awgn(&noise_source)));
196         /*endfor*/
197         for (i = 0;  i < tx_samples;  i++)
198             out_amp[2*i] = amp[i];
199         /*endfor*/
200         rx_samples = sig_tone_rx(&state, amp, tx_samples);
201         for (i = 0;  i < rx_samples;  i++)
202             out_amp[2*i + 1] = amp[i];
203         /*endfor*/
204         outframes = afWriteFrames(outhandle,
205                                   AF_DEFAULT_TRACK,
206                                   out_amp,
207                                   rx_samples);
208         if (outframes != rx_samples)
209         {
210             fprintf(stderr, "    Error writing wave file\n");
211             exit(2);
212         }
213         /*endif*/
214     }
215 
216     printf("2280Hz tests.\n");
217     sig_tone_init(&state, SIG_TONE_2280HZ, handler, NULL);
218     state.current_tx_tone |= SIG_TONE_RX_PASSTHROUGH;
219 
220     map_frequency_response(&state);
221 
222     for (sampleno = 0;  sampleno < 20000;  sampleno += 160)
223     {
224         memset(amp, 0, sizeof(int16_t)*160);
225         tx_samples = sig_tone_tx(&state, amp, 160);
226         for (i = 0;  i < tx_samples;  i++)
227             out_amp[2*i] = amp[i];
228         /*endfor*/
229         rx_samples = sig_tone_rx(&state, amp, tx_samples);
230         for (i = 0;  i < rx_samples;  i++)
231             out_amp[2*i + 1] = amp[i];
232         /*endfor*/
233         outframes = afWriteFrames(outhandle,
234                                   AF_DEFAULT_TRACK,
235                                   out_amp,
236                                   rx_samples);
237         if (outframes != rx_samples)
238         {
239             fprintf(stderr, "    Error writing wave file\n");
240             exit(2);
241         }
242         /*endif*/
243     }
244     /*endfor*/
245     if (afCloseFile(outhandle) != 0)
246     {
247         fprintf(stderr, "    Cannot close wave file '%s'\n", OUT_FILE_NAME);
248         exit(2);
249     }
250     /*endif*/
251     afFreeFileSetup(filesetup);
252 
253     printf("Tests completed.\n");
254     return  0;
255 }
256 /*- End of function --------------------------------------------------------*/
257 /*- End of file ------------------------------------------------------------*/
258