/* * Talkbox * * This module is ported from the mdaTalkbox plugin by Paul Kellet * (maxim digital audio). * * More information on his plugins and the original code can be found here: * * http://mda.smartelectronix.com/ * */ #include #include #include #include "soundpipe.h" #ifndef TWO_PI #define TWO_PI 6.28318530717958647692528676655901 #endif #define ORD_MAX 50 static void lpc_durbin(SPFLOAT *r, int p, float *k, float *g) { int i, j; SPFLOAT a[ORD_MAX], at[ORD_MAX], e=r[0]; for(i=0; i<=p; i++) a[i] = at[i] = 0.0f; for(i=1; i<=p; i++) { k[i] = -r[i]; for(j=1; j 0.995f) k[i] = 0.995f; else if(k[i] < -0.995f) k[i] = -.995f; } for(i=0; i0; j--) { x -= k[j] * z[j-1]; z[j] = z[j-1] + k[j] * x; } buf[i] = z[0] = x; /* output buf[] will be windowed elsewhere */ } } int sp_talkbox_create(sp_talkbox **p) { *p = malloc(sizeof(sp_talkbox)); return SP_OK; } int sp_talkbox_destroy(sp_talkbox **p) { free(*p); return SP_OK; } int sp_talkbox_init(sp_data *sp, sp_talkbox *p) { uint32_t n; p->quality = 1.f; p->N = 1; p->K = 0; n = (uint32_t)(0.01633f * sp->sr); if(n > SP_TALKBOX_BUFMAX) n = SP_TALKBOX_BUFMAX; /* calculate hanning window */ if(n != p->N) { SPFLOAT dp; SPFLOAT pos; p->N = n; dp = TWO_PI / (SPFLOAT)p->N; pos = 0.0f; for(n=0; n < p->N; n++) { p->window[n] = 0.5f - 0.5f * (SPFLOAT)cos(pos); pos += dp; } } /* zero out variables and buffers */ p->pos = p->K = 0; p->emphasis = 0.0f; p->FX = 0; p->u0 = p->u1 = p->u2 = p->u3 = p->u4 = 0.0f; p->d0 = p->d1 = p->d2 = p->d3 = p->d4 = 0.0f; memset(p->buf0, 0, SP_TALKBOX_BUFMAX * sizeof(SPFLOAT)); memset(p->buf1, 0, SP_TALKBOX_BUFMAX * sizeof(SPFLOAT)); memset(p->car0, 0, SP_TALKBOX_BUFMAX * sizeof(SPFLOAT)); memset(p->car1, 0, SP_TALKBOX_BUFMAX * sizeof(SPFLOAT)); return SP_OK; } int sp_talkbox_compute(sp_data *sp, sp_talkbox *t, SPFLOAT *src, SPFLOAT *exc, SPFLOAT *out) { int32_t p0=t->pos, p1 = (t->pos + t->N/2) % t->N; SPFLOAT e=t->emphasis, w, o, x, fx=t->FX; SPFLOAT p, q, h0=0.3f, h1=0.77f; SPFLOAT den; t->O = (uint32_t)((0.0001f + 0.0004f * t->quality) * sp->sr); o = *src; x = *exc; p = t->d0 + h0 * x; t->d0 = t->d1; t->d1 = x - h0 * p; q = t->d2 + h1 * t->d4; t->d2 = t->d3; t->d3 = t->d4 - h1 * q; t->d4 = x; x = p + q; if(t->K++) { t->K = 0; /* carrier input */ t->car0[p0] = t->car1[p1] = x; /* 6dB/oct pre-emphasis */ x = o - e; e = o; /* 50% overlapping hanning windows */ w = t->window[p0]; fx = t->buf0[p0] * w; t->buf0[p0] = x * w; if(++p0 >= t->N) { lpc(t->buf0, t->car0, t->N, t->O); p0 = 0; } w = 1.0f - w; fx += t->buf1[p1] * w; t->buf1[p1] = x * w; if(++p1 >= t->N) { lpc(t->buf1, t->car1, t->N, t->O); } } p = t->u0 + h0 * fx; t->u0 = t->u1; t->u1 = fx - h0 * p; q = t->u2 + h1 * t->u4; t->u2 = t->u3; t->u3 = t->u4 - h1 * q; t->u4 = fx; x = p + q; o = x * 0.5; *out = o; t->emphasis = e; t->pos = p0; t->FX = fx; den = 1.0e-10f; /* anti-denormal */ if(fabs(t->d0) < den) t->d0 = 0.0f; if(fabs(t->d1) < den) t->d1 = 0.0f; if(fabs(t->d2) < den) t->d2 = 0.0f; if(fabs(t->d3) < den) t->d3 = 0.0f; if(fabs(t->u0) < den) t->u0 = 0.0f; if(fabs(t->u1) < den) t->u1 = 0.0f; if(fabs(t->u2) < den) t->u2 = 0.0f; if(fabs(t->u3) < den) t->u3 = 0.0f; return SP_OK; }