File: tdec.c

package info (click to toggle)
codec2 0.9.2-4
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 113,072 kB
  • sloc: ansic: 412,877; python: 4,004; sh: 1,540; objc: 817; asm: 683; makefile: 588
file content (141 lines) | stat: -rw-r--r-- 3,731 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
   tdec.c
   David Rowe
   Jan 2017

   Trivial non filtered decimator for high ration sample rate conversion.

   build: gcc tdec.c -o tdec -Wall -O2

*/

#include <assert.h>
#include <getopt.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

#define SIGNED_16BIT   0
#define SIGNED_8BIT    1
#define UNSIGNED_8BIT  2

void freq_shift_complex_buf(short buf[], int n, int lo_i[], int lo_q[]);

void display_help(void) {
    fprintf(stderr, "\nusage: tdec inputRawFile OutputRawFile DecimationRatio [-c]\n");
    fprintf(stderr, "\nUse - for stdin/stdout\n\n");
    fprintf(stderr, "-c complex signed 16 bit input and output\n");
    fprintf(stderr, "-d complex signed 8 bit input (e.g. HackRF), complex signed 16 bit output\n");
    fprintf(stderr, "-e complex unsigned 8 bit input (e.g. RTL-SDR), complex signed 16 bit output\n");
    fprintf(stderr, "-f -Fs/4 freq shift\n\n");
}

int main(int argc, char *argv[]) {
    FILE       *fin, *fout;
    short       dec;
    int         lo_i[3], lo_q[3];

    if (argc < 3) {
	display_help();
	exit(1);
    }

    if (strcmp(argv[1], "-") == 0) 
        fin = stdin;
    else
        fin = fopen(argv[1], "rb");
    assert(fin != NULL);

    if (strcmp(argv[2], "-") == 0) 
        fout = stdout;
    else
        fout = fopen(argv[2], "wb");
    assert(fout != NULL);

    dec = atoi(argv[3]);

    int channels = 1;
    int freq_shift = 0;
    lo_i[0] = -1; lo_i[1] =  0;
    lo_q[0] =  0; lo_q[1] = -1;
    int opt;
    int format = SIGNED_16BIT;
    while ((opt = getopt(argc, argv, "cdef")) != -1) {
        switch (opt) {
        case 'c': channels = 2; break;
        case 'd': channels = 2; format = SIGNED_8BIT; break;
        case 'e': channels = 2; format = UNSIGNED_8BIT; break;
        case 'f': freq_shift = 1; break;
        default:
            display_help();
            exit(1);
        }
    }

    if (format == SIGNED_16BIT) {
        short buf[dec*channels];
        while(fread(buf, sizeof(short)*channels, dec, fin) == dec) {
            if (freq_shift)            
                freq_shift_complex_buf(buf, dec*channels, lo_i, lo_q);
            fwrite(buf, sizeof(short), channels, fout);
        }
    }
    else {
        uint8_t inbuf[dec*channels];
        short   outbuf[dec*channels];
        short   sam, i;
        
        while(fread(inbuf, sizeof(uint8_t)*channels, dec, fin) == dec) {
            for (i=0; i<dec*channels; i++) {
                assert((format == SIGNED_8BIT) || (format == UNSIGNED_8BIT));
                if (format == SIGNED_8BIT) {
                    sam = (short)inbuf[i];
                    sam <<= 8;
                } else {
                    sam = (short)inbuf[i] - 127;
                    sam <<= 8;
                }
                outbuf[i] = sam;
            }
            if (freq_shift)
                freq_shift_complex_buf(outbuf, dec*channels, lo_i, lo_q);
            fwrite(outbuf, sizeof(short), channels, fout);
        }

    }

    fclose(fout);
    fclose(fin);

    return 0;
}
                

void freq_shift_complex_buf(short buf[], int n, int lo_i[], int lo_q[]) {
    int i;

    for (i=0; i<n; i+=2) {
        /* update local osc recursion */

        lo_i[2] = -lo_i[0]; lo_q[2] = -lo_q[0];

        /* freq shift down input samples */

        int a = buf[i];
        int b = buf[i+1];
        int c = lo_i[2];
        int d = -lo_q[2];  /* conj LO as down shift */

        buf[i]   = a*c - b*d;
        buf[i+1] = b*c + a*d;

        //fprintf(stderr, "% d % d % 5d % 5d\n", lo_i[2], lo_q[2], buf[i], buf[i+1]);

        /* update LO memory */

        lo_i[0] = lo_i[1]; lo_i[1] = lo_i[2]; 
        lo_q[0] = lo_q[1]; lo_q[1] = lo_q[2]; 
    }
}