/* * ./shift IQ.wav [freq] [> IQ_translated.wav] ## translate * ./shift IQ.wav - [> IQ_swap.wav] ## swap IQ */ /* sdr# rtlsdrIQ.wav: swapIQ */ /* time domain frequency domain w(t) = exp(t*i*2pi*f0)*z(t) <-> W(f) = Z(f-f0) z = x + iy w = u + iv = exp(ia)*z u = x*cos(a) - y*sin(a); v = x*sin(a) + y*cos(a); */ #include #include #include #include #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_IQwavheader(FILE *fp, int *sample_rate, int *bits_sample, FILE *fout) { int channels = 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; else fwrite(txt, 1, 4, fout); if (strncmp(txt, "RIFF", 4)) return -1; // pos_WAVE = 8L if (fread(txt, 1, 4, fp) < 4) return -1; else fwrite(txt, 1, 4, fout); if (fread(txt, 1, 4, fp) < 4) return -1; else fwrite(txt, 1, 4, fout); if (strncmp(txt, "WAVE", 4)) return -1; // pos_fmt = 12L for ( ; ; ) { if ( (byte=fgetc(fp)) == EOF ) return -1; else 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; else fwrite(dat, 1, 4, fout); if (fread(dat, 1, 2, fp) < 2) return -1; else fwrite(dat, 1, 2, fout); if (fread(dat, 1, 2, fp) < 2) return -1; else fwrite(dat, 1, 2, fout); channels = dat[0] + (dat[1] << 8); if (fread(dat, 1, 4, fp) < 4) return -1; else fwrite(dat, 1, 4, fout); *sample_rate = dat[0] | (dat[1] << 8) | (dat[2] << 16) | (dat[3] << 24); //memcpy(&sr, dat, 4); if (fread(dat, 1, 4, fp) < 4) return -1; else fwrite(dat, 1, 4, fout); if (fread(dat, 1, 2, fp) < 2) return -1; else fwrite(dat, 1, 2, fout); if (fread(dat, 1, 2, fp) < 2) return -1; else fwrite(dat, 1, 2, fout); *bits_sample = dat[0] + (dat[1] << 8); // pos_dat = 36L + info for ( ; ; ) { if ( (byte=fgetc(fp)) == EOF ) return -1; else 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; else fwrite(dat, 1, 4, fout); fprintf(stderr, "sample_rate: %d\n", *sample_rate); fprintf(stderr, "bits : %d\n", *bits_sample); fprintf(stderr, "channels : %d\n", channels); if ((*bits_sample != 8) && (*bits_sample != 16)) return -2; if (channels != 2) return -3; 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; } return 0; } int write_csample(FILE *fp, double complex w) { int u, v; if (bits_sample == 8) { w += 128 + I*128; } u = creal(w); v = cimag(w); // 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 main(int argc, char *argv[]) { FILE *fp, *fout; int sample = 0; double t, f = 0; double complex z, w; int swap = 0; if (argv[1]) { fp = fopen(argv[1], "rb"); if (fp == NULL) return -1; fout = stdout; //fopen("tmp_out.wav", "wb"); if (read_IQwavheader(fp, &sample_rate, &bits_sample, fout) != 0) { fprintf(stderr, "error: wav header\n"); return -1; } if (argv[2]) { if (strcmp(argv[2], "-") == 0) swap = 1; else f = (double)atoi(argv[2]); // f0 } sample = 0; for ( ; ; ) { if (read_csample(fp, &z) == EOF) break; if (swap) { // swap IQ w = cimag(z) + I*creal(z); // = cexp(I*PI/2) * conj(z) = I * conj(z); // W(f) = Z(-f); fuer Spiegelung reicht: w = conj(z) } else { // translate t = (double)sample / sample_rate; w = cexp(t*2*PI*f*I) * z; } write_csample(fout, w); sample++; } fclose(fp); fclose(fout); } return 0; }