From 783b56d54788f177881d68ae2ec7a7cb4bb38ac4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 18 Apr 2004 01:35:53 +0000 Subject: Initial commit git-svn-id: file:///home/lennart/svn/public/vfax/trunk@3 541b366f-4dd8-0310-ae39-b2612fd50714 --- resample.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 resample.c (limited to 'resample.c') 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 +#include +#include +#include +#include + +#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 -- cgit