Code:
// Converts any file into a 600 baud PSK wave file
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define PI 3.14159265358979323846
int main(int argc, char **argv)
{
double dWave;
int bPrev, i, j, k, l;
long lSize;
unsigned char *lpWave;
unsigned long ulTemp;
FILE *fpIn, *fpOut;
printf("Phase Shift Keying (PSK) 1200 Hz Encoder\n");
if (argc != 2)
{
printf("Usage: pskwrite <filename>\n\n");
return 0;
}
// This was originally an allocation for a 1 second buffer (48,000 bytes)
// Could probably take this from the stack now...
lpWave = malloc(80);
if (!lpWave)
{
printf("ERROR: Couldn't allocate 80 bytes!\n\n");
return -1;
}
// get the unit change of the sine wave across the wave buffer
dWave = (2 * PI * 1200) / 48000;
// generate the wave for later use
for (i=0;i<80;i++)
lpWave[i] = (unsigned char)((sin(i * dWave) * 63) + 127);
// open the source and get size
fpIn = fopen(argv[1], "rb");
if (!fpIn)
{
printf("ERROR: Couldn't open file for reading!\n\n");
return -1;
}
fseek(fpIn, 0, SEEK_END);
lSize = ftell(fpIn) * 8 * 80; // 80 samples per wave or bit
// experience told me that this was a good idea :)
printf("Resultant wave data will be %ld bytes in size. Continue? (Y/N): ", lSize);
i = fgetc(stdin);
if (i != 'y' && i != 'Y')
{
fclose(fpIn);
printf("Aborted.\n\n");
return 0;
}
fseek(fpIn, 0, SEEK_SET);
// open the destination file and write header
fpOut = fopen("output.wav", "wb");
fwrite("RIFF", 4, 1, fpOut);
ulTemp = lSize + 32;
fwrite(&ulTemp, 4, 1, fpOut);
fwrite("WAVE", 4, 1, fpOut);
fwrite("fmt ", 4, 1, fpOut);
ulTemp = 16;
fwrite(&ulTemp, 4, 1, fpOut);
ulTemp = 1;
fwrite(&ulTemp, 2, 1, fpOut); // WAVE_FORMAT_PCM
fwrite(&ulTemp, 2, 1, fpOut); // number of channels
ulTemp = 48000;
fwrite(&ulTemp, 4, 1, fpOut); // sample rate
fwrite(&ulTemp, 4, 1, fpOut); // bytes per sec
ulTemp = 1;
fwrite(&ulTemp, 2, 1, fpOut); // block alignment
ulTemp = 8;
fwrite(&ulTemp, 2, 1, fpOut); // bits per sample
fwrite("data", 4, 1, fpOut);
fwrite(&lSize, 4, 1, fpOut);
bPrev = 0;
// process all source bytes
while ((i = fgetc(fpIn)) != EOF)
{
// for each bit
for (j=0;j<8;j++)
{
// not sure if this is right...
// differential is relative to the previous bit,
// according to the V.22 spec the phase encoding is
// +90 degrees for a 0 and +270 degrees for a 1
if (i & (1 << j))
{
k = (!bPrev) ? 20 : 0;
bPrev = 1;
}
else
{
k = (bPrev) ? 20 : 0;
bPrev = 0;
}
// write the wave from the buffer to the file
for (l=0;l<80;l++)
{
if (fputc(lpWave[k], fpOut) == EOF)
{
fclose(fpOut);
fclose(fpIn);
free(lpWave);
printf("ERROR: Write failure!\n\n");
return -1;
}
// circular buffer
if (k + 1 < 80)
k++;
else
k = 0;
}
}
}
fclose(fpOut);
fclose(fpIn);
free(lpWave);
return 0;
}