kopia lustrzana https://github.com/xdsopl/robot36
moved ddc to own files
rodzic
04e68c262f
commit
07236f86cd
2
Makefile
2
Makefile
|
@ -22,5 +22,5 @@ clean:
|
||||||
|
|
||||||
encode: encode.o mmap_file.o
|
encode: encode.o mmap_file.o
|
||||||
|
|
||||||
decode: decode.o mmap_file.o pcm.o wav.o alsa.o window.o
|
decode: decode.o mmap_file.o pcm.o wav.o alsa.o window.o ddc.o
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <complex.h>
|
||||||
|
#include "window.h"
|
||||||
|
#include "ddc.h"
|
||||||
|
|
||||||
|
void do_ddc(ddc_t *ddc, float *input, float complex *output)
|
||||||
|
{
|
||||||
|
int in = 0;
|
||||||
|
ddc->s[ddc->last] = input[in++];
|
||||||
|
ddc->last = (ddc->last + 1) < ddc->samples ? ddc->last + 1 : 0;
|
||||||
|
ddc->skip += ddc->L;
|
||||||
|
// this works only for L <= M
|
||||||
|
for (int k = 0; k < ddc->L; k++) {
|
||||||
|
float complex sum = 0.0;
|
||||||
|
for (int i = ddc->offset, j = ddc->last; i < ddc->taps; i += ddc->L) {
|
||||||
|
sum += ddc->b[i] * ddc->s[j];
|
||||||
|
j += j ? - 1 : ddc->samples - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ddc->offset = (ddc->offset + ddc->M) % ddc->L;
|
||||||
|
|
||||||
|
while (ddc->skip < ddc->M) {
|
||||||
|
ddc->s[ddc->last] = input[in++];
|
||||||
|
ddc->last = (ddc->last + 1) < ddc->samples ? ddc->last + 1 : 0;
|
||||||
|
ddc->skip += ddc->L;
|
||||||
|
}
|
||||||
|
|
||||||
|
ddc->skip %= ddc->M;
|
||||||
|
output[k] = ddc->osc * sum;
|
||||||
|
ddc->osc *= ddc->d;
|
||||||
|
// ddc->osc /= cabsf(ddc->osc); // not really needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ddc_t *alloc_ddc(float freq, float bw, float step, int taps, int L, int M, float (*window)(float, float))
|
||||||
|
{
|
||||||
|
float lstep = step / (float)L;
|
||||||
|
float ostep = step * (float)M / (float)L;
|
||||||
|
ddc_t *ddc = malloc(sizeof(ddc_t));
|
||||||
|
ddc->taps = taps;
|
||||||
|
ddc->samples = (taps + L - 1) / L;
|
||||||
|
ddc->b = malloc(sizeof(float complex) * ddc->taps);
|
||||||
|
ddc->s = malloc(sizeof(float) * ddc->samples);
|
||||||
|
ddc->osc = I;
|
||||||
|
ddc->d = cexpf(-I * 2.0 * M_PI * freq * ostep);
|
||||||
|
ddc->offset = 0;
|
||||||
|
ddc->last = 0;
|
||||||
|
ddc->skip = 0;
|
||||||
|
ddc->L = L;
|
||||||
|
ddc->M = M;
|
||||||
|
for (int i = 0; i < ddc->samples; i++)
|
||||||
|
ddc->s[i] = 0.0;
|
||||||
|
float sum = 0.0;
|
||||||
|
for (int i = 0; i < ddc->taps; i++) {
|
||||||
|
float N = (float)ddc->taps;
|
||||||
|
float n = (float)i;
|
||||||
|
float x = n - (N - 1.0) / 2.0;
|
||||||
|
float l = 2.0 * M_PI * bw * lstep;
|
||||||
|
float w = window(n, ddc->taps);
|
||||||
|
float h = 0.0 == x ? l / M_PI : sinf(l * x) / (x * M_PI);
|
||||||
|
float b = w * h;
|
||||||
|
sum += b;
|
||||||
|
complex float o = cexpf(I * 2.0 * M_PI * freq * lstep * n);
|
||||||
|
ddc->b[i] = b * o * (float)L;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < ddc->taps; i++)
|
||||||
|
ddc->b[i] /= sum;
|
||||||
|
return ddc;
|
||||||
|
}
|
||||||
|
void free_ddc(ddc_t *ddc)
|
||||||
|
{
|
||||||
|
free(ddc->b);
|
||||||
|
free(ddc->s);
|
||||||
|
free(ddc);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
|
||||||
|
#ifndef DDC_H
|
||||||
|
#define DDC_H
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float complex *b;
|
||||||
|
float *s;
|
||||||
|
float complex osc;
|
||||||
|
float complex d;
|
||||||
|
int offset;
|
||||||
|
int skip;
|
||||||
|
int last;
|
||||||
|
int taps;
|
||||||
|
int samples;
|
||||||
|
int L;
|
||||||
|
int M;
|
||||||
|
} ddc_t;
|
||||||
|
|
||||||
|
void do_ddc(ddc_t *, float *, float complex *);
|
||||||
|
ddc_t *alloc_ddc(float, float, float, int, int, int, float (*)(float, float));
|
||||||
|
void free_ddc(ddc_t *);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
86
decode.c
86
decode.c
|
@ -8,7 +8,7 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "mmap_file.h"
|
#include "mmap_file.h"
|
||||||
#include "pcm.h"
|
#include "pcm.h"
|
||||||
#include "window.h"
|
#include "ddc.h"
|
||||||
|
|
||||||
float lerp(float a, float b, float x)
|
float lerp(float a, float b, float x)
|
||||||
{
|
{
|
||||||
|
@ -31,90 +31,6 @@ float limit(float min, float max, float x)
|
||||||
return tmp > max ? max : tmp;
|
return tmp > max ? max : tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
float complex *b;
|
|
||||||
float *s;
|
|
||||||
float complex osc;
|
|
||||||
float complex d;
|
|
||||||
int offset;
|
|
||||||
int skip;
|
|
||||||
int last;
|
|
||||||
int taps;
|
|
||||||
int samples;
|
|
||||||
int L;
|
|
||||||
int M;
|
|
||||||
} ddc_t;
|
|
||||||
|
|
||||||
void do_ddc(ddc_t *ddc, float *input, float complex *output)
|
|
||||||
{
|
|
||||||
int in = 0;
|
|
||||||
ddc->s[ddc->last] = input[in++];
|
|
||||||
ddc->last = (ddc->last + 1) < ddc->samples ? ddc->last + 1 : 0;
|
|
||||||
ddc->skip += ddc->L;
|
|
||||||
// this works only for L <= M
|
|
||||||
for (int k = 0; k < ddc->L; k++) {
|
|
||||||
float complex sum = 0.0;
|
|
||||||
for (int i = ddc->offset, j = ddc->last; i < ddc->taps; i += ddc->L) {
|
|
||||||
sum += ddc->b[i] * ddc->s[j];
|
|
||||||
j += j ? - 1 : ddc->samples - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ddc->offset = (ddc->offset + ddc->M) % ddc->L;
|
|
||||||
|
|
||||||
while (ddc->skip < ddc->M) {
|
|
||||||
ddc->s[ddc->last] = input[in++];
|
|
||||||
ddc->last = (ddc->last + 1) < ddc->samples ? ddc->last + 1 : 0;
|
|
||||||
ddc->skip += ddc->L;
|
|
||||||
}
|
|
||||||
|
|
||||||
ddc->skip %= ddc->M;
|
|
||||||
output[k] = ddc->osc * sum;
|
|
||||||
ddc->osc *= ddc->d;
|
|
||||||
// ddc->osc /= cabsf(ddc->osc); // not really needed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ddc_t *alloc_ddc(float freq, float bw, float step, int taps, int L, int M, float (*window)(float, float))
|
|
||||||
{
|
|
||||||
float lstep = step / (float)L;
|
|
||||||
float ostep = step * (float)M / (float)L;
|
|
||||||
ddc_t *ddc = malloc(sizeof(ddc_t));
|
|
||||||
ddc->taps = taps;
|
|
||||||
ddc->samples = (taps + L - 1) / L;
|
|
||||||
ddc->b = malloc(sizeof(float complex) * ddc->taps);
|
|
||||||
ddc->s = malloc(sizeof(float) * ddc->samples);
|
|
||||||
ddc->osc = I;
|
|
||||||
ddc->d = cexpf(-I * 2.0 * M_PI * freq * ostep);
|
|
||||||
ddc->offset = 0;
|
|
||||||
ddc->last = 0;
|
|
||||||
ddc->skip = 0;
|
|
||||||
ddc->L = L;
|
|
||||||
ddc->M = M;
|
|
||||||
for (int i = 0; i < ddc->samples; i++)
|
|
||||||
ddc->s[i] = 0.0;
|
|
||||||
float sum = 0.0;
|
|
||||||
for (int i = 0; i < ddc->taps; i++) {
|
|
||||||
float N = (float)ddc->taps;
|
|
||||||
float n = (float)i;
|
|
||||||
float x = n - (N - 1.0) / 2.0;
|
|
||||||
float l = 2.0 * M_PI * bw * lstep;
|
|
||||||
float w = window(n, ddc->taps);
|
|
||||||
float h = 0.0 == x ? l / M_PI : sinf(l * x) / (x * M_PI);
|
|
||||||
float b = w * h;
|
|
||||||
sum += b;
|
|
||||||
complex float o = cexpf(I * 2.0 * M_PI * freq * lstep * n);
|
|
||||||
ddc->b[i] = b * o * (float)L;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < ddc->taps; i++)
|
|
||||||
ddc->b[i] /= sum;
|
|
||||||
return ddc;
|
|
||||||
}
|
|
||||||
void free_ddc(ddc_t *ddc)
|
|
||||||
{
|
|
||||||
free(ddc->b);
|
|
||||||
free(ddc->s);
|
|
||||||
free(ddc);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float *s;
|
float *s;
|
||||||
int last;
|
int last;
|
||||||
|
|
Ładowanie…
Reference in New Issue