summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--qbuf.c62
-rw-r--r--qbuf.h22
-rw-r--r--qbufsplit.c33
-rw-r--r--qbufsplit.h10
-rw-r--r--resample.c90
-rw-r--r--resample.h14
-rw-r--r--v17dem.c121
-rw-r--r--v17tcm.h2
9 files changed, 240 insertions, 116 deletions
diff --git a/Makefile b/Makefile
index 45cc029..a697177 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@ all: main
*.o: Makefile
-main: main.o v17tcm.o v17mod.o bitsplit.o util.o interpol.o resample.o
+main: main.o v17tcm.o v17mod.o bitsplit.o util.o interpol.o resample.o qbuf.o qbufsplit.o
$(CC) -o $@ $^ $(LIBS)
clean:
diff --git a/qbuf.c b/qbuf.c
new file mode 100644
index 0000000..d225ce7
--- /dev/null
+++ b/qbuf.c
@@ -0,0 +1,62 @@
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "qbuf.h"
+
+void qbuf_init(struct qbuf *q, size_t length) {
+ assert(q && length);
+ memset(q, 0, sizeof(struct qbuf));
+
+ q->data = malloc(q->length = length*2);
+ assert(q->data);
+}
+
+void qbuf_done(struct qbuf *q) {
+ assert(q);
+ free(q->data);
+}
+
+static void move_to_front(struct qbuf *q) {
+ assert(q);
+
+ if (q->index+q->fill <= q->length/2)
+ return;
+
+ memmove(q->data, q->data+q->index, q->fill);
+ q->index = 0;
+}
+
+void* qbuf_push(struct qbuf *q, size_t *l) {
+ size_t m;
+ assert(q);
+
+ move_to_front(q);
+ m = q->length - q->fill - q->index;
+ *l = m;
+ return q->data + q->index + q->fill;
+}
+
+void qbuf_push_validate(struct qbuf *q, size_t l) {
+ assert(q);
+ q->fill += l;
+ assert(q->index+q->fill <= q->length);
+}
+
+void* qbuf_pull(struct qbuf *q, size_t *l) {
+ assert(q);
+ *l = q->fill;
+ return q->data + q->index;
+}
+
+void qbuf_pull_invalidate(struct qbuf *q, size_t l) {
+ assert(q);
+
+ assert(l <= q->fill);
+ q->fill -= l;
+ q->index += l;
+
+ assert(q->index+q->fill <= q->length);
+ if (!q->fill)
+ q->index = 0;
+}
diff --git a/qbuf.h b/qbuf.h
new file mode 100644
index 0000000..12d07b7
--- /dev/null
+++ b/qbuf.h
@@ -0,0 +1,22 @@
+#ifndef fooqbufhfoo
+#define fooqbufhfoo
+
+/* $Id$ */
+
+#include <sys/types.h>
+
+struct qbuf {
+ void *data;
+ size_t length, index, fill;
+};
+
+void qbuf_init(struct qbuf *q, size_t length);
+void qbuf_done(struct qbuf *q);
+
+void* qbuf_push(struct qbuf *q, size_t *l);
+void qbuf_push_validate(struct qbuf *q, size_t l);
+
+void* qbuf_pull(struct qbuf *q, size_t *l);
+void qbuf_pull_invalidate(struct qbuf *q, size_t l);
+
+#endif
diff --git a/qbufsplit.c b/qbufsplit.c
new file mode 100644
index 0000000..e03d1a3
--- /dev/null
+++ b/qbufsplit.c
@@ -0,0 +1,33 @@
+#include <assert.h>
+
+#include "qbufsplit.h"
+
+void qbuf_float_split(struct qbuf* sq, struct qbuf* dq1, struct qbuf*dq2) {
+ float *sp, *dp1, *dp2;
+ size_t sl, dl1, dl2;
+ size_t c = 0;
+
+ assert(sq && dq1 && dq2);
+
+ sp = qbuf_pull(sq, &sl);
+ dp1 = qbuf_push(dq1, &dl1);
+ dp2 = qbuf_push(dq2, &dl2);
+
+ assert(sp && dp1 && dp2);
+
+ while (sl >= 2*sizeof(float) && dl1 >= sizeof(float) && dl2 >= sizeof(float)) {
+
+ *(dp1++) = *(sp++);
+ *(dp2++) = *(sp++);
+
+ sl -= 2*sizeof(float);
+ dl1 -= sizeof(float);
+ dl2 -= sizeof(float);
+
+ c += sizeof(float);
+ }
+
+ qbuf_pull_invalidate(sq, c*2);
+ qbuf_push_validate(dq1, c);
+ qbuf_push_validate(dq2, c);
+}
diff --git a/qbufsplit.h b/qbufsplit.h
new file mode 100644
index 0000000..05762b4
--- /dev/null
+++ b/qbufsplit.h
@@ -0,0 +1,10 @@
+#ifndef fooqbufsplithfoo
+#define fooqbufsplithfoo
+
+/* $Id$ */
+
+#include "qbuf.h"
+
+void qbuf_float_split(struct qbuf* sq, struct qbuf* dq1, struct qbuf*dq2);
+
+#endif
diff --git a/resample.c b/resample.c
index ee9e540..3ed5c05 100644
--- a/resample.c
+++ b/resample.c
@@ -9,14 +9,6 @@
#define SINC_RADIUS 10
-struct resample_state {
- float delta;
-
- int sfreq, dfreq;
- struct interpol_state interpol;
-};
-
-
static int lcd(int a, int b) {
assert(a >= 1 && b >= 1);
@@ -44,13 +36,13 @@ void resample_done(struct resample_state *s) {
interpol_done(&s->interpol);
}
-void resample_get(struct resample_state *s, float* sp, int *sl, float *dp, int *dl, int sfreq, int dfreq) {
+void resample_get(struct resample_state *s, struct qbuf *sq, struct qbuf *dq, int sfreq, int dfreq) {
int di;
float x = 0;
-
- assert(s && sp && dp && sfreq > 0 && dfreq > 0);
- assert(*sl > 0);
- assert(*dl > 0);
+ float *sp, *dp;
+ size_t sl, dl;
+
+ assert(s && sq && dq && sfreq > 0 && dfreq > 0);
if (sfreq != s->sfreq || dfreq != s->dfreq) {
interpol_done(&s->interpol);
@@ -59,38 +51,50 @@ void resample_get(struct resample_state *s, float* sp, int *sl, float *dp, int *
s->dfreq = dfreq;
}
+ sp = qbuf_pull(sq, &sl);
+ dp = qbuf_push(dq, &dl);
+
+ assert(sp && dp && sl && dl);
+
+ sl /= sizeof(float);
+ dl /= sizeof(float);
+
di = 0;
- while (di < *dl) {
+ while (di < dl) {
x = (float) di*sfreq/dfreq + s->delta;
- if (x + SINC_RADIUS + 1 > *sl)
+ if (x + SINC_RADIUS + 1 > sl)
break;
- *(dp++) = interpol_get(&s->interpol, sp, *sl, x);
+ *(dp++) = interpol_get(&s->interpol, sp, sl, x);
di++;
}
- *dl = di;
+ qbuf_push_validate(dq, di*sizeof(float));
if (x >= SINC_RADIUS) {
- *sl = (int) (x - SINC_RADIUS);
- s->delta = x - *sl;
- } else
- *sl = 0;
+ int rn;
+ rn = (int) (x - SINC_RADIUS);
+ assert(rn <= sl);
+ s->delta = x - rn;
+ fprintf(stderr, "foo\n");
+ qbuf_pull_invalidate(sq, rn*sizeof(float));
+ fprintf(stderr, "bar\n");
+ }
}
#if (TEST == 7)
#define BUFSIZE (10*1024)
-void sinbuf(float *buf, int l) {
+static void sinbuf(float *buf, int l) {
static int i = 0;
for (; l > 0; l--, i = (i+1 == 100) ? 0 : i+1)
*(buf++) = sin(i*2*M_PI/100);
}
-void convbuf(float *buf, int l) {
+static void convbuf(float *buf, int l) {
int16_t *p = (int16_t*) buf;
for (; l > 0; l--, p+=2) {
float v = ((float) *p + (float) *(p+1))/0x7FFF;
@@ -102,44 +106,40 @@ void convbuf(float *buf, int l) {
int main(int argc, char *argv[]) {
struct resample_state resample;
- float inbuf[BUFSIZE];
- int total_n_inbuf = 0;
-
+ struct qbuf qi, qo;
+
if (argc > 1) {
stdin = fopen(argv[1], "r");
assert(stdin);
}
+ qbuf_init(&qi, BUFSIZE);
+ qbuf_init(&qo, BUFSIZE);
resample_init(&resample);
while (!feof(stdin)) {
- float outbuf[BUFSIZE];
- int n_outbuf = sizeof(outbuf) / sizeof(float);
- int n_inbuf, c;
-
+ int c;
+ float *ip, *up;
+ size_t il, ol;
+
fprintf(stderr, "LOOP!\n");
- c = fread(inbuf + total_n_inbuf, sizeof(float), sizeof(inbuf)/sizeof(float) - total_n_inbuf, stdin);
- convbuf(inbuf + total_n_inbuf, c);
- n_inbuf = (total_n_inbuf += c);
-
+ ip = qbuf_push(&qi, &il);
-
-/* sinbuf(inbuf + total_n_inbuf, sizeof(inbuf)/sizeof(float) - total_n_inbuf); */
-/* n_inbuf = total_n_inbuf = sizeof(inbuf)/sizeof(float); *\/ */
-
+ c = fread(ip, sizeof(float), il/sizeof(float), stdin);
+ convbuf(ip, c);
+ qbuf_push_validate(&qi, c*sizeof(float));
- resample_get(&resample, inbuf, &n_inbuf, outbuf, &n_outbuf, 44100, 8000);
-
- fwrite(outbuf, sizeof(float), n_outbuf, stdout);
+ resample_get(&resample, &qi, &qo, 44100, 8000);
- if (n_inbuf) {
- total_n_inbuf -= n_inbuf;
- memmove(inbuf, inbuf + n_inbuf, total_n_inbuf*sizeof(float));
- }
+ up = qbuf_pull(&qo, &ol);
+ fwrite(up, sizeof(float), ol/sizeof(float), stdout);
+ qbuf_pull_invalidate(&qo, ol);
}
resample_done(&resample);
+ qbuf_done(&qi);
+ qbuf_done(&qo);
return 0;
}
diff --git a/resample.h b/resample.h
index a2905b3..e1ce8e6 100644
--- a/resample.h
+++ b/resample.h
@@ -1,11 +1,21 @@
#ifndef fooresamplehfoo
#define fooresamplehfoo
-struct resample_state;
+/* $Id$ */
+
+#include "interpol.h"
+#include "qbuf.h"
+
+struct resample_state {
+ float delta;
+
+ int sfreq, dfreq;
+ struct interpol_state interpol;
+};
void resample_init(struct resample_state *s);
void resample_done(struct resample_state *s);
-void resample_get(struct resample_state *s, float* sp, int *sl, float *dp, int *dl, int sfreq, int dfreq);
+void resample_get(struct resample_state *s, struct qbuf *sq, struct qbuf *dq, int sfreq, int dfreq);
#endif
diff --git a/v17dem.c b/v17dem.c
index 4fad8f3..5f2e832 100644
--- a/v17dem.c
+++ b/v17dem.c
@@ -5,98 +5,83 @@
#define SAMPLE_RATE 8000
#define SAMPLES_MAX (SAMPLES_RATE*5) /* -> 5s buffer */
-#define SINC_RADIUS 10
-
struct v17dem_state {
- float *samples;
- int i_samples, n_samples;
-
- int sample_index;
-
int baud_rate;
int carrier_freq;
-
- struct interpol_state qam_interpol;
- struct interpol_state am_interpol;
-
- enum { COSINUS, SINUS } current;
- float *xam, *yam;
- int am_index;
+
+ struct resample_state qam_resample, xam_resample, yam_resample;
+ struct qbuf am_qbuf, xam_qbuf, yam_qbuf, xsymbols_qbuf, ysymbols_qbuf;
};
-void v17dem_init(struct v17dem_state *s) {
- assert(s);
+static int v17_7k2_symbol_decode(float x, float y) {
+ int row, col, i;
- memset(s, 0, sizeof(struct v17dem_state));
- s->baud_rate = INITIAL_BAUD_RATE;
- s->carrier_freq = INITIAL_CARRIER_FREQ;
- s->samples = malloc(sizeof(float) * SAMPLES_MAX * 2);
+ static const int v17_7k2_table[] = {
+ 3, 10, 5, 0,
+ 6, 15, 12, 9,
+ 13, 8, 11, 2,
+ 4, 1, 14, 7
+ };
- interpol_init(&s->qam_interpol, 9, SINC_RADIUS);
-}
+ col = (int) ((x+.6)/.4 +.5);
+ if (col < 0) col = 0;
+ if (col > 3) col = 3;
-void v17dem_done(struct v17dem_state *s) {
- assert(s);
+ row = (int) ((y+.6)/.4 +.5);
+ if (row < 0) row = 0;
+ if (row > 3) row = 3;
- free(s->samples);
- inertpol_done(&s->qam_interpol);
-}
-
-static void move_to_front(struct v17dem_state *s) {
- assert(s);
+ i = col*4+row;
- if (s->i_samples < SAMPLES_MAX)
- return;
+ assert(i >= 0 && i <= 15);
- memmove(s->samples, s->samples + s->i_samples, s->n_samples*sizeof(float));
- s->i_samples = 0;
+ return v17_7k2_table[i];
}
-void v17dem_push(struct v17dem_state *s, const float *p, int l){
- assert(s && p && l);
+void v17dem_init(struct v17dem_state *s) {
+ assert(s);
- assert(l <= SAMPLES_MAX-s->n_samples);
+ memset(s, 0, sizeof(struct v17dem_state));
+ s->baud_rate = INITIAL_BAUD_RATE;
+ s->carrier_freq = INITIAL_CARRIER_FREQ;
- move_to_front(s);
+ resample_init(&s->qam_resample);
+ resample_init(&s->xam_resample);
+ resample_init(&s->yam_resample);
- memcpy(s->samples + s->i_samples + s->n_samples, p, l*sizeof(float));
- s->n_samples += l;
+ qbuf_init(&s->am_qbuf, sizeof(float) * SAMPLES_MAX);
+ qbuf_init(&s->xam_qbuf, sizeof(float) * SAMPLES_MAX/2);
+ qbuf_init(&s->yam_qbuf, sizeof(float) * SAMPLES_MAX/2);
+ qbuf_init(&s->xsymbols_qbuf, sizeof(float) * SAMPLES_MAX/2);
+ qbuf_init(&s->ysymbols_qbuf, sizeof(float) * SAMPLES_MAX/2);
}
-int v17dem_pull(struct v17dem_state *s, uint8_t *p, int l){
- int alt = 0;
-
- assert(s && p && l);
+void v17dem_done(struct v17dem_state *s) {
+ assert(s);
- for (;;) {
- int n;
-
- /* Position für AM-Abtastung im Sample-Puffer berechnen -- alle 90° */
- float x = (SAMPLE_RATE/(4.0*s->carrier_freq) * s->am_index) - s->sample_index;
- assert(x >= 0);
+ resample_done(&s->qam_resample);
+ resample_done(&s->xam_resample);
+ resample_done(&s->yam_resample);
- /* AM-Abtatsung druchführen */
- if (s->current = COSINUS)
- am = s->xam;
- else
- am = s->yam;
+ qbuf_done(&s->am_qbuf);
+ qbuf_done(&s->xam_qbuf);
+ qbuf_done(&s->yam_qbuf);
+ qbuf_done(&s->xsymbols_qbuf);
+ qbuf_done(&s->ysymbols_qbuf);
+}
- am[s->am_index] = interpol_get(s->qam_interpol, s->samples + s->i_samples, s->n_samples, x);
+static int v17_decode(struct qbuf
- if (s->current == SINUS)
- s->am_index++;
-
- s->current = !s->current;
- /* Überflüssige Sampledaten killen */
+int v17dem_run(struct v17dem_state *s, struct qbuf *sample_qbuf, struct qbuf *byte_qbuf){
+ assert(s && sample_qbuf && byte_qbuf);
- n = (int) (x - (float) SINC_RADIUS*SAMPLE_RATE/s->carrier_freq/4);
+ resample_get(s->qam_resample, sample_qbuf, s->am_qbuf, SAMPLE_RATE, s->carrier_freq*4);
+ qbuf_float_split(s->am_qbuf, s->xam_qbuf, s->yam_qbuf);
+ resample_get(s->xam_resample, s->xam_qbuf, s->xsymbols_qbuf);
+ resample_get(s->yam_resample, s->yam_qbuf, s->ysymbols_qbuf);
- if (n > 0) {
- s->n_samples -= n;
- s->i_samples += n;
- s->sample_index += n;
- }
- }
+ v17_decode(s->xsymbols_qbuf, s->ysymbols_qbuf, byte_qbuf),
+
}
diff --git a/v17tcm.h b/v17tcm.h
index f126714..790c31f 100644
--- a/v17tcm.h
+++ b/v17tcm.h
@@ -1,6 +1,8 @@
#ifndef foov17tcmhfoo
#define foov17tcmhfoo
+/* $Id$ */
+
#include <inttypes.h>
struct v17tcm_state {