/* gcc wavIQ.c -lm -o wavIQ ./wavIQ -s dfmIQ.wav > IQswap.wav ./wavIQ -t -10600 IQswap.wav > IQtransl1.wav ./wavIQ -l 6000 IQtransl1.wav > IQlowpass1.wav ./wavIQ -d1 IQlowpass1.wav > IQdemod1.wav sox IQdemod1.wav -r 48000 IQdemod48k1.wav ./wavIQ -t 11200 IQswap.wav > IQtransl2.wav ./wavIQ -l 6000 IQtransl2.wav > IQlowpass2.wav ./wavIQ -d1 IQlowpass2.wav > IQdemod2.wav sox IQdemod2.wav -r 48000 IQdemod48k2.wav ./wavIQ -fm IQdemod48k1.wav > dfmIQ2.wav */ #include #include #include #include #include #define SWAPIQ 0x10 #define TRANSLATE 0x20 #define LOWPASS 0x30 #define DEMOD 0x40 #define FMMOD 0x50 #define PI (3.1415926535897932384626433832795) int sample_rate, bits_sample; int findstr(char *buff, char *str, int pos) { int i; for (i = 0; i < 4; i++) { if (buff[(pos+i)%4] != str[i]) break; } return i; } int read_wavheader(FILE *fp, int *sample_rate, int *bits_sample, unsigned char chIn, unsigned char chOut, FILE *fout) { unsigned int channels = 0, size = 0; char txt[4+1] = "\0\0\0\0"; unsigned char dat[4]; int byte, p=0; if (fread(txt, 1, 4, fp) < 4) return -1; fwrite(txt, 1, 4, fout); if (strncmp(txt, "RIFF", 4)) return -1; if (fread(dat, 1, 4, fp) < 4) return -1; size = dat[0] | (dat[1] << 8) | (dat[2] << 16) | (dat[3] << 24); //fprintf(stderr, "filesize: 0x%08x = %d\n", size+8, size+8); size = ((size+8-44)*chOut)/chIn + 44-8; for (byte = 0; byte < 4; byte++) { dat[byte] = size & 0xFF; size >>= 8; } fwrite(dat, 1, 4, fout); // pos_WAVE = 8L if (fread(txt, 1, 4, fp) < 4) return -1; fwrite(txt, 1, 4, fout); if (strncmp(txt, "WAVE", 4)) return -1; // pos_fmt = 12L for ( ; ; ) { if ( (byte=fgetc(fp)) == EOF ) return -1; fprintf(fout, "%c", byte & 0xFF); txt[p % 4] = byte; p++; if (p==4) p=0; if (findstr(txt, "fmt ", p) == 4) break; } if (fread(dat, 1, 4, fp) < 4) return -1; fwrite(dat, 1, 4, fout); if (fread(dat, 1, 2, fp) < 2) return -1; fwrite(dat, 1, 2, fout); // channels if (fread(dat, 1, 2, fp) < 2) return -1; channels = dat[0] + (dat[1] << 8); dat[0] = chOut; fwrite(dat, 1, 2, fout); // sample_rate if (fread(dat, 1, 4, fp) < 4) return -1; fwrite(dat, 1, 4, fout); *sample_rate = dat[0] | (dat[1] << 8) | (dat[2] << 16) | (dat[3] << 24); //memcpy(&sr, dat, 4); // bytes/sec if (fread(dat, 1, 4, fp) < 4) return -1; size = dat[0] | (dat[1] << 8) | (dat[2] << 16) | (dat[3] << 24); size = (size*chOut)/chIn; for (byte = 0; byte < 4; byte++) { dat[byte] = size & 0xFF; size >>= 8; } fwrite(dat, 1, 4, fout); // block align if (fread(dat, 1, 2, fp) < 2) return -1; size = dat[0] | (dat[1] << 8); size = (size*chOut)/chIn; for (byte = 0; byte < 2; byte++) { dat[byte] = size & 0xFF; size >>= 8; } fwrite(dat, 1, 2, fout); // bits/sample if (fread(dat, 1, 2, fp) < 2) return -1; fwrite(dat, 1, 2, fout); *bits_sample = dat[0] + (dat[1] << 8); if ((*bits_sample != 8) && (*bits_sample != 16)) return -2; // pos_dat = 36L + info for ( ; ; ) { if ( (byte=fgetc(fp)) == EOF ) return -1; fprintf(fout, "%c", byte & 0xFF); txt[p % 4] = byte; p++; if (p==4) p=0; if (findstr(txt, "data", p) == 4) break; } if (fread(dat, 1, 4, fp) < 4) return -1; size = dat[0] | (dat[1] << 8) | (dat[2] << 16) | (dat[3] << 24); //fprintf(stderr, "datasize: 0x%08x = %d\n", size, size); size = (size*chOut)/chIn; for (byte = 0; byte < 4; byte++) { dat[byte] = size & 0xFF; size >>= 8; } fwrite(dat, 1, 4, fout); if (channels != chIn) return -3; // I&Q: chIn=2 /* fprintf(stderr, "sample_rate: %d\n", *sample_rate); fprintf(stderr, "bits : %d\n", *bits_sample); fprintf(stderr, "channels : %d\n", channels); */ return 0; } int read_csample(FILE *fp, double complex *z) { short x = 0, y = 0; if (fread( &x, bits_sample/8, 1, fp) != 1) return EOF; if (fread( &y, bits_sample/8, 1, fp) != 1) return EOF; *z = x + I*y; if (bits_sample == 8) { *z -= 128 + I*128; } *z /= 128.0; if (bits_sample == 16) { *z /= 256.0; } return 0; } int write_csample(FILE *fp, double complex w) { int u, v; w *= 128.0; if (bits_sample == 16) { w *= 256.0; } u = creal(w); v = cimag(w); if (bits_sample == 8) { u += 128; v += 128; } // 16 bit (short) -> (int) fwrite( &u, bits_sample/8, 1, fp); // + 0000 .. 7FFF -> 0000 0000 .. 0000 7FFF fwrite( &v, bits_sample/8, 1, fp); // - 8000 .. FFFF -> FFFF 8000 .. FFFF FFFF return 0; } int read_sample(FILE *fp, double *x) { // channels == 1 short b = 0; if (fread( &b, bits_sample/8, 1, fp) != 1) return EOF; if (bits_sample == 8) { b -= 128; } *x = b/128.0; if (bits_sample == 16) { *x /= 256.0; } return 0; } int write_sample(FILE *fp, double x) { int b; x *= 128.0; if (bits_sample == 8) { x += 128.0; } if (bits_sample == 16) { x *= 256.0; } b = (int)x; // -> short // 16 bit (short) -> (int) fwrite( &b, bits_sample/8, 1, fp); // + 0000 .. 7FFF -> 0000 0000 .. 0000 7FFF // - 8000 .. FFFF -> FFFF 8000 .. FFFF FFFF return 0; } // // lowpass double sinc(double x) { double y; if (x == 0) y = 1; else y = sin(PI*x)/(PI*x); return y; } double *ws = NULL; int lowpass_init(int fs, int lpf) { // lpf = lowpass freq bandwidth = 2*lp_freq double f = (double)lpf/fs; int M = 2*((2*fs)/1200); double *h, *w; double norm = 0; int n; ws = (double*)calloc( M+1, sizeof(double)); h = (double*)calloc( M+1, sizeof(double)); w = (double*)calloc( M+1, sizeof(double)); for (n = 0; n < M+1; n++) { w[n] = 0.54 - 0.46*cos(2*PI*n/M) + 0.08*cos(4*PI*n/M); h[n] = 2*f*sinc(2*f*(n-M/2)); ws[n] = w[n]*h[n]; norm += ws[n]; } for (n = 0; n < M+1; n++) { ws[n] /= norm; } free(h); h = NULL; free(w); w = NULL; return M; } double complex lowpass(double complex buffer[], int sample, int M) { int n; double complex w = 0; if (sample > M) { for (n = 0; n < M+1; n++) { w += buffer[(sample+n+1)%(M+1)]*ws[M-n]; } } return w; } // lowpass // int main(int argc, char *argv[]) { FILE *fp = NULL, *fout = NULL; char *fpname = NULL; unsigned char chIn = 0, chOut = 0; int option = 0, phi = 0, wavloaded = 0; int sample = 0, M = 0; double t, s, f = 0, fm, b, omega = 0; double complex z = 0, z0 = 0, w = 0, *buffer = NULL; double gain = 1.0; fpname = argv[0]; ++argv; while ((*argv) && (!wavloaded)) { if ( (strcmp(*argv, "-h") == 0) || (strcmp(*argv, "--help") == 0) ) { fprintf(stderr, "%s