1 // morse.cxx -- Morse code generation class
3 // Written by Curtis Olson, started March 2001.
5 // Copyright (C) 2001 Curtis L. Olson - curt@flightgear.org
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.
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.
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.
24 #include <simgear/constants.h>
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 */
68 // allocate and initialize sound samples
69 bool FGMorse::init() {
73 for ( i = 0; i < TRANSITION_BYTES; ++i ) {
74 float level = ( sin( (double) i * 2.0 * SGD_PI
75 / (8000.0 / LO_FREQUENCY) ) )
76 * ((double)i / TRANSITION_BYTES)
79 /* Convert to unsigned byte */
80 lo_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
83 for ( i = TRANSITION_BYTES;
84 i < DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE; ++i ) {
85 float level = ( sin( (double) i * 2.0 * SGD_PI
86 / (8000.0 / LO_FREQUENCY) ) )
89 /* Convert to unsigned byte */
90 lo_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
93 for ( i = DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE;
94 i < DIT_SIZE - COUNT_SIZE;
96 float level = ( sin( (double) i * 2.0 * SGD_PI
97 / (8000.0 / LO_FREQUENCY) ) )
98 * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5;
101 /* Convert to unsigned byte */
102 lo_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
104 for ( i = DIT_SIZE - COUNT_SIZE; i < DIT_SIZE; ++i ) {
105 lo_dit[ i ] = (unsigned char) ( 0.5 * 255.0 ) ;
109 for ( i = 0; i < TRANSITION_BYTES; ++i ) {
110 float level = ( sin( (double) i * 2.0 * SGD_PI
111 / (8000.0 / HI_FREQUENCY)) )
112 * ((double)i / TRANSITION_BYTES) / 2.0 + 0.5;
114 /* Convert to unsigned byte */
115 hi_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
118 for ( i = TRANSITION_BYTES;
119 i < DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE; ++i ) {
120 float level = ( sin( (double) i * 2.0 * SGD_PI
121 / (8000.0 / HI_FREQUENCY) ) )
124 /* Convert to unsigned byte */
125 hi_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
127 j = TRANSITION_BYTES;
128 for ( i = DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE;
129 i < DIT_SIZE - COUNT_SIZE;
131 float level = ( sin( (double) i * 2.0 * SGD_PI
132 / (8000.0 / HI_FREQUENCY) ) )
133 * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5;
136 /* Convert to unsigned byte */
137 hi_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
139 for ( i = DIT_SIZE - COUNT_SIZE; i < DIT_SIZE; ++i ) {
140 hi_dit[ i ] = (unsigned char) ( 0.5 * 255.0 ) ;
144 for ( i = 0; i < TRANSITION_BYTES; ++i ) {
145 float level = ( sin( (double) i * 2.0 * SGD_PI
146 / (8000.0 / LO_FREQUENCY) ) )
147 * ((double)i / TRANSITION_BYTES) / 2.0 + 0.5;
149 /* Convert to unsigned byte */
150 lo_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
153 for ( i = TRANSITION_BYTES;
154 i < DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE;
156 float level = ( sin( (double) i * 2.0 * SGD_PI
157 / (8000.0 / LO_FREQUENCY) ) )
160 /* Convert to unsigned byte */
161 lo_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
163 j = TRANSITION_BYTES;
164 for ( i = DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE;
165 i < DAH_SIZE - COUNT_SIZE;
167 float level = ( sin( (double) i * 2.0 * SGD_PI
168 / (8000.0 / LO_FREQUENCY) ) )
169 * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5;
172 /* Convert to unsigned byte */
173 lo_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
175 for ( i = DAH_SIZE - COUNT_SIZE; i < DAH_SIZE; ++i ) {
176 lo_dah[ i ] = (unsigned char) ( 0.5 * 255.0 ) ;
180 for ( i = 0; i < TRANSITION_BYTES; ++i ) {
181 float level = ( sin( (double) i * 2.0 * SGD_PI
182 / (8000.0 / HI_FREQUENCY) ) )
183 * ((double)i / TRANSITION_BYTES) / 2.0 + 0.5;
185 /* Convert to unsigned byte */
186 hi_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
189 for ( i = TRANSITION_BYTES;
190 i < DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE;
192 float level = ( sin( (double) i * 2.0 * SGD_PI
193 / (8000.0 / HI_FREQUENCY) ) )
196 /* Convert to unsigned byte */
197 hi_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
199 j = TRANSITION_BYTES;
200 for ( i = DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE;
201 i < DAH_SIZE - COUNT_SIZE;
203 float level = ( sin( (double) i * 2.0 * SGD_PI
204 / (8000.0 / HI_FREQUENCY) ) )
205 * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5;
208 /* Convert to unsigned byte */
209 hi_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
211 for ( i = DAH_SIZE - COUNT_SIZE; i < DAH_SIZE; ++i ) {
212 hi_dah[ i ] = (unsigned char) ( 0.5 * 255.0 ) ;
216 for ( i = 0; i < SPACE_SIZE; ++i ) {
217 space[ i ] = (unsigned char) ( 0.5 * 255 ) ;
224 // allocate and initialize sound samples
225 bool FGMorse::cust_init(const int freq ) {
229 for ( i = 0; i < TRANSITION_BYTES; ++i ) {
230 float level = ( sin( (double) i * 2.0 * SGD_PI / (8000.0 / freq)) )
231 * ((double)i / TRANSITION_BYTES) / 2.0 + 0.5;
233 /* Convert to unsigned byte */
234 cust_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
237 for ( i = TRANSITION_BYTES;
238 i < DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE; ++i ) {
239 float level = ( sin( (double) i * 2.0 * SGD_PI / (8000.0 / freq) ) )
242 /* Convert to unsigned byte */
243 cust_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
245 j = TRANSITION_BYTES;
246 for ( i = DIT_SIZE - TRANSITION_BYTES - COUNT_SIZE;
247 i < DIT_SIZE - COUNT_SIZE;
249 float level = ( sin( (double) i * 2.0 * SGD_PI / (8000.0 / freq) ) )
250 * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5;
253 /* Convert to unsigned byte */
254 cust_dit[ i ] = (unsigned char) ( level * 255.0 ) ;
256 for ( i = DIT_SIZE - COUNT_SIZE; i < DIT_SIZE; ++i ) {
257 cust_dit[ i ] = (unsigned char) ( 0.5 * 255.0 ) ;
261 for ( i = 0; i < TRANSITION_BYTES; ++i ) {
262 float level = ( sin( (double) i * 2.0 * SGD_PI / (8000.0 / freq) ) )
263 * ((double)i / TRANSITION_BYTES) / 2.0 + 0.5;
265 /* Convert to unsigned byte */
266 cust_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
269 for ( i = TRANSITION_BYTES;
270 i < DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE;
272 float level = ( sin( (double) i * 2.0 * SGD_PI / (8000.0 / freq) ) )
275 /* Convert to unsigned byte */
276 cust_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
278 j = TRANSITION_BYTES;
279 for ( i = DAH_SIZE - TRANSITION_BYTES - COUNT_SIZE;
280 i < DAH_SIZE - COUNT_SIZE;
282 float level = ( sin( (double) i * 2.0 * SGD_PI / (8000.0 / freq) ) )
283 * ((double)j / TRANSITION_BYTES) / 2.0 + 0.5;
286 /* Convert to unsigned byte */
287 cust_dah[ i ] = (unsigned char) ( level * 255.0 ) ;
289 for ( i = DAH_SIZE - COUNT_SIZE; i < DAH_SIZE; ++i ) {
290 cust_dah[ i ] = (unsigned char) ( 0.5 * 255.0 ) ;
294 for ( i = 0; i < SPACE_SIZE; ++i ) {
295 space[ i ] = (unsigned char) ( 0.5 * 255 ) ;
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();
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;
313 if ( freq == LO_FREQUENCY ) {
316 } else if ( freq == HI_FREQUENCY ) {
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 ) {
332 } else if ( alphabet[c][j] == DAH ) {
336 length += SPACE_SIZE;
338 // skip unknown character
341 // add 2x more space to the end of the string
342 length += 2 * SPACE_SIZE;
344 // 2. Allocate space for the message
345 unsigned char *buffer = new unsigned char[length];
347 // 3. Assemble the message;
348 unsigned char *buf_ptr = buffer;
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 );
357 } else if ( alphabet[c][j] == DAH ) {
358 memcpy( buf_ptr, dah_ptr, DAH_SIZE );
362 memcpy( buf_ptr, space, SPACE_SIZE );
363 buf_ptr += SPACE_SIZE;
365 // skip unknown character
368 memcpy( buf_ptr, space, SPACE_SIZE );
369 buf_ptr += SPACE_SIZE;
370 memcpy( buf_ptr, space, SPACE_SIZE );
371 buf_ptr += SPACE_SIZE;
373 // 4. create the simple sound and return
374 FGSimpleSound *sample = new FGSimpleSound( buffer, length );