summaryrefslogtreecommitdiffstats
path: root/resample.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2004-04-18 01:35:53 +0000
committerLennart Poettering <lennart@poettering.net>2004-04-18 01:35:53 +0000
commit783b56d54788f177881d68ae2ec7a7cb4bb38ac4 (patch)
tree77555207fa13c137e0c8dab8726f2ed96538e075 /resample.c
parentf069d236c79a7cb89542eba5ddc454d03ead5394 (diff)
Initial commit
git-svn-id: file:///home/lennart/svn/public/vfax/trunk@3 541b366f-4dd8-0310-ae39-b2612fd50714
Diffstat (limited to 'resample.c')
-rw-r--r--resample.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/resample.c b/resample.c
new file mode 100644
index 0000000..ee9e540
--- /dev/null
+++ b/resample.c
@@ -0,0 +1,147 @@
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+#include <inttypes.h>
+
+#include "resample.h"
+#include "interpol.h"
+
+#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);
+
+ while (a != b) {
+ while (a > b) {
+ a = a-b;
+ }
+
+ while (b > a) {
+ b = b-a;
+ }
+ }
+
+ return a;
+}
+
+void resample_init(struct resample_state *s) {
+ assert(s);
+ memset(s, 0, sizeof(struct resample_state));
+ s->sfreq = s->dfreq = -1;
+}
+
+void resample_done(struct resample_state *s) {
+ assert(s);
+ interpol_done(&s->interpol);
+}
+
+void resample_get(struct resample_state *s, float* sp, int *sl, float *dp, int *dl, int sfreq, int dfreq) {
+ int di;
+ float x = 0;
+
+ assert(s && sp && dp && sfreq > 0 && dfreq > 0);
+ assert(*sl > 0);
+ assert(*dl > 0);
+
+ if (sfreq != s->sfreq || dfreq != s->dfreq) {
+ interpol_done(&s->interpol);
+ interpol_init(&s->interpol, dfreq/lcd(sfreq,dfreq), SINC_RADIUS);
+ s->sfreq = sfreq;
+ s->dfreq = dfreq;
+ }
+
+ di = 0;
+ while (di < *dl) {
+ x = (float) di*sfreq/dfreq + s->delta;
+
+ if (x + SINC_RADIUS + 1 > *sl)
+ break;
+
+ *(dp++) = interpol_get(&s->interpol, sp, *sl, x);
+ di++;
+ }
+
+ *dl = di;
+
+ if (x >= SINC_RADIUS) {
+ *sl = (int) (x - SINC_RADIUS);
+ s->delta = x - *sl;
+ } else
+ *sl = 0;
+}
+
+#if (TEST == 7)
+
+#define BUFSIZE (10*1024)
+
+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) {
+ int16_t *p = (int16_t*) buf;
+ for (; l > 0; l--, p+=2) {
+ float v = ((float) *p + (float) *(p+1))/0x7FFF;
+ *(buf++) = (v < -1) ? -1 : ((v > 1) ? 1 : v);
+ }
+
+}
+
+
+int main(int argc, char *argv[]) {
+ struct resample_state resample;
+ float inbuf[BUFSIZE];
+ int total_n_inbuf = 0;
+
+ if (argc > 1) {
+ stdin = fopen(argv[1], "r");
+ assert(stdin);
+ }
+
+ resample_init(&resample);
+
+ while (!feof(stdin)) {
+ float outbuf[BUFSIZE];
+ int n_outbuf = sizeof(outbuf) / sizeof(float);
+ int n_inbuf, c;
+
+ 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);
+
+
+
+/* sinbuf(inbuf + total_n_inbuf, sizeof(inbuf)/sizeof(float) - total_n_inbuf); */
+/* n_inbuf = total_n_inbuf = sizeof(inbuf)/sizeof(float); *\/ */
+
+
+ resample_get(&resample, inbuf, &n_inbuf, outbuf, &n_outbuf, 44100, 8000);
+
+ fwrite(outbuf, sizeof(float), n_outbuf, stdout);
+
+ if (n_inbuf) {
+ total_n_inbuf -= n_inbuf;
+ memmove(inbuf, inbuf + n_inbuf, total_n_inbuf*sizeof(float));
+ }
+ }
+
+ resample_done(&resample);
+
+ return 0;
+}
+
+#endif