kopia lustrzana https://github.com/rs1729/RS
IQ <-> FM
rodzic
00427a5698
commit
cfa4635052
104
iq/wavIQ.c
104
iq/wavIQ.c
|
@ -13,6 +13,9 @@
|
||||||
./wavIQ -l 6000 IQtransl2.wav > IQlowpass2.wav
|
./wavIQ -l 6000 IQtransl2.wav > IQlowpass2.wav
|
||||||
./wavIQ -d1 IQlowpass2.wav > IQdemod2.wav
|
./wavIQ -d1 IQlowpass2.wav > IQdemod2.wav
|
||||||
sox IQdemod2.wav -r 48000 IQdemod48k2.wav
|
sox IQdemod2.wav -r 48000 IQdemod48k2.wav
|
||||||
|
|
||||||
|
./wavIQ -fm IQdemod48k1.wav > dfmIQ2.wav
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,6 +30,7 @@
|
||||||
#define TRANSLATE 0x20
|
#define TRANSLATE 0x20
|
||||||
#define LOWPASS 0x30
|
#define LOWPASS 0x30
|
||||||
#define DEMOD 0x40
|
#define DEMOD 0x40
|
||||||
|
#define FMMOD 0x50
|
||||||
|
|
||||||
#define PI (3.1415926535897932384626433832795)
|
#define PI (3.1415926535897932384626433832795)
|
||||||
|
|
||||||
|
@ -40,7 +44,8 @@ int findstr(char *buff, char *str, int pos) {
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
int read_IQwavheader(FILE *fp, int *sample_rate, int *bits_sample, unsigned char ch, FILE *fout) {
|
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;
|
unsigned int channels = 0, size = 0;
|
||||||
char txt[4+1] = "\0\0\0\0";
|
char txt[4+1] = "\0\0\0\0";
|
||||||
unsigned char dat[4];
|
unsigned char dat[4];
|
||||||
|
@ -51,7 +56,7 @@ int read_IQwavheader(FILE *fp, int *sample_rate, int *bits_sample, unsigned char
|
||||||
|
|
||||||
if (fread(dat, 1, 4, fp) < 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 = dat[0] | (dat[1] << 8) | (dat[2] << 16) | (dat[3] << 24); //fprintf(stderr, "filesize: 0x%08x = %d\n", size+8, size+8);
|
||||||
if (ch == 1) size = (size+8-44)/2 + 44-8;
|
size = ((size+8-44)*chOut)/chIn + 44-8;
|
||||||
for (byte = 0; byte < 4; byte++) { dat[byte] = size & 0xFF; size >>= 8; }
|
for (byte = 0; byte < 4; byte++) { dat[byte] = size & 0xFF; size >>= 8; }
|
||||||
fwrite(dat, 1, 4, fout);
|
fwrite(dat, 1, 4, fout);
|
||||||
|
|
||||||
|
@ -70,16 +75,30 @@ int read_IQwavheader(FILE *fp, int *sample_rate, int *bits_sample, unsigned char
|
||||||
if (fread(dat, 1, 4, fp) < 4) return -1; fwrite(dat, 1, 4, fout);
|
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);
|
if (fread(dat, 1, 2, fp) < 2) return -1; fwrite(dat, 1, 2, fout);
|
||||||
|
|
||||||
|
// channels
|
||||||
if (fread(dat, 1, 2, fp) < 2) return -1;
|
if (fread(dat, 1, 2, fp) < 2) return -1;
|
||||||
channels = dat[0] + (dat[1] << 8);
|
channels = dat[0] + (dat[1] << 8);
|
||||||
dat[0] = ch; fwrite(dat, 1, 2, fout);
|
dat[0] = chOut; fwrite(dat, 1, 2, fout);
|
||||||
|
|
||||||
|
// sample_rate
|
||||||
if (fread(dat, 1, 4, fp) < 4) return -1; fwrite(dat, 1, 4, fout);
|
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);
|
*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; fwrite(dat, 1, 4, fout);
|
// bytes/sec
|
||||||
if (fread(dat, 1, 2, fp) < 2) return -1; fwrite(dat, 1, 2, fout);
|
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);
|
if (fread(dat, 1, 2, fp) < 2) return -1; fwrite(dat, 1, 2, fout);
|
||||||
*bits_sample = dat[0] + (dat[1] << 8);
|
*bits_sample = dat[0] + (dat[1] << 8);
|
||||||
if ((*bits_sample != 8) && (*bits_sample != 16)) return -2;
|
if ((*bits_sample != 8) && (*bits_sample != 16)) return -2;
|
||||||
|
@ -93,11 +112,11 @@ int read_IQwavheader(FILE *fp, int *sample_rate, int *bits_sample, unsigned char
|
||||||
}
|
}
|
||||||
if (fread(dat, 1, 4, fp) < 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, "datasize: 0x%08x = %d\n", size, size);
|
size = dat[0] | (dat[1] << 8) | (dat[2] << 16) | (dat[3] << 24); //fprintf(stderr, "datasize: 0x%08x = %d\n", size, size);
|
||||||
if (ch == 1) size = size/2;
|
size = (size*chOut)/chIn;
|
||||||
for (byte = 0; byte < 4; byte++) { dat[byte] = size & 0xFF; size >>= 8; }
|
for (byte = 0; byte < 4; byte++) { dat[byte] = size & 0xFF; size >>= 8; }
|
||||||
fwrite(dat, 1, 4, fout);
|
fwrite(dat, 1, 4, fout);
|
||||||
|
|
||||||
if (channels != 2) return -3; // I&Q
|
if (channels != chIn) return -3; // I&Q: chIn=2
|
||||||
/*
|
/*
|
||||||
fprintf(stderr, "sample_rate: %d\n", *sample_rate);
|
fprintf(stderr, "sample_rate: %d\n", *sample_rate);
|
||||||
fprintf(stderr, "bits : %d\n", *bits_sample);
|
fprintf(stderr, "bits : %d\n", *bits_sample);
|
||||||
|
@ -124,12 +143,15 @@ int read_csample(FILE *fp, double complex *z) {
|
||||||
int write_csample(FILE *fp, double complex w) {
|
int write_csample(FILE *fp, double complex w) {
|
||||||
int u, v;
|
int u, v;
|
||||||
|
|
||||||
if (bits_sample == 8) {
|
if (bits_sample == 16) { w *= 256.0; }
|
||||||
w += 128 + I*128;
|
|
||||||
}
|
|
||||||
|
|
||||||
u = creal(w);
|
u = creal(w);
|
||||||
v = cimag(w);
|
v = cimag(w);
|
||||||
|
|
||||||
|
if (bits_sample == 8) {
|
||||||
|
u += 128;
|
||||||
|
v += 128;
|
||||||
|
}
|
||||||
// 16 bit (short) -> (int)
|
// 16 bit (short) -> (int)
|
||||||
fwrite( &u, bits_sample/8, 1, fp); // + 0000 .. 7FFF -> 0000 0000 .. 0000 7FFF
|
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
|
fwrite( &v, bits_sample/8, 1, fp); // - 8000 .. FFFF -> FFFF 8000 .. FFFF FFFF
|
||||||
|
@ -138,6 +160,21 @@ int write_csample(FILE *fp, double complex w) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int read_sample(FILE *fp, double *z) { // channels == 1
|
||||||
|
short x = 0;
|
||||||
|
|
||||||
|
if (fread( &x, bits_sample/8, 1, fp) != 1) return EOF;
|
||||||
|
|
||||||
|
if (bits_sample == 8) {
|
||||||
|
x -= 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
*z = x/128.0;
|
||||||
|
if (bits_sample == 16) { *z = x/256.0; }
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int write_sample(FILE *fp, double x) {
|
int write_sample(FILE *fp, double x) {
|
||||||
int b;
|
int b;
|
||||||
|
|
||||||
|
@ -211,23 +248,25 @@ double complex lowpass(double complex buffer[], int sample, int M) {
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
FILE *fp = NULL, *fout = NULL;
|
FILE *fp = NULL, *fout = NULL;
|
||||||
char *fpname = NULL;
|
char *fpname = NULL;
|
||||||
unsigned char ch = 0;
|
unsigned char chIn = 0, chOut = 0;
|
||||||
int option = 0, phi = 0, wavloaded = 0;
|
int option = 0, phi = 0, wavloaded = 0;
|
||||||
int sample = 0, M = 0;
|
int sample = 0, M = 0;
|
||||||
double t, f = 0, fm, gain;
|
double t, s, f = 0, fm, b, omega;
|
||||||
double complex z = 0, z0 = 0, w = 0,
|
double complex z = 0, z0 = 0, w = 0,
|
||||||
*buffer = NULL;
|
*buffer = NULL;
|
||||||
|
double gain = 40.0;
|
||||||
|
|
||||||
fpname = argv[0];
|
fpname = argv[0];
|
||||||
++argv;
|
++argv;
|
||||||
while ((*argv) && (!wavloaded)) {
|
while ((*argv) && (!wavloaded)) {
|
||||||
if ( (strcmp(*argv, "-h") == 0) || (strcmp(*argv, "--help") == 0) ) {
|
if ( (strcmp(*argv, "-h") == 0) || (strcmp(*argv, "--help") == 0) ) {
|
||||||
fprintf(stderr, "%s <option> IQ.wav\n", fpname);
|
fprintf(stderr, "%s <option> file.wav\n", fpname);
|
||||||
fprintf(stderr, " options:\n");
|
fprintf(stderr, " options:\n");
|
||||||
fprintf(stderr, " -s (swap IQ)\n");
|
fprintf(stderr, " -s (swap IQ)\n");
|
||||||
fprintf(stderr, " -t <freq> (translate)\n");
|
fprintf(stderr, " -t <freq> (translate)\n");
|
||||||
fprintf(stderr, " -l <freq> (lowpass)\n");
|
fprintf(stderr, " -l <freq> (lowpass)\n");
|
||||||
fprintf(stderr, " -d1,2 (demod fm)\n");
|
fprintf(stderr, " -d1,2 (demod fm)\n");
|
||||||
|
fprintf(stderr, " -fm (fm-mod)\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (strcmp(*argv, "-s") == 0) option = SWAPIQ;
|
else if (strcmp(*argv, "-s") == 0) option = SWAPIQ;
|
||||||
|
@ -251,6 +290,7 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
else if (strcmp(*argv, "-d1") == 0) { option = DEMOD; phi = 1; }
|
else if (strcmp(*argv, "-d1") == 0) { option = DEMOD; phi = 1; }
|
||||||
else if (strcmp(*argv, "-d2") == 0) { option = DEMOD; phi = 2; }
|
else if (strcmp(*argv, "-d2") == 0) { option = DEMOD; phi = 2; }
|
||||||
|
else if (strcmp(*argv, "-fm") == 0) { option = FMMOD; }
|
||||||
else {
|
else {
|
||||||
if (!option) return 0;
|
if (!option) return 0;
|
||||||
fp = fopen(*argv, "rb");
|
fp = fopen(*argv, "rb");
|
||||||
|
@ -266,11 +306,21 @@ int main(int argc, char *argv[]) {
|
||||||
if (!wavloaded) fp = stdin;
|
if (!wavloaded) fp = stdin;
|
||||||
|
|
||||||
|
|
||||||
if ( (option & 0xF0) == (DEMOD & 0xF0) ) ch = 1;
|
if ( (option & 0xF0) == (DEMOD & 0xF0) ) {
|
||||||
else ch = 2;
|
chIn = 2;
|
||||||
|
chOut = 1;
|
||||||
|
}
|
||||||
|
else if ((option & 0xF0) == (FMMOD & 0xF0) ) {
|
||||||
|
chIn = 1;
|
||||||
|
chOut = 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
chIn = 2;
|
||||||
|
chOut = 2;
|
||||||
|
}
|
||||||
|
|
||||||
fout = stdout; //fopen("tmp_out.wav", "wb");
|
fout = stdout; //fopen("tmp_out.wav", "wb");
|
||||||
if (read_IQwavheader(fp, &sample_rate, &bits_sample, ch, fout) != 0) {
|
if (read_wavheader(fp, &sample_rate, &bits_sample, chIn, chOut, fout) != 0) {
|
||||||
fprintf(stderr, "error: wav header\n");
|
fprintf(stderr, "error: wav header\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -282,8 +332,8 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
case SWAPIQ:
|
case SWAPIQ:
|
||||||
while ( read_csample(fp, &z) != EOF ) {
|
while ( read_csample(fp, &z) != EOF ) {
|
||||||
w = cimag(z) + I*creal(z); // = cexp(I*PI/2) * conj(z) = I * conj(z);
|
w = cimag(z) + I*creal(z); // = cexp(I*PI/2) * conj(z) = I * conj(z);
|
||||||
write_csample(fout, w);
|
write_csample(fout, w);
|
||||||
sample++;
|
sample++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -315,19 +365,29 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
case DEMOD:
|
case DEMOD:
|
||||||
z0 = 0;
|
z0 = 0;
|
||||||
gain = 128.0;
|
|
||||||
while ( read_csample(fp, &z) != EOF ) {
|
while ( read_csample(fp, &z) != EOF ) {
|
||||||
w = z * conj(z0);
|
w = z * conj(z0);
|
||||||
switch ( phi ) { // phi'-Algo
|
switch ( phi ) { // phi'-Algo
|
||||||
case 1: fm = carg(w); break; // = atan2( cimag(w) , creal(w) );
|
case 1: fm = carg(w); break; // = atan2( cimag(w) , creal(w) );
|
||||||
case 2: fm = cimag(w) / (cabs(z0)*cabs(z0)); break;
|
case 2: fm = cimag(w) / (cabs(z0)*cabs(z0)); break;
|
||||||
} //fm3 = cimag(w); // FM: |z|=const
|
} //fm3 = cimag(w); // FM: |z|=const
|
||||||
write_sample(fout, fm*gain/PI);
|
write_sample(fout, fm*gain);
|
||||||
z0 = z;
|
z0 = z;
|
||||||
sample++;
|
sample++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FMMOD:
|
||||||
|
b = 0.7;
|
||||||
|
while ( read_sample(fp, &s) != EOF ) {
|
||||||
|
// integrate phi'
|
||||||
|
omega += 2*PI * b*s ; // mod 2*PI
|
||||||
|
w = cexp(I*omega);
|
||||||
|
write_csample(fout, w*gain);
|
||||||
|
sample++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
Ładowanie…
Reference in New Issue