File: tlininterp.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 (153 lines) | stat: -rw-r--r-- 3,880 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
142
143
144
145
146
147
148
149
150
151
152
153
/*
   tlininterp.c
   David Rowe
   Jan 2017

   Fast linear interpolator for high oversam[pling rates.  Upsample
   with a decent filter first such that the signal is "low pass" wrt
   to the input sample rate.

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

*/

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

#define NBUF         1000
#define SIGNED_16BIT    0
#define SIGNED_8BIT     1

void display_help(void) {
    fprintf(stderr, "\nusage: tlininterp inputRawFile OutputRawFile OverSampleRatio [-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 16 bit input, complex signed 8 bit output\n");
    fprintf(stderr, "-f +Fs/4 freq shift\n\n");
}

int main(int argc, char *argv[]) {
    FILE       *fin, *fout;
    short       left[2], right[2], out[2*NBUF], i;
    float       oversample, t;
    int8_t      out_s8[2*NBUF];
    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);

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

    for (i=0; i<channels; i++)
        left[i] = 0;
    t = 0.0;
    int j = 0;
    while(fread(&right, sizeof(short)*channels, 1, fin) == 1) {
        while (t < 1.0) {

            for (i=0; i<channels; i++) {
                out[2*j+i] = (1.0 - t)*left[i] + t*right[i];
            }

            if (freq_shift) {

                /* update local osc recursion */

                lo_i[2] = -lo_i[0]; lo_q[2] = -lo_q[0];
                
                /* complex mixer to up-shift complex samples */

                int a = out[2*j];
                int b = out[2*j+1];
                int c = lo_i[2];
                int d = lo_q[2];

                out[2*j]   = a*c - b*d;
                out[2*j+1] = b*c + a*d;

                //fprintf(stderr, "% d % d % 5d % 5d\n", lo_i[2], lo_q[2], out[0], out[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]; 
            }

            /* once we have enough samples write to disk */

            j++;
            if (j == NBUF) {
                if (format == SIGNED_16BIT) {
                    fwrite(&out, sizeof(short)*channels, NBUF, fout);
                } else {
                    for (i=0; i<channels*NBUF; i++) {
                        out_s8[i] = out[i] >> 8;
                    }
                    fwrite(&out_s8, sizeof(int8_t)*channels, NBUF, fout);
                }
                j = 0;
            }

            t += 1.0/oversample;
        }
        
        t -= 1.0;
        for (i=0; i<channels; i++)
            left[i] = right[i];
    }

    /* write remaining samples to disk */

    if (format == SIGNED_16BIT) {
        fwrite(&out, sizeof(short), j, fout);
    } else {
        for (i=0; i<j; i++) {
            out_s8[i] = out[i] >> 8;
        }
        fwrite(&out_s8, sizeof(int8_t), j, fout);
    }

    fclose(fout);
    fclose(fin);

    return 0;
}