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