pull/3/head
Zilog80 2017-04-23 00:07:44 +02:00
rodzic 00427a5698
commit cfa4635052
1 zmienionych plików z 82 dodań i 22 usunięć

Wyświetl plik

@ -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);