Adding interface support for remote app (chan_lcr).
[lcr.git] / ss5_encode.c
1 /*
2  * SS5 signal coder.
3  *
4  * Copyright            by Andreas Eversberg (jolly@eversberg.eu)
5  *
6  * This software may be used and distributed according to the terms
7  * of the GNU General Public License, incorporated herein by reference.
8  *
9  */
10
11 #include "main.h"
12 #include "ss5_encode.h"
13
14         /* 2*PI*f/8000 */
15 static double ss5_freq[9][2] = {
16         {0.0, 0},               /* 0: 0 */
17         {700,   0.19952623},    /* 1: 700, -7db */
18         {900,   0.19952623},    /* 2: 900, -7db */
19         {1100,  0.19952623},    /* 3: 1100, -7db */
20         {1300,  0.19952623},    /* 4: 1300, -7db */
21         {1500,  0.19952623},    /* 5: 1500, -7db */
22         {1700,  0.19952623},    /* 6: 1700, -7db */
23         {2400,  0.12589254},    /* 7: 2400, -9db */
24         {2600,  0.12589254},    /* 8: 2600, -9db */
25 };
26
27 static char ss5_digits[][3] = {
28         {'1', 1, 2},
29         {'2', 1, 3},
30         {'3', 2, 3},
31         {'4', 1, 4},
32         {'5', 2, 4},
33         {'6', 3, 4},
34         {'7', 1, 5},
35         {'8', 2, 5},
36         {'9', 3, 5},
37         {'0', 4, 5},
38         {'*', 1, 6}, /* code 11 */
39         {'#', 2, 6}, /* code 12 */
40         {'a', 3, 6}, /* KP1 */
41         {'b', 4, 6}, /* KP2 */
42         {'c', 5, 6}, /* ST */
43         {'A', 7, 0}, /* 2400 answer, acknowledge */
44         {'B', 8, 0}, /* 2600 busy */
45         {'C', 7, 8}, /* 2600+2400 clear forward */
46         {0 , 0, 0},
47 };
48
49 static unsigned char sintab[15+3][8192]; /* sine tables of about one second sound (error <1Hz) */
50
51 /* generate sine tables */
52 void ss5_sine_generate(void)
53 {
54         int i, j;
55         int cycles1, cycles2;
56         double vol1, vol2, phase1, phase2;
57         signed short sample;
58
59         for (i = 0; i < 15+3; i++) {
60                 /* how many cycles are within 8192 samples (rounded!) */
61                 cycles1 = (int)(ss5_freq[(int)ss5_digits[i][1]][0] / 8000.0 * 8192.0 + 0.5);
62                 cycles2 = (int)(ss5_freq[(int)ss5_digits[i][2]][0] / 8000.0 * 8192.0 + 0.5);
63                 /* how much phase shift within one cycle */
64                 phase1 = 2.0 * 3.14159265 * cycles1 / 8192.0;
65                 phase2 = 2.0 * 3.14159265 * cycles2 / 8192.0;
66                 /* volume */
67                 vol1 = ss5_freq[(int)ss5_digits[i][1]][1] * 32768.0;
68                 vol2 = ss5_freq[(int)ss5_digits[i][2]][1] * 32768.0;
69                 for (j = 0; j < 8192; j++) {
70                         sample = (int)(sin(phase1 * j) * vol1);
71                         sample += (int)(sin(phase2 * j) * vol2);
72                         sintab[i][j] = audio_s16_to_law[sample & 0xffff];
73                 }
74         }
75 }
76
77 /* encode digit at given sample_nr with given lengt and return law-encoded audio */
78 unsigned char *ss5_encode(unsigned char *buffer, int len, char digit, int sample_nr)
79 {
80         int i, j;
81
82         /* get frequency from digit */
83         i = 0;
84         while(ss5_digits[i][0]) {
85                 if (digit == ss5_digits[i][0])
86                         break;
87                 i++;
88         }
89         if (!ss5_digits[i][0]) {
90                 PERROR("Digit '%c' does not exist.\n", digit);
91                 memset(buffer, audio_s16_to_law[0], sizeof(buffer));
92                 return buffer;
93         }
94
95         /* copy tones */
96         for (j = 0; j < len; j++)
97                 *buffer++ = sintab[i][sample_nr++ & 8191];
98
99         return buffer;
100 }
101
102