Showing the changes to LEAF/Src_cpp/leaf-vocoder.cpp (1 of 147 files). Show all
Unified · Split
| @@ -0,0 +1,386 @@ | ||
| 1 | +/* | |
| 2 | + ============================================================================== | |
| 3 | + | |
| 4 | + LEAFInstrument.c | |
| 5 | + Created: 20 Jan 2017 12:01:54pm | |
| 6 | + Author: Michael R Mulshine | |
| 7 | + | |
| 8 | + ============================================================================== | |
| 9 | +*/ | |
| 10 | + | |
| 11 | +#if _WIN32 || _WIN64 | |
| 12 | + | |
| 13 | +#include "..\Inc\leaf-vocoder.h" | |
| 14 | +#include "..\leaf.h" | |
| 15 | + | |
| 16 | +#else | |
| 17 | + | |
| 18 | +#include "../Inc/leaf-vocoder.h" | |
| 19 | +#include "../leaf.h" | |
| 20 | + | |
| 21 | +#endif | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | |
| 26 | + * | |
| 27 | + * | |
| 28 | + * | |
| 29 | + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
| 30 | + | |
| 31 | +void tTalkbox_init(tTalkbox* const v) | |
| 32 | +{ | |
| 33 | + v->param[0] = 0.5f; //wet | |
| 34 | + v->param[1] = 0.0f; //dry | |
| 35 | + v->param[2] = 0; // Swap | |
| 36 | + v->param[3] = 1.0f; //quality | |
| 37 | + | |
| 38 | + tTalkbox_update(v); | |
| 39 | +} | |
| 40 | + | |
| 41 | +void tTalkbox_free(tTalkbox* const v) | |
| 42 | +{ | |
| 43 | + leaf_free(v); | |
| 44 | +} | |
| 45 | + | |
| 46 | +void tTalkbox_update(tTalkbox* const v) ///update internal parameters... | |
| 47 | +{ | |
| 48 | + float fs = leaf.sampleRate; | |
| 49 | + if(fs < 8000.0f) fs = 8000.0f; | |
| 50 | + if(fs > 96000.0f) fs = 96000.0f; | |
| 51 | + | |
| 52 | + int32_t n = (int32_t)(0.01633f * fs); | |
| 53 | + if(n > TALKBOX_BUFFER_LENGTH) n = TALKBOX_BUFFER_LENGTH; | |
| 54 | + | |
| 55 | + //O = (VstInt32)(0.0005f * fs); | |
| 56 | + v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * fs); | |
| 57 | + | |
| 58 | + if(n != v->N) //recalc hanning window | |
| 59 | + { | |
| 60 | + v->N = n; | |
| 61 | + float dp = TWO_PI / v->N; | |
| 62 | + float p = 0.0f; | |
| 63 | + for(n=0; n<v->N; n++) | |
| 64 | + { | |
| 65 | + v->window[n] = 0.5f - 0.5f * cosf(p); | |
| 66 | + p += dp; | |
| 67 | + } | |
| 68 | + } | |
| 69 | + v->wet = 0.5f * v->param[0] * v->param[0]; | |
| 70 | + v->dry = 2.0f * v->param[1] * v->param[1]; | |
| 71 | +} | |
| 72 | + | |
| 73 | +void tTalkbox_suspend(tTalkbox* const v) ///clear any buffers... | |
| 74 | +{ | |
| 75 | + v->pos = v->K = 0; | |
| 76 | + v->emphasis = 0.0f; | |
| 77 | + v->FX = 0; | |
| 78 | + | |
| 79 | + v->u0 = v->u1 = v->u2 = v->u3 = v->u4 = 0.0f; | |
| 80 | + v->d0 = v->d1 = v->d2 = v->d3 = v->d4 = 0.0f; | |
| 81 | + | |
| 82 | + for (int32_t i = 0; i < TALKBOX_BUFFER_LENGTH; i++) | |
| 83 | + { | |
| 84 | + v->buf0[i] = 0; | |
| 85 | + v->buf1[i] = 0; | |
| 86 | + v->car0[i] = 0; | |
| 87 | + v->car1[i] = 0; | |
| 88 | + } | |
| 89 | +} | |
| 90 | + | |
| 91 | + | |
| 92 | +#define ORD_MAX 100 // Was 50. Increasing this gets rid of glitchiness, lowering it breaks it; not sure how it affects performance | |
| 93 | +void tTalkbox_lpc(float *buf, float *car, int32_t n, int32_t o) | |
| 94 | +{ | |
| 95 | + float z[ORD_MAX], r[ORD_MAX], k[ORD_MAX], G, x; | |
| 96 | + int32_t i, j, nn=n; | |
| 97 | + | |
| 98 | + for(j=0; j<=o; j++, nn--) //buf[] is already emphasized and windowed | |
| 99 | + { | |
| 100 | + z[j] = r[j] = 0.0f; | |
| 101 | + for(i=0; i<nn; i++) r[j] += buf[i] * buf[i+j]; //autocorrelation | |
| 102 | + } | |
| 103 | + r[0] *= 1.001f; //stability fix | |
| 104 | + | |
| 105 | + float min = 0.00001f; | |
| 106 | + if(r[0] < min) { for(i=0; i<n; i++) buf[i] = 0.0f; return; } | |
| 107 | + | |
| 108 | + tTalkbox_lpcDurbin(r, o, k, &G); //calc reflection coeffs | |
| 109 | + | |
| 110 | + for(i=0; i<=o; i++) | |
| 111 | + { | |
| 112 | + if(k[i] > 0.995f) k[i] = 0.995f; else if(k[i] < -0.995f) k[i] = -.995f; | |
| 113 | + } | |
| 114 | + | |
| 115 | + for(i=0; i<n; i++) | |
| 116 | + { | |
| 117 | + x = G * car[i]; | |
| 118 | + for(j=o; j>0; j--) //lattice filter | |
| 119 | + { | |
| 120 | + x -= k[j] * z[j-1]; | |
| 121 | + z[j] = z[j-1] + k[j] * x; | |
| 122 | + } | |
| 123 | + buf[i] = z[0] = x; //output buf[] will be windowed elsewhere | |
| 124 | + } | |
| 125 | +} | |
| 126 | + | |
| 127 | + | |
| 128 | +void tTalkbox_lpcDurbin(float *r, int p, float *k, float *g) | |
| 129 | +{ | |
| 130 | + int i, j; | |
| 131 | + float a[ORD_MAX], at[ORD_MAX], e=r[0]; | |
| 132 | + | |
| 133 | + for(i=0; i<=p; i++) a[i] = at[i] = 0.0f; //probably don't need to clear at[] or k[] | |
| 134 | + | |
| 135 | + for(i=1; i<=p; i++) | |
| 136 | + { | |
| 137 | + k[i] = -r[i]; | |
| 138 | + | |
| 139 | + for(j=1; j<i; j++) | |
| 140 | + { | |
| 141 | + at[j] = a[j]; | |
| 142 | + k[i] -= a[j] * r[i-j]; | |
| 143 | + } | |
| 144 | + if(fabs(e) < 1.0e-20f) { e = 0.0f; break; } | |
| 145 | + k[i] /= e; // This might be costing us | |
| 146 | + | |
| 147 | + a[i] = k[i]; | |
| 148 | + for(j=1; j<i; j++) a[j] = at[j] + k[i] * at[i-j]; | |
| 149 | + | |
| 150 | + e *= 1.0f - k[i] * k[i]; | |
| 151 | + } | |
| 152 | + | |
| 153 | + if(e < 1.0e-20f) e = 0.0f; | |
| 154 | + *g = sqrtf(e); | |
| 155 | +} | |
| 156 | + | |
| 157 | +float tTalkbox_tick(tTalkbox* const v, float synth, float voice) | |
| 158 | +{ | |
| 159 | + | |
| 160 | + int32_t p0=v->pos, p1 = (v->pos + v->N/2) % v->N; | |
| 161 | + float e=v->emphasis, w, o, x, dr, fx=v->FX; | |
| 162 | + float p, q, h0=0.3f, h1=0.77f; | |
| 163 | + | |
| 164 | + o = voice; | |
| 165 | + x = synth; | |
| 166 | + | |
| 167 | + dr = o; | |
| 168 | + | |
| 169 | + p = v->d0 + h0 * x; v->d0 = v->d1; v->d1 = x - h0 * p; | |
| 170 | + q = v->d2 + h1 * v->d4; v->d2 = v->d3; v->d3 = v->d4 - h1 * q; | |
| 171 | + v->d4 = x; | |
| 172 | + x = p + q; | |
| 173 | + | |
| 174 | + if(v->K++) | |
| 175 | + { | |
| 176 | + v->K = 0; | |
| 177 | + | |
| 178 | + v->car0[p0] = v->car1[p1] = x; //carrier input | |
| 179 | + | |
| 180 | + x = o - e; e = o; //6dB/oct pre-emphasis | |
| 181 | + | |
| 182 | + w = v->window[p0]; fx = v->buf0[p0] * w; v->buf0[p0] = x * w; //50% overlapping hanning windows | |
| 183 | + if(++p0 >= v->N) { tTalkbox_lpc(v->buf0, v->car0, v->N, v->O); p0 = 0; } | |
| 184 | + | |
| 185 | + w = 1.0f - w; fx += v->buf1[p1] * w; v->buf1[p1] = x * w; | |
| 186 | + if(++p1 >= v->N) { tTalkbox_lpc(v->buf1, v->car1, v->N, v->O); p1 = 0; } | |
| 187 | + } | |
| 188 | + | |
| 189 | + p = v->u0 + h0 * fx; v->u0 = v->u1; v->u1 = fx - h0 * p; | |
| 190 | + q = v->u2 + h1 * v->u4; v->u2 = v->u3; v->u3 = v->u4 - h1 * q; | |
| 191 | + v->u4 = fx; | |
| 192 | + x = p + q; | |
| 193 | + | |
| 194 | + o = x; | |
| 195 | + | |
| 196 | + v->emphasis = e; | |
| 197 | + v->pos = p0; | |
| 198 | + v->FX = fx; | |
| 199 | + | |
| 200 | + float den = 1.0e-10f; //(float)pow(10.0f, -10.0f * param[4]); | |
| 201 | + if(fabs(v->d0) < den) v->d0 = 0.0f; //anti-denormal (doesn't seem necessary but P4?) | |
| 202 | + if(fabs(v->d1) < den) v->d1 = 0.0f; | |
| 203 | + if(fabs(v->d2) < den) v->d2 = 0.0f; | |
| 204 | + if(fabs(v->d3) < den) v->d3 = 0.0f; | |
| 205 | + if(fabs(v->u0) < den) v->u0 = 0.0f; | |
| 206 | + if(fabs(v->u1) < den) v->u1 = 0.0f; | |
| 207 | + if(fabs(v->u2) < den) v->u2 = 0.0f; | |
| 208 | + if(fabs(v->u3) < den) v->u3 = 0.0f; | |
| 209 | + return o; | |
| 210 | +} | |
| 211 | + | |
| 212 | +void tTalkbox_setQuality(tTalkbox* const v, float quality) | |
| 213 | +{ | |
| 214 | + v->param[3] = quality; | |
| 215 | + v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * leaf.sampleRate); | |
| 216 | +} | |
| 217 | + | |
| 218 | + | |
| 219 | +void tVocoder_init (tVocoder* const v) | |
| 220 | +{ | |
| 221 | + v->param[0] = 0.33f; //input select | |
| 222 | + v->param[1] = 0.50f; //output dB | |
| 223 | + v->param[2] = 0.40f; //hi thru | |
| 224 | + v->param[3] = 0.40f; //hi band | |
| 225 | + v->param[4] = 0.16f; //envelope | |
| 226 | + v->param[5] = 0.55f; //filter q | |
| 227 | + v->param[6] = 0.6667f;//freq range | |
| 228 | + v->param[7] = 0.33f; //num bands | |
| 229 | + | |
| 230 | + tVocoder_update(v); | |
| 231 | +} | |
| 232 | + | |
| 233 | +void tVocoder_update (tVocoder* const v) | |
| 234 | +{ | |
| 235 | + float tpofs = 6.2831853f * leaf.invSampleRate; | |
| 236 | + | |
| 237 | + float rr, th, re; | |
| 238 | + | |
| 239 | + float sh; | |
| 240 | + | |
| 241 | + int32_t i; | |
| 242 | + | |
| 243 | + v->gain = (float)pow(10.0f, 2.0f * v->param[1] - 3.0f * v->param[5] - 2.0f); | |
| 244 | + | |
| 245 | + v->thru = (float)pow(10.0f, 0.5f + 2.0f * v->param[1]); | |
| 246 | + v->high = v->param[3] * v->param[3] * v->param[3] * v->thru; | |
| 247 | + v->thru *= v->param[2] * v->param[2] * v->param[2]; | |
| 248 | + | |
| 249 | + if(v->param[7]<0.5f) | |
| 250 | + { | |
| 251 | + v->nbnd=8; | |
| 252 | + re=0.003f; | |
| 253 | + v->f[1][2] = 3000.0f; | |
| 254 | + v->f[2][2] = 2200.0f; | |
| 255 | + v->f[3][2] = 1500.0f; | |
| 256 | + v->f[4][2] = 1080.0f; | |
| 257 | + v->f[5][2] = 700.0f; | |
| 258 | + v->f[6][2] = 390.0f; | |
| 259 | + v->f[7][2] = 190.0f; | |
| 260 | + } | |
| 261 | + else | |
| 262 | + { | |
| 263 | + v->nbnd=16; | |
| 264 | + re=0.0015f; | |
| 265 | + v->f[ 1][2] = 5000.0f; //+1000 | |
| 266 | + v->f[ 2][2] = 4000.0f; //+750 | |
| 267 | + v->f[ 3][2] = 3250.0f; //+500 | |
| 268 | + v->f[ 4][2] = 2750.0f; //+450 | |
| 269 | + v->f[ 5][2] = 2300.0f; //+300 | |
| 270 | + v->f[ 6][2] = 2000.0f; //+250 | |
| 271 | + v->f[ 7][2] = 1750.0f; //+250 | |
| 272 | + v->f[ 8][2] = 1500.0f; //+250 | |
| 273 | + v->f[ 9][2] = 1250.0f; //+250 | |
| 274 | + v->f[10][2] = 1000.0f; //+250 | |
| 275 | + v->f[11][2] = 750.0f; //+210 | |
| 276 | + v->f[12][2] = 540.0f; //+190 | |
| 277 | + v->f[13][2] = 350.0f; //+155 | |
| 278 | + v->f[14][2] = 195.0f; //+100 | |
| 279 | + v->f[15][2] = 95.0f; | |
| 280 | + } | |
| 281 | + | |
| 282 | + if(v->param[4]<0.05f) //freeze | |
| 283 | + { | |
| 284 | + for(i=0;i<v->nbnd;i++) v->f[i][12]=0.0f; | |
| 285 | + } | |
| 286 | + else | |
| 287 | + { | |
| 288 | + v->f[0][12] = (float)pow(10.0, -1.7 - 2.7f * v->param[4]); //envelope speed | |
| 289 | + | |
| 290 | + rr = 0.022f / (float)v->nbnd; //minimum proportional to frequency to stop distortion | |
| 291 | + for(i=1;i<v->nbnd;i++) | |
| 292 | + { | |
| 293 | + v->f[i][12] = (float)(0.025 - rr * (double)i); | |
| 294 | + if(v->f[0][12] < v->f[i][12]) v->f[i][12] = v->f[0][12]; | |
| 295 | + } | |
| 296 | + v->f[0][12] = 0.5f * v->f[0][12]; //only top band is at full rate | |
| 297 | + } | |
| 298 | + | |
| 299 | + rr = 1.0 - pow(10.0f, -1.0f - 1.2f * v->param[5]); | |
| 300 | + sh = (float)pow(2.0f, 3.0f * v->param[6] - 1.0f); //filter bank range shift | |
| 301 | + | |
| 302 | + for(i=1;i<v->nbnd;i++) | |
| 303 | + { | |
| 304 | + v->f[i][2] *= sh; | |
| 305 | + th = acos((2.0 * rr * cos(tpofs * v->f[i][2])) / (1.0 + rr * rr)); | |
| 306 | + v->f[i][0] = (float)(2.0 * rr * cos(th)); //a0 | |
| 307 | + v->f[i][1] = (float)(-rr * rr); //a1 | |
| 308 | + //was .98 | |
| 309 | + v->f[i][2] *= 0.96f; //shift 2nd stage slightly to stop high resonance peaks | |
| 310 | + th = acos((2.0 * rr * cos(tpofs * v->f[i][2])) / (1.0 + rr * rr)); | |
| 311 | + v->f[i][2] = (float)(2.0 * rr * cos(th)); | |
| 312 | + } | |
| 313 | +} | |
| 314 | + | |
| 315 | +float tVocoder_tick (tVocoder* const v, float synth, float voice) | |
| 316 | +{ | |
| 317 | + float a, b, o=0.0f, aa, bb, oo = v->kout, g = v->gain, ht = v->thru, hh = v->high, tmp; | |
| 318 | + uint32_t i, k = v->kval, nb = v->nbnd; | |
| 319 | + | |
| 320 | + a = voice; //speech | |
| 321 | + b = synth; //synth | |
| 322 | + | |
| 323 | + tmp = a - v->f[0][7]; //integrate modulator for HF band and filter bank pre-emphasis | |
| 324 | + v->f[0][7] = a; | |
| 325 | + a = tmp; | |
| 326 | + | |
| 327 | + if(tmp<0.0f) tmp = -tmp; | |
| 328 | + v->f[0][11] -= v->f[0][12] * (v->f[0][11] - tmp); //high band envelope | |
| 329 | + o = v->f[0][11] * (ht * a + hh * (b - v->f[0][3])); //high band + high thru | |
| 330 | + | |
| 331 | + v->f[0][3] = b; //integrate carrier for HF band | |
| 332 | + | |
| 333 | + if(++k & 0x1) //this block runs at half sample rate | |
| 334 | + { | |
| 335 | + oo = 0.0f; | |
| 336 | + aa = a + v->f[0][9] - v->f[0][8] - v->f[0][8]; //apply zeros here instead of in each reson | |
| 337 | + v->f[0][9] = v->f[0][8]; v->f[0][8] = a; | |
| 338 | + bb = b + v->f[0][5] - v->f[0][4] - v->f[0][4]; | |
| 339 | + v->f[0][5] = v->f[0][4]; v->f[0][4] = b; | |
| 340 | + | |
| 341 | + for(i=1; i<nb; i++) //filter bank: 4th-order band pass | |
| 342 | + { | |
| 343 | + tmp = v->f[i][0] * v->f[i][3] + v->f[i][1] * v->f[i][4] + bb; | |
| 344 | + v->f[i][4] = v->f[i][3]; | |
| 345 | + v->f[i][3] = tmp; | |
| 346 | + tmp += v->f[i][2] * v->f[i][5] + v->f[i][1] * v->f[i][6]; | |
| 347 | + v->f[i][6] = v->f[i][5]; | |
| 348 | + v->f[i][5] = tmp; | |
| 349 | + | |
| 350 | + tmp = v->f[i][0] * v->f[i][7] + v->f[i][1] * v->f[i][8] + aa; | |
| 351 | + v->f[i][8] = v->f[i][7]; | |
| 352 | + v->f[i][7] = tmp; | |
| 353 | + tmp += v->f[i][2] * v->f[i][9] + v->f[i][1] * v->f[i][10]; | |
| 354 | + v->f[i][10] = v->f[i][9]; | |
| 355 | + v->f[i][9] = tmp; | |
| 356 | + | |
| 357 | + if(tmp<0.0f) tmp = -tmp; | |
| 358 | + v->f[i][11] -= v->f[i][12] * (v->f[i][11] - tmp); | |
| 359 | + oo += v->f[i][5] * v->f[i][11]; | |
| 360 | + } | |
| 361 | + } | |
| 362 | + o += oo * g; //effect of interpolating back up to Fs would be minimal (aliasing >16kHz) | |
| 363 | + | |
| 364 | + v->kout = oo; | |
| 365 | + v->kval = k & 0x1; | |
| 366 | + if(fabs(v->f[0][11])<1.0e-10) v->f[0][11] = 0.0f; //catch HF envelope denormal | |
| 367 | + | |
| 368 | + for(i=1;i<nb;i++) | |
| 369 | + if(fabs(v->f[i][3])<1.0e-10 || fabs(v->f[i][7])<1.0e-10) | |
| 370 | + for(k=3; k<12; k++) v->f[i][k] = 0.0f; //catch reson & envelope denormals | |
| 371 | + | |
| 372 | + if(fabs(o)>10.0f) tVocoder_suspend(v); //catch instability | |
| 373 | + | |
| 374 | + return o; | |
| 375 | + | |
| 376 | +} | |
| 377 | + | |
| 378 | +void tVocoder_suspend (tVocoder* const v) | |
| 379 | +{ | |
| 380 | + int32_t i, j; | |
| 381 | + | |
| 382 | + for(i=0; i<v->nbnd; i++) for(j=3; j<12; j++) v->f[i][j] = 0.0f; //zero band filters and envelopes | |
| 383 | + v->kout = 0.0f; | |
| 384 | + v->kval = 0; | |
| 385 | +} | |
| 386 | + | |