103 lines
2.6 KiB
C
103 lines
2.6 KiB
C
/*
|
|
* SS5 signal coder.
|
|
*
|
|
* Copyright by Andreas Eversberg (jolly@eversberg.eu)
|
|
*
|
|
* This software may be used and distributed according to the terms
|
|
* of the GNU General Public License, incorporated herein by reference.
|
|
*
|
|
*/
|
|
|
|
#include "main.h"
|
|
#include "ss5_encode.h"
|
|
|
|
/* 2*PI*f/8000 */
|
|
static double ss5_freq[9][2] = {
|
|
{0.0, 0}, /* 0: 0 */
|
|
{700, 0.19952623}, /* 1: 700, -7db */
|
|
{900, 0.19952623}, /* 2: 900, -7db */
|
|
{1100, 0.19952623}, /* 3: 1100, -7db */
|
|
{1300, 0.19952623}, /* 4: 1300, -7db */
|
|
{1500, 0.19952623}, /* 5: 1500, -7db */
|
|
{1700, 0.19952623}, /* 6: 1700, -7db */
|
|
{2400, 0.12589254}, /* 7: 2400, -9db */
|
|
{2600, 0.12589254}, /* 8: 2600, -9db */
|
|
};
|
|
|
|
static char ss5_digits[][3] = {
|
|
{'1', 1, 2},
|
|
{'2', 1, 3},
|
|
{'3', 2, 3},
|
|
{'4', 1, 4},
|
|
{'5', 2, 4},
|
|
{'6', 3, 4},
|
|
{'7', 1, 5},
|
|
{'8', 2, 5},
|
|
{'9', 3, 5},
|
|
{'0', 4, 5},
|
|
{'*', 1, 6}, /* code 11 */
|
|
{'#', 2, 6}, /* code 12 */
|
|
{'a', 3, 6}, /* KP1 */
|
|
{'b', 4, 6}, /* KP2 */
|
|
{'c', 5, 6}, /* ST */
|
|
{'A', 7, 0}, /* 2400 answer, acknowledge */
|
|
{'B', 8, 0}, /* 2600 busy */
|
|
{'C', 7, 8}, /* 2600+2400 clear forward */
|
|
{0 , 0, 0},
|
|
};
|
|
|
|
static unsigned char sintab[15+3][8192]; /* sine tables of about one second sound (error <1Hz) */
|
|
|
|
/* generate sine tables */
|
|
void ss5_sine_generate(void)
|
|
{
|
|
int i, j;
|
|
int cycles1, cycles2;
|
|
double vol1, vol2, phase1, phase2;
|
|
signed short sample;
|
|
|
|
for (i = 0; i < 15+3; i++) {
|
|
/* how many cycles are within 8192 samples (rounded!) */
|
|
cycles1 = (int)(ss5_freq[(int)ss5_digits[i][1]][0] / 8000.0 * 8192.0 + 0.5);
|
|
cycles2 = (int)(ss5_freq[(int)ss5_digits[i][2]][0] / 8000.0 * 8192.0 + 0.5);
|
|
/* how much phase shift within one cycle */
|
|
phase1 = 2.0 * 3.14159265 * cycles1 / 8192.0;
|
|
phase2 = 2.0 * 3.14159265 * cycles2 / 8192.0;
|
|
/* volume */
|
|
vol1 = ss5_freq[(int)ss5_digits[i][1]][1] * 32768.0;
|
|
vol2 = ss5_freq[(int)ss5_digits[i][2]][1] * 32768.0;
|
|
for (j = 0; j < 8192; j++) {
|
|
sample = (int)(sin(phase1 * j) * vol1);
|
|
sample += (int)(sin(phase2 * j) * vol2);
|
|
sintab[i][j] = audio_s16_to_law[sample & 0xffff];
|
|
}
|
|
}
|
|
}
|
|
|
|
/* encode digit at given sample_nr with given lengt and return law-encoded audio */
|
|
unsigned char *ss5_encode(unsigned char *buffer, int len, char digit, int sample_nr)
|
|
{
|
|
int i, j;
|
|
|
|
/* get frequency from digit */
|
|
i = 0;
|
|
while(ss5_digits[i][0]) {
|
|
if (digit == ss5_digits[i][0])
|
|
break;
|
|
i++;
|
|
}
|
|
if (!ss5_digits[i][0]) {
|
|
PERROR("Digit '%c' does not exist.\n", digit);
|
|
memset(buffer, audio_s16_to_law[0], len);
|
|
return buffer;
|
|
}
|
|
|
|
/* copy tones */
|
|
for (j = 0; j < len; j++)
|
|
*buffer++ = sintab[i][sample_nr++ & 8191];
|
|
|
|
return buffer;
|
|
}
|
|
|
|
|