kopia lustrzana https://github.com/projecthorus/radiosonde_auto_rx
Translation von IQ-Signalen
rodzic
866f408dec
commit
fbfdee9d8e
|
@ -0,0 +1,163 @@
|
|||
|
||||
/*
|
||||
* ./shift <IQ.wav> [freq] [> IQ_translated.wav]
|
||||
*/
|
||||
|
||||
/*
|
||||
sdrsharpIQ.wav = conj(rtlsdrIQ.wav) -> 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <complex.h>
|
||||
|
||||
|
||||
#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, y;
|
||||
|
||||
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;
|
||||
|
||||
if (argv[1]) {
|
||||
|
||||
fp = fopen(argv[1], "rb");
|
||||
if (fp == NULL) return -1;
|
||||
|
||||
fout = stdout; //fopen("tmp_out.wav", "wb");
|
||||
read_IQwavheader(fp, &sample_rate, &bits_sample, fout);
|
||||
|
||||
if (argv[2]) f = (double)atoi(argv[2]); // f0
|
||||
|
||||
sample = 0;
|
||||
for ( ; ; ) {
|
||||
|
||||
if (read_csample(fp, &z) == EOF) break;
|
||||
|
||||
t = (double)sample / sample_rate;
|
||||
w = cexp(t*2*PI*f*I) * z;
|
||||
|
||||
write_csample(fout, w);
|
||||
sample++;
|
||||
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
fclose(fout);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Ładowanie…
Reference in New Issue