-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathchirp_downconvert.c
148 lines (135 loc) · 3.42 KB
/
chirp_downconvert.c
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
#include "chirp_downconvert.h"
#include <stdint.h>
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
void complex_mul(complex_float *a, complex_float *res)
{
float tmp;
//res = (a.re + 1i*a.im)*(res.re + 1i*res.im)
//res.re = (a.re*res.re) - a.im*res*im
//res.im = (a.im*res.re) + a.re*res.im
tmp = res->re;
res->re = a->re*tmp - a->im*res->im;
res->im = a->im*tmp + a->re*res->im;
}
void complex_add(complex_float *a, complex_float *res)
{
res->re = res->re + a->re;
res->im = res->im + a->im;
}
void add_and_advance_phasor(double chirpt, complex_float *sintab, int tabl, complex_float *a, complex_float *mean, double f0, double rate)
{
complex_float tmp;
// this is faster
int64_t idx = (int64_t)(tabl*(f0+0.5*rate*chirpt)*chirpt) % tabl;
if(idx < 0)
idx = tabl+idx;
tmp = sintab[idx];
complex_mul(a, &tmp);
complex_add(&tmp, mean);
}
void test(complex_float *sintab, int n)
{
for(int i=0; i<n ; i++)
{
printf("%d %f %f\n",i,sintab[i].re,sintab[i].im);
}
}
struct arg_struct {
double chirpt;
double dt;
complex_float *sintab;
int tabl;
complex_float *in;
complex_float *out_buffer;
int n_out;
int dec;
int dec2;
double f0;
double rate;
float *wfun;
int rank;
int size;
};
void *consume_one(void *args)
{
struct arg_struct *a = args;
double chirpt=a->chirpt;
double dt=a->dt;
complex_float *sintab=a->sintab;
complex_float *in=a->in;
complex_float *out_buffer=a->out_buffer;
int n_out = a->n_out;
int tabl = a->tabl;
int dec=a->dec;
int dec2=a->dec2;
double f0=a->f0;
double rate=a->rate;
float *wfun=a->wfun;
int rank=a->rank;
int size=a->size;
/*
parallel consume
*/
// complex_float *in = (complex_float *) input_items[0];
complex_float out_sample;
complex_float tmp;
int i;
double chirpt0;
chirpt0=chirpt;
for(int out_idx=rank; out_idx<n_out; out_idx+=size)
{
out_sample.re=0.0;out_sample.im=0.0;
chirpt=((double)dec*out_idx)*dt + chirpt0;
i=out_idx*dec;
/*
better lpf with a user defined window function (e.g., windowed ideal LPF)
*/
for(int dec_idx=0; dec_idx<dec2; dec_idx++)
{
/* dechirp and low-pass filter by averaging */
/* window function to improve filter peformance */
tmp=in[i];
tmp.re=tmp.re*wfun[dec_idx];
tmp.im=tmp.im*wfun[dec_idx];
add_and_advance_phasor(chirpt, sintab, tabl, &tmp, &out_sample, f0, rate);
chirpt+=dt;
i++;
}
out_buffer[out_idx]=out_sample;
}
pthread_exit(NULL);
return(NULL);
}
void consume(double chirpt, double dt, complex_float *sintab, int tabl, complex_float *in, complex_float *out_buffer, int n_out, int dec, int dec2, double f0, double rate, float *wfun, int n_threads)
{
pthread_t *proc_threads;
struct arg_struct *a;
a=(struct arg_struct *)malloc(sizeof(struct arg_struct)*n_threads);
proc_threads=(pthread_t *)malloc(sizeof(pthread_t)*n_threads);
for(int i=0; i<n_threads; i++)
{
a[i].chirpt=chirpt;
a[i].dt=dt;
a[i].sintab=sintab;
a[i].tabl=tabl;
a[i].in=in;
a[i].out_buffer=out_buffer;
a[i].n_out=n_out;
a[i].dec=dec;
a[i].dec2=dec2;
a[i].f0=f0;
a[i].rate=rate;
a[i].wfun=wfun;
a[i].rank=i;
a[i].size=n_threads;
pthread_create(&proc_threads[i], NULL, consume_one, (void *)&a[i]);
}
for(int i=0; i<n_threads; i++)
{
pthread_join(proc_threads[i],NULL);
}
free(a);
free(proc_threads);
}