]> git.mxchange.org Git - flightgear.git/blob - src/Sound/morse.cxx
FG_ to SG_ namespace changes.
[flightgear.git] / src / Sound / morse.cxx
1 // morse.cxx -- Morse code generation class
2 //
3 // Written by Curtis Olson, started March 2001.
4 //
5 // Copyright (C) 2001  Curtis L. Olson - curt@flightgear.org
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 // $Id$
22
23
24 #include <simgear/constants.h>
25
26 #include "morse.hxx"
27
28
29 static const char alphabet[26][4] = {
30     { DI, DAH, end, end },      /* A */ 
31     { DA, DI, DI, DIT },        /* B */ 
32     { DA, DI, DA, DIT },        /* C */ 
33     { DA, DI, DIT, end },       /* D */ 
34     { DIT, end, end, end },     /* E */ 
35     { DI, DI, DA, DIT },        /* F */ 
36     { DA, DA, DIT, end },       /* G */ 
37     { DI, DI, DI, DIT },        /* H */ 
38     { DI, DIT, end, end },      /* I */ 
39     { DI, DA, DA, DAH },        /* J */ 
40     { DA, DI, DAH, end },       /* K */ 
41     { DI, DA, DI, DIT },        /* L */ 
42     { DA, DAH, end, end },      /* M */ 
43     { DA, DIT, end, end },      /* N */ 
44     { DA, DA, DAH, end },       /* O */ 
45     { DI, DA, DA, DIT },        /* P */ 
46     { DA, DA, DI, DAH },        /* Q */ 
47     { DI, DA, DIT, end },       /* R */ 
48     { DI, DI, DIT, end },       /* S */ 
49     { DAH, end, end, end },     /* T */ 
50     { DI, DI, DAH, end },       /* U */ 
51     { DI, DI, DI, DAH },        /* V */ 
52     { DI, DA, DAH, end },       /* W */ 
53     { DA, DI, DI, DAH },        /* X */ 
54     { DA, DI, DA, DAH },        /* Y */ 
55     { DA, DA, DI, DIT }         /* Z */ 
56 };
57
58
59 // constructor
60 FGMorse::FGMorse() {
61 }
62
63 // destructor
64 FGMorse::~FGMorse() {
65 }
66
67
68 // allocate and initialize sound samples
69 bool FGMorse::init() {
70     int i, j;
71
72     // Make Low DIT
73     for ( i = 0; i < TRANSITION_BYTES; ++i ) {
74         float level = ( sin( (double) i * 2.0 * SG_PI
75                              / (8000.0 / LO_FREQUENCY) ) )
76             * ((double)i / TRANSITION_BYTES)
77             / 2.0 + 0.5;
78
79         /* Convert to unsigned byte */
80         lo_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
81     }
82
83     for ( i = TRANSITION_BYTES;
84           i < DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE; ++i ) {
85         float level = ( sin( (double) i * 2.0 * SG_PI
86                              / (8000.0 / LO_FREQUENCY) ) )
87             / 2.0 + 0.5;
88
89         /* Convert to unsigned byte */
90         lo_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
91     }
92     j = TRANSITION_BYTES;
93     for ( i = DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE;
94           i < DIT_SIZE - COUNT_SIZE;
95           ++i ) {
96         float level = ( sin( (double) i * 2.0 * SG_PI
97                              / (8000.0 / LO_FREQUENCY) ) )
98             * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5;
99         --j;
100
101         /* Convert to unsigned byte */
102         lo_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
103     }
104     for ( i = DIT_SIZE - COUNT_SIZE; i < DIT_SIZE; ++i ) {
105         lo_dit[ i ] = (unsigned char) ( 0.5 * 255.0 ) ;
106     }
107
108     // Make High DIT
109     for ( i = 0; i < TRANSITION_BYTES; ++i ) {
110         float level = ( sin( (double) i * 2.0 * SG_PI
111                              / (8000.0 / HI_FREQUENCY)) )
112             * ((double)i / TRANSITION_BYTES) / 2.0 + 0.5;
113
114         /* Convert to unsigned byte */
115         hi_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
116     }
117
118     for ( i = TRANSITION_BYTES;
119           i < DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE; ++i ) {
120         float level = ( sin( (double) i * 2.0 * SG_PI
121                              / (8000.0 / HI_FREQUENCY) ) )
122             / 2.0 + 0.5;
123
124         /* Convert to unsigned byte */
125         hi_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
126     }
127     j = TRANSITION_BYTES;
128     for ( i = DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE;
129           i < DIT_SIZE - COUNT_SIZE;
130           ++i ) {
131         float level = ( sin( (double) i * 2.0 * SG_PI
132                              / (8000.0 / HI_FREQUENCY) ) )
133             * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5;
134         --j;
135
136         /* Convert to unsigned byte */
137         hi_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
138     }
139     for ( i = DIT_SIZE - COUNT_SIZE; i < DIT_SIZE; ++i ) {
140         hi_dit[ i ] = (unsigned char) ( 0.5 * 255.0 ) ;
141     }
142
143     // Make Low DAH
144     for ( i = 0; i < TRANSITION_BYTES; ++i ) {
145         float level = ( sin( (double) i * 2.0 * SG_PI
146                              / (8000.0 / LO_FREQUENCY) ) )
147             * ((double)i / TRANSITION_BYTES) / 2.0 + 0.5;
148
149         /* Convert to unsigned byte */
150         lo_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
151     }
152
153     for ( i = TRANSITION_BYTES;
154           i < DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE;
155           ++i ) {
156         float level = ( sin( (double) i * 2.0 * SG_PI
157                              / (8000.0 / LO_FREQUENCY) ) )
158             / 2.0 + 0.5;
159
160         /* Convert to unsigned byte */
161         lo_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
162     }
163     j = TRANSITION_BYTES;
164     for ( i = DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE;
165           i < DAH_SIZE - COUNT_SIZE;
166           ++i ) {
167         float level = ( sin( (double) i * 2.0 * SG_PI
168                              / (8000.0 / LO_FREQUENCY) ) )
169             * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5;
170         --j;
171
172         /* Convert to unsigned byte */
173         lo_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
174     }
175     for ( i = DAH_SIZE - COUNT_SIZE; i < DAH_SIZE; ++i ) {
176         lo_dah[ i ] = (unsigned char) ( 0.5 * 255.0 ) ;
177     }
178
179     // Make High DAH
180     for ( i = 0; i < TRANSITION_BYTES; ++i ) {
181         float level = ( sin( (double) i * 2.0 * SG_PI
182                              / (8000.0 / HI_FREQUENCY) ) )
183             * ((double)i / TRANSITION_BYTES) / 2.0 + 0.5;
184
185         /* Convert to unsigned byte */
186         hi_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
187     }
188
189     for ( i = TRANSITION_BYTES;
190           i < DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE;
191           ++i ) {
192         float level = ( sin( (double) i * 2.0 * SG_PI
193                              / (8000.0 / HI_FREQUENCY) ) )
194             / 2.0 + 0.5;
195
196         /* Convert to unsigned byte */
197         hi_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
198     }
199     j = TRANSITION_BYTES;
200     for ( i = DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE;
201           i < DAH_SIZE - COUNT_SIZE;
202           ++i ) {
203         float level = ( sin( (double) i * 2.0 * SG_PI
204                              / (8000.0 / HI_FREQUENCY) ) )
205             * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5;
206         --j;
207
208         /* Convert to unsigned byte */
209         hi_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
210     }
211     for ( i = DAH_SIZE - COUNT_SIZE; i < DAH_SIZE; ++i ) {
212         hi_dah[ i ] = (unsigned char) ( 0.5 * 255.0 ) ;
213     }
214
215     // Make SPACE
216     for ( i = 0; i < SPACE_SIZE; ++i ) {
217         space[ i ] = (unsigned char) ( 0.5 * 255 ) ;
218     }
219
220     return true;
221 }
222
223
224 // allocate and initialize sound samples
225 bool FGMorse::cust_init(const int freq ) {
226     int i, j;
227
228     // Make DIT
229     for ( i = 0; i < TRANSITION_BYTES; ++i ) {
230         float level = ( sin( (double) i * 2.0 * SG_PI / (8000.0 / freq)) )
231             * ((double)i / TRANSITION_BYTES) / 2.0 + 0.5;
232
233         /* Convert to unsigned byte */
234         cust_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
235     }
236
237     for ( i = TRANSITION_BYTES;
238           i < DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE; ++i ) {
239         float level = ( sin( (double) i * 2.0 * SG_PI / (8000.0 / freq) ) )
240             / 2.0 + 0.5;
241
242         /* Convert to unsigned byte */
243         cust_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
244     }
245     j = TRANSITION_BYTES;
246     for ( i = DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE;
247           i < DIT_SIZE - COUNT_SIZE;
248           ++i ) {
249         float level = ( sin( (double) i * 2.0 * SG_PI / (8000.0 / freq) ) )
250             * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5;
251         --j;
252
253         /* Convert to unsigned byte */
254         cust_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
255     }
256     for ( i = DIT_SIZE - COUNT_SIZE; i < DIT_SIZE; ++i ) {
257         cust_dit[ i ] = (unsigned char) ( 0.5 * 255.0 ) ;
258     }
259
260     // Make DAH
261     for ( i = 0; i < TRANSITION_BYTES; ++i ) {
262         float level = ( sin( (double) i * 2.0 * SG_PI / (8000.0 / freq) ) )
263             * ((double)i / TRANSITION_BYTES) / 2.0 + 0.5;
264
265         /* Convert to unsigned byte */
266         cust_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
267     }
268
269     for ( i = TRANSITION_BYTES;
270           i < DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE;
271           ++i ) {
272         float level = ( sin( (double) i * 2.0 * SG_PI / (8000.0 / freq) ) )
273             / 2.0 + 0.5;
274
275         /* Convert to unsigned byte */
276         cust_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
277     }
278     j = TRANSITION_BYTES;
279     for ( i = DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE;
280           i < DAH_SIZE - COUNT_SIZE;
281           ++i ) {
282         float level = ( sin( (double) i * 2.0 * SG_PI / (8000.0 / freq) ) )
283             * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5;
284         --j;
285
286         /* Convert to unsigned byte */
287         cust_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
288     }
289     for ( i = DAH_SIZE - COUNT_SIZE; i < DAH_SIZE; ++i ) {
290         cust_dah[ i ] = (unsigned char) ( 0.5 * 255.0 ) ;
291     }
292
293     // Make SPACE
294     for ( i = 0; i < SPACE_SIZE; ++i ) {
295         space[ i ] = (unsigned char) ( 0.5 * 255 ) ;
296     }
297
298     return true;
299 }
300
301
302 // make a FGSimpleSound morse code transmission for the specified string
303 FGSimpleSound *FGMorse::make_ident( const string& id, const int freq ) {
304     char *idptr = (char *)id.c_str();
305
306     int length = 0;
307     int i, j;
308
309     // 0. Select the frequency.  If custom frequency, generate the
310     // sound fragments we need on the fly.
311     unsigned char *dit_ptr, *dah_ptr;
312
313     if ( freq == LO_FREQUENCY ) {
314         dit_ptr = lo_dit;
315         dah_ptr = lo_dah;
316     } else if ( freq == HI_FREQUENCY ) {
317         dit_ptr = hi_dit;
318         dah_ptr = hi_dah;
319     } else {
320         cust_init( freq );
321         dit_ptr = cust_dit;
322         dah_ptr = cust_dah;
323     }
324
325     // 1. Determine byte length of message
326     for ( i = 0; i < (int)id.length(); ++i ) {
327         if ( idptr[i] >= 'A' && idptr[i] <= 'Z' ) {
328             char c = idptr[i] - 'A';
329             for ( j = 0; j < 4 || alphabet[c][j] == end; ++j ) {
330                 if ( alphabet[c][j] == DIT ) {
331                     length += DIT_SIZE;
332                 } else if ( alphabet[c][j] == DAH ) {
333                     length += DAH_SIZE;
334                 }
335             }
336             length += SPACE_SIZE;
337         } else {
338             // skip unknown character
339         }
340     }
341     // add 2x more space to the end of the string
342     length += 2 * SPACE_SIZE;
343
344     // 2. Allocate space for the message
345     unsigned char *buffer = new unsigned char[length];
346
347     // 3. Assemble the message;
348     unsigned char *buf_ptr = buffer;
349
350     for ( i = 0; i < (int)id.length(); ++i ) {
351         if ( idptr[i] >= 'A' && idptr[i] <= 'Z' ) {
352             char c = idptr[i] - 'A';
353             for ( j = 0; j < 4 || alphabet[c][j] == end; ++j ) {
354                 if ( alphabet[c][j] == DIT ) {
355                     memcpy( buf_ptr, dit_ptr, DIT_SIZE );
356                     buf_ptr += DIT_SIZE;
357                 } else if ( alphabet[c][j] == DAH ) {
358                     memcpy( buf_ptr, dah_ptr, DAH_SIZE );
359                     buf_ptr += DAH_SIZE;
360                 }
361             }
362             memcpy( buf_ptr, space, SPACE_SIZE );
363             buf_ptr += SPACE_SIZE;
364         } else {
365             // skip unknown character
366         }
367     }
368     memcpy( buf_ptr, space, SPACE_SIZE );
369     buf_ptr += SPACE_SIZE;
370     memcpy( buf_ptr, space, SPACE_SIZE );
371     buf_ptr += SPACE_SIZE;
372
373     // 4. create the simple sound and return
374     FGSimpleSound *sample = new FGSimpleSound( buffer, length );
375
376     return sample;
377 }