Unified · Split
Binary file not shown.
| @@ -86,7 +86,7 @@ void tVocoder_suspend (tVocoder* const); · 85 unmodified lines | ||
| 86 | 86 | |
| 87 | 87 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ |
| 88 | 88 | |
| 89 | −/* tSOLAD : pitch shifting algorithm that underlies tPitchShifter etc */ | |
| 89 | +/* tSOLAD : pitch shifting algorithm that underlies tRetune etc */ | |
| 90 | 90 | #define LOOPSIZE (2048*2) // (4096*2) // loop size must be power of two |
| 91 | 91 | #define LOOPMASK (LOOPSIZE - 1) |
| 92 | 92 | #define PITCHFACTORDEFAULT 1.0f |
| @@ -111,99 +111,122 @@ typedef struct _tSOLAD · 18 unmodified lines | ||
| 111 | 111 | |
| 112 | 112 | void tSOLAD_init (tSOLAD* const); |
| 113 | 113 | void tSOLAD_free (tSOLAD* const); |
| 114 | − | |
| 115 | 114 | // send one block of input samples, receive one block of output samples |
| 116 | 115 | void tSOLAD_ioSamples (tSOLAD *w, float* in, float* out, int blocksize); |
| 117 | − | |
| 118 | 116 | // set periodicity analysis data |
| 119 | 117 | void tSOLAD_setPeriod (tSOLAD *w, float period); |
| 120 | − | |
| 121 | 118 | // set pitch factor between 0.25 and 4 |
| 122 | 119 | void tSOLAD_setPitchFactor (tSOLAD *w, float pitchfactor); |
| 123 | − | |
| 124 | 120 | // force readpointer lag |
| 125 | 121 | void tSOLAD_setReadLag (tSOLAD *w, float readlag); |
| 126 | − | |
| 127 | 122 | // reset state variables |
| 128 | 123 | void tSOLAD_resetState (tSOLAD *w); |
| 129 | 124 | |
| 130 | −// Pitch shifter | |
| 131 | −typedef struct _tPitchShifter | |
| 125 | +// Pitch shift | |
| 126 | +typedef struct _tPitchShift | |
| 132 | 127 | { |
| 133 | − tEnvPD env; | |
| 134 | − tSNAC snac; | |
| 135 | 128 | tSOLAD sola; |
| 136 | 129 | tHighpass hp; |
| 130 | + tPeriodDetection* p; | |
| 137 | 131 | |
| 138 | − float* inBuffer; | |
| 139 | 132 | float* outBuffer; |
| 140 | 133 | int frameSize; |
| 141 | 134 | int bufSize; |
| 135 | + | |
| 142 | 136 | int framesPerBuffer; |
| 143 | 137 | int curBlock; |
| 144 | 138 | int lastBlock; |
| 145 | 139 | int index; |
| 146 | 140 | |
| 141 | + float pitchFactor; | |
| 142 | + float timeConstant; | |
| 143 | + float radius; | |
| 144 | +} tPitchShift; | |
| 145 | + | |
| 146 | +void tPitchShift_init (tPitchShift* const, tPeriodDetection* const, float* out, int bufSize); | |
| 147 | +void tPitchShift_free (tPitchShift* const); | |
| 148 | +float tPitchShift_shift (tPitchShift* const); | |
| 149 | +float tPitchShift_shiftToFunc (tPitchShift* const, float (*fun)(float)); | |
| 150 | +float tPitchShift_shiftToFreq (tPitchShift* const, float freq); | |
| 151 | +void tPitchShift_setPitchFactor (tPitchShift* const, float pf); | |
| 152 | + | |
| 153 | +// Retune | |
| 154 | +typedef struct _tRetune | |
| 155 | +{ | |
| 156 | + tPeriodDetection pd; | |
| 157 | + tPitchShift* ps; | |
| 158 | + | |
| 159 | + float* inBuffer; | |
| 160 | + float** outBuffers; | |
| 161 | + float* tickOutput; | |
| 162 | + int frameSize; | |
| 163 | + int bufSize; | |
| 164 | + | |
| 147 | 165 | uint16_t hopSize; |
| 148 | 166 | uint16_t windowSize; |
| 149 | 167 | uint8_t fba; |
| 150 | 168 | |
| 151 | − float pitchFactor; | |
| 169 | + float* pitchFactor; | |
| 152 | 170 | float timeConstant; |
| 153 | 171 | float radius; |
| 154 | − float max; | |
| 155 | − float lastmax; | |
| 156 | − float deltamax; | |
| 157 | − | |
| 158 | −} tPitchShifter; | |
| 159 | − | |
| 160 | −void tPitchShifter_init (tPitchShifter* const, float* in, float* out, int bufSize, int frameSize); | |
| 161 | −void tPitchShifter_free (tPitchShifter* const); | |
| 162 | − | |
| 163 | −float tPitchShifter_tick (tPitchShifter* const, float sample); | |
| 164 | −float tPitchShifterToFreq_tick (tPitchShifter* const, float sample, float freq); | |
| 165 | −float tPitchShifterToFunc_tick (tPitchShifter* const, float sample, float (*fun)(float)); | |
| 166 | −void tPitchShifter_ioSamples_toFreq (tPitchShifter* const, float* in, float* out, int size, float toFreq); | |
| 167 | −void tPitchShifter_ioSamples_toPeriod(tPitchShifter* const, float* in, float* out, int size, float toPeriod); | |
| 168 | −void tPitchShifter_ioSamples_toFunc (tPitchShifter* const, float* in, float* out, int size, float (*fun)(float)); | |
| 169 | −void tPitchShifter_setPitchFactor (tPitchShifter* const, float pf); | |
| 170 | −void tPitchShifter_setTimeConstant (tPitchShifter* const, float tc); | |
| 171 | −void tPitchShifter_setHopSize (tPitchShifter* const, int hs); | |
| 172 | −void tPitchShifter_setWindowSize (tPitchShifter* const, int ws); | |
| 173 | −float tPitchShifter_getPeriod (tPitchShifter* const); | |
| 174 | − | |
| 175 | −//============================================================================== | |
| 176 | − | |
| 177 | −// Pitch shift | |
| 178 | −typedef struct _tPitchShift | |
| 172 | + | |
| 173 | + float inputPeriod; | |
| 174 | + | |
| 175 | + int numVoices; | |
| 176 | +} tRetune; | |
| 177 | + | |
| 178 | +void tRetune_init (tRetune* const, int numVoices, int bufSize, int frameSize); | |
| 179 | +void tRetune_free (tRetune* const); | |
| 180 | + | |
| 181 | +float* tRetune_tick (tRetune* const, float sample); | |
| 182 | +void tRetune_setNumVoices (tRetune* const, int numVoices); | |
| 183 | +void tRetune_setPitchFactors (tRetune* const, float pf); | |
| 184 | +void tRetune_setPitchFactor (tRetune* const, float pf, int voice); | |
| 185 | +void tRetune_setTimeConstant (tRetune* const, float tc); | |
| 186 | +void tRetune_setHopSize (tRetune* const, int hs); | |
| 187 | +void tRetune_setWindowSize (tRetune* const, int ws); | |
| 188 | +float tRetune_getInputPeriod (tRetune* const); | |
| 189 | +float tRetune_getInputFreq (tRetune* const); | |
| 190 | + | |
| 191 | +// Autotune | |
| 192 | +typedef struct _tAutotune | |
| 179 | 193 | { |
| 180 | − tSOLAD sola; | |
| 181 | − tHighpass hp; | |
| 182 | − tPeriodDetection* p; | |
| 194 | + tPeriodDetection pd; | |
| 195 | + tPitchShift* ps; | |
| 183 | 196 | |
| 184 | − float* outBuffer; | |
| 197 | + float* inBuffer; | |
| 198 | + float** outBuffers; | |
| 199 | + float* tickOutput; | |
| 185 | 200 | int frameSize; |
| 186 | 201 | int bufSize; |
| 187 | 202 | |
| 188 | − int framesPerBuffer; | |
| 189 | − int curBlock; | |
| 190 | − int lastBlock; | |
| 191 | − int index; | |
| 203 | + uint16_t hopSize; | |
| 204 | + uint16_t windowSize; | |
| 205 | + uint8_t fba; | |
| 192 | 206 | |
| 193 | − float pitchFactor; | |
| 207 | + float* freq; | |
| 194 | 208 | float timeConstant; |
| 195 | 209 | float radius; |
| 196 | −} tPitchShift; | |
| 210 | + | |
| 211 | + float inputPeriod; | |
| 212 | + | |
| 213 | + int numVoices; | |
| 214 | +} tAutotune; | |
| 197 | 215 | |
| 198 | −void tPitchShift_init (tPitchShift* const,tPeriodDetection* const, float* out, int bufSize); | |
| 199 | −void tPitchShift_free (tPitchShift* const); | |
| 216 | +void tAutotune_init (tAutotune* const, int numVoices, int bufSize, int frameSize); | |
| 217 | +void tAutotune_free (tAutotune* const); | |
| 200 | 218 | |
| 201 | −float tPitchShift_shift (tPitchShift* const); | |
| 202 | −float tPitchShift_shiftToFunc (tPitchShift* const, float (*fun)(float)); | |
| 203 | −float tPitchShift_shiftToFreq (tPitchShift* const, float freq); | |
| 204 | −void tPitchShift_setPitchFactor (tPitchShift* const, float pf); | |
| 219 | +float* tAutotune_tick (tAutotune* const, float sample); | |
| 220 | +void tAutotune_setNumVoices (tAutotune* const, int numVoices); | |
| 221 | +void tAutotune_setFreq (tAutotune* const, float f, int voice); | |
| 222 | +void tAutotune_setTimeConstant (tAutotune* const, float tc); | |
| 223 | +void tAutotune_setHopSize (tAutotune* const, int hs); | |
| 224 | +void tAutotune_setWindowSize (tAutotune* const, int ws); | |
| 225 | +float tAutotune_getInputPeriod (tAutotune* const); | |
| 226 | +float tAutotune_getInputFreq (tAutotune* const); | |
| 205 | 227 | |
| 206 | 228 | //============================================================================== |
| 229 | + | |
| 207 | 230 | |
| 208 | 231 | #define FORD 7 |
| 209 | 232 | #define FORMANT_BUFFER_SIZE 2048 |
| @@ -402,331 +402,240 @@ void tVocoder_suspend (tVocoder* const v) · 401 unmodified lines | ||
| 402 | 402 | } |
| 403 | 403 | |
| 404 | 404 | //============================================================================================================ |
| 405 | −// PITCHSHIFTER | |
| 405 | +// RETUNE | |
| 406 | 406 | //============================================================================================================ |
| 407 | −static int pitchshifter_attackdetect(tPitchShifter* ps); | |
| 408 | 407 | |
| 409 | −void tPitchShifter_init(tPitchShifter* const ps, float* in, float* out, int bufSize, int frameSize) | |
| 408 | +void tRetune_init(tRetune* const r, int numVoices, int bufSize, int frameSize) | |
| 410 | 409 | { |
| 411 | − ps->inBuffer = in; | |
| 412 | − ps->outBuffer = out; | |
| 413 | − ps->bufSize = bufSize; | |
| 414 | − ps->frameSize = frameSize; | |
| 415 | − ps->framesPerBuffer = ps->bufSize / ps->frameSize; | |
| 416 | − ps->curBlock = 1; | |
| 417 | − ps->lastBlock = 0; | |
| 418 | − ps->index = 0; | |
| 419 | − | |
| 420 | − ps->hopSize = DEFHOPSIZE; | |
| 421 | − ps->windowSize = DEFWINDOWSIZE; | |
| 422 | − ps->fba = FBA; | |
| 410 | + r->bufSize = bufSize; | |
| 411 | + r->frameSize = frameSize; | |
| 412 | + r->numVoices = numVoices; | |
| 423 | 413 | |
| 424 | − tEnvPD_init(&ps->env, ps->windowSize, ps->hopSize, ps->frameSize); | |
| 414 | + r->inBuffer = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 415 | + r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices); | |
| 425 | 416 | |
| 426 | − tSNAC_init(&ps->snac, DEFOVERLAP); | |
| 427 | − | |
| 428 | − tSOLAD_init(&ps->sola); | |
| 417 | + r->hopSize = DEFHOPSIZE; | |
| 418 | + r->windowSize = DEFWINDOWSIZE; | |
| 419 | + r->fba = FBA; | |
| 420 | + tRetune_setTimeConstant(r, DEFTIMECONSTANT); | |
| 429 | 421 | |
| 430 | − tHighpass_init(&ps->hp, HPFREQ); | |
| 422 | + tPeriodDetection_init(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize); | |
| 431 | 423 | |
| 432 | − tSOLAD_setPitchFactor(&ps->sola, DEFPITCHRATIO); | |
| 424 | + r->inputPeriod = 0.0f; | |
| 433 | 425 | |
| 434 | − tPitchShifter_setTimeConstant(ps, DEFTIMECONSTANT); | |
| 426 | + r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices); | |
| 427 | + for (int i = 0; i < r->numVoices; ++i) | |
| 428 | + { | |
| 429 | + r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 430 | + tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize); | |
| 431 | + } | |
| 435 | 432 | } |
| 436 | 433 | |
| 437 | −void tPitchShifter_free(tPitchShifter* const ps) | |
| 434 | +void tRetune_free(tRetune* const r) | |
| 438 | 435 | { |
| 439 | − tEnvPD_free(&ps->env); | |
| 440 | − tSNAC_free(&ps->snac); | |
| 441 | − tSOLAD_free(&ps->sola); | |
| 442 | − tHighpass_free(&ps->hp); | |
| 436 | + tPeriodDetection_free(&r->pd); | |
| 437 | + for (int i = 0; i < r->numVoices; ++i) | |
| 438 | + { | |
| 439 | + tPitchShift_free(&r->ps[i]); | |
| 440 | + leaf_free(r->outBuffers[i]); | |
| 441 | + } | |
| 442 | + leaf_free(r->ps); | |
| 443 | + leaf_free(r->inBuffer); | |
| 444 | + leaf_free(r->outBuffers); | |
| 443 | 445 | } |
| 444 | 446 | |
| 445 | −float tPitchShifter_tick(tPitchShifter* ps, float sample) | |
| 447 | +float* tRetune_tick(tRetune* const r, float sample) | |
| 446 | 448 | { |
| 447 | − float period, out; | |
| 448 | − int i, iLast; | |
| 449 | − | |
| 450 | − i = (ps->curBlock*ps->frameSize); | |
| 451 | − iLast = (ps->lastBlock*ps->frameSize)+ps->index; | |
| 449 | + r->inputPeriod = tPeriodDetection_findPeriod(&r->pd, sample); | |
| 452 | 450 | |
| 453 | − out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]); | |
| 454 | − ps->inBuffer[i+ps->index] = sample; | |
| 455 | − | |
| 456 | − ps->index++; | |
| 457 | − if (ps->index >= ps->frameSize) | |
| 451 | + for (int v = 0; v < r->numVoices; ++v) | |
| 458 | 452 | { |
| 459 | − ps->index = 0; | |
| 460 | − | |
| 461 | − tEnvPD_processBlock(&ps->env, &(ps->inBuffer[i])); | |
| 462 | − | |
| 463 | − if(pitchshifter_attackdetect(ps) == 1) | |
| 464 | − { | |
| 465 | − ps->fba = 5; | |
| 466 | − tSOLAD_setReadLag(&ps->sola, ps->windowSize); | |
| 467 | − } | |
| 468 | − | |
| 469 | − tSNAC_ioSamples(&ps->snac, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize); | |
| 470 | − period = tSNAC_getPeriod(&ps->snac); | |
| 471 | − | |
| 472 | − ps->curBlock++; | |
| 473 | − if (ps->curBlock >= ps->framesPerBuffer) ps->curBlock = 0; | |
| 474 | − ps->lastBlock++; | |
| 475 | − if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0; | |
| 476 | − | |
| 477 | − //separate here | |
| 478 | − | |
| 479 | − tSOLAD_setPeriod(&ps->sola, period); | |
| 480 | − | |
| 481 | − tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor); | |
| 482 | − tSOLAD_ioSamples(&ps->sola, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize); | |
| 483 | − | |
| 453 | + r->tickOutput[v] = tPitchShift_shift(&r->ps[v]); | |
| 484 | 454 | } |
| 485 | − | |
| 486 | − return out; | |
| 455 | + | |
| 456 | + return r->tickOutput; | |
| 487 | 457 | } |
| 488 | 458 | |
| 489 | −float tPitchShifterToFreq_tick(tPitchShifter* ps, float sample, float freq) | |
| 459 | +void tRetune_setNumVoices(tRetune* const r, int numVoices) | |
| 490 | 460 | { |
| 491 | − float period, out; | |
| 492 | − int i, iLast; | |
| 493 | − | |
| 494 | − i = (ps->curBlock*ps->frameSize); | |
| 495 | − iLast = (ps->lastBlock*ps->frameSize)+ps->index; | |
| 461 | + for (int i = 0; i < r->numVoices; ++i) | |
| 462 | + { | |
| 463 | + tPitchShift_free(&r->ps[i]); | |
| 464 | + leaf_free(r->outBuffers[i]); | |
| 465 | + } | |
| 466 | + leaf_free(r->ps); | |
| 467 | + leaf_free(r->outBuffers); | |
| 496 | 468 | |
| 497 | − out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]); | |
| 498 | − ps->inBuffer[i+ps->index] = sample; | |
| 469 | + r->numVoices = numVoices; | |
| 499 | 470 | |
| 500 | − ps->index++; | |
| 501 | − if (ps->index >= ps->frameSize) | |
| 471 | + r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices); | |
| 472 | + r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices); | |
| 473 | + for (int i = 0; i < r->numVoices; ++i) | |
| 502 | 474 | { |
| 503 | − ps->index = 0; | |
| 504 | − | |
| 505 | − tEnvPD_processBlock(&ps->env, &(ps->inBuffer[i])); | |
| 506 | − | |
| 507 | − if(pitchshifter_attackdetect(ps) == 1) | |
| 508 | − { | |
| 509 | − ps->fba = 5; | |
| 510 | − tSOLAD_setReadLag(&ps->sola, ps->windowSize); | |
| 511 | − } | |
| 512 | − | |
| 513 | − tSNAC_ioSamples(&ps->snac, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize); | |
| 514 | − period = tSNAC_getPeriod(&ps->snac); | |
| 515 | − | |
| 516 | − tSOLAD_setPeriod(&ps->sola, period); | |
| 517 | − | |
| 518 | − ps->pitchFactor = period*freq*leaf.invSampleRate; | |
| 519 | − tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor); | |
| 520 | − tSOLAD_ioSamples(&ps->sola, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize); | |
| 521 | − | |
| 522 | − ps->curBlock++; | |
| 523 | − if (ps->curBlock >= ps->framesPerBuffer) ps->curBlock = 0; | |
| 524 | − ps->lastBlock++; | |
| 525 | − if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0; | |
| 475 | + r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 476 | + tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize); | |
| 526 | 477 | } |
| 527 | 478 | |
| 528 | − return out; | |
| 479 | + | |
| 529 | 480 | } |
| 530 | 481 | |
| 531 | −float tPitchShifterToFunc_tick(tPitchShifter* ps, float sample, float (*fun)(float)) | |
| 482 | +void tRetune_setPitchFactors(tRetune* const r, float pf) | |
| 532 | 483 | { |
| 533 | − float period, out; | |
| 534 | − int i, iLast; | |
| 535 | − | |
| 536 | − i = (ps->curBlock*ps->frameSize); | |
| 537 | − iLast = (ps->lastBlock*ps->frameSize)+ps->index; | |
| 538 | − | |
| 539 | − out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]); | |
| 540 | − ps->inBuffer[i+ps->index] = sample; | |
| 541 | − | |
| 542 | − ps->index++; | |
| 543 | − if (ps->index >= ps->frameSize) | |
| 484 | + for (int i = 0; i < r->numVoices; ++i) | |
| 544 | 485 | { |
| 545 | − ps->index = 0; | |
| 546 | − | |
| 547 | − tEnvPD_processBlock(&ps->env, &(ps->inBuffer[i])); | |
| 548 | − | |
| 549 | − if(pitchshifter_attackdetect(ps) == 1) | |
| 550 | − { | |
| 551 | − ps->fba = 5; | |
| 552 | − tSOLAD_setReadLag(&ps->sola, ps->windowSize); | |
| 553 | − } | |
| 554 | − | |
| 555 | − tSNAC_ioSamples(&ps->snac, (&ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize); | |
| 556 | − period = tSNAC_getPeriod(&ps->snac); | |
| 557 | − | |
| 558 | − tSOLAD_setPeriod(&ps->sola, period); | |
| 559 | − | |
| 560 | − ps->pitchFactor = period/fun(period); | |
| 561 | − tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor); | |
| 562 | − tSOLAD_ioSamples(&ps->sola, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize); | |
| 563 | − | |
| 564 | − ps->curBlock++; | |
| 565 | − if (ps->curBlock >= ps->framesPerBuffer) ps->curBlock = 0; | |
| 566 | − ps->lastBlock++; | |
| 567 | − if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0; | |
| 486 | + r->pitchFactor[i] = pf; | |
| 487 | + tPitchShift_setPitchFactor(&r->ps[i], r->pitchFactor[i]); | |
| 568 | 488 | } |
| 569 | − | |
| 570 | − return out; | |
| 571 | 489 | } |
| 572 | 490 | |
| 573 | −void tPitchShifter_ioSamples(tPitchShifter* ps, float* in, float* out, int size) | |
| 491 | +void tRetune_setPitchFactor(tRetune* const r, float pf, int voice) | |
| 574 | 492 | { |
| 575 | − float period; | |
| 576 | − | |
| 577 | − tEnvPD_processBlock(&ps->env, in); | |
| 578 | − | |
| 579 | − if(pitchshifter_attackdetect(ps) == 1) | |
| 580 | − { | |
| 581 | − ps->fba = 5; | |
| 582 | − tSOLAD_setReadLag(&ps->sola, ps->windowSize); | |
| 583 | − } | |
| 493 | + r->pitchFactor[voice] = pf; | |
| 494 | + tPitchShift_setPitchFactor(&r->ps[voice], r->pitchFactor[voice]); | |
| 495 | +} | |
| 496 | + | |
| 497 | +void tRetune_setTimeConstant(tRetune* const r, float tc) | |
| 498 | +{ | |
| 499 | + r->timeConstant = tc; | |
| 500 | + r->radius = expf(-1000.0f * r->hopSize * leaf.invSampleRate / r->timeConstant); | |
| 501 | +} | |
| 502 | + | |
| 503 | +void tRetune_setHopSize(tRetune* const r, int hs) | |
| 504 | +{ | |
| 505 | + r->hopSize = hs; | |
| 506 | + tPeriodDetection_setHopSize(&r->pd, r->hopSize); | |
| 507 | +} | |
| 508 | + | |
| 509 | +void tRetune_setWindowSize(tRetune* const r, int ws) | |
| 510 | +{ | |
| 511 | + r->windowSize = ws; | |
| 512 | + tPeriodDetection_setWindowSize(&r->pd, r->windowSize); | |
| 513 | +} | |
| 514 | + | |
| 515 | +float tRetune_getInputPeriod(tRetune* const r) | |
| 516 | +{ | |
| 517 | + return r->inputPeriod; | |
| 518 | +} | |
| 519 | + | |
| 520 | +float tRetune_getInputFreq(tRetune* const r) | |
| 521 | +{ | |
| 522 | + return 1.0f/r->inputPeriod; | |
| 523 | +} | |
| 524 | + | |
| 525 | +//============================================================================================================ | |
| 526 | +// AUTOTUNE | |
| 527 | +//============================================================================================================ | |
| 528 | + | |
| 529 | +void tAutotune_init(tAutotune* const r, int numVoices, int bufSize, int frameSize) | |
| 530 | +{ | |
| 531 | + r->bufSize = bufSize; | |
| 532 | + r->frameSize = frameSize; | |
| 533 | + r->numVoices = numVoices; | |
| 584 | 534 | |
| 585 | − tSNAC_ioSamples(&ps->snac, in, out, size); | |
| 586 | − period = tSNAC_getPeriod(&ps->snac); | |
| 535 | + r->inBuffer = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 536 | + r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices); | |
| 587 | 537 | |
| 588 | − tSOLAD_setPeriod(&ps->sola, period); | |
| 538 | + r->hopSize = DEFHOPSIZE; | |
| 539 | + r->windowSize = DEFWINDOWSIZE; | |
| 540 | + r->fba = FBA; | |
| 541 | + tAutotune_setTimeConstant(r, DEFTIMECONSTANT); | |
| 589 | 542 | |
| 590 | − tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor); | |
| 591 | − tSOLAD_ioSamples(&ps->sola, in, out, size); | |
| 543 | + tPeriodDetection_init(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize); | |
| 592 | 544 | |
| 593 | − for (int cc = 0; cc < size; ++cc) | |
| 545 | + r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices); | |
| 546 | + for (int i = 0; i < r->numVoices; ++i) | |
| 594 | 547 | { |
| 595 | − out[cc] = tHighpass_tick(&ps->hp, out[cc]); | |
| 548 | + r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 549 | + tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize); | |
| 596 | 550 | } |
| 551 | + | |
| 552 | + r->inputPeriod = 0.0f; | |
| 597 | 553 | } |
| 598 | 554 | |
| 599 | −void tPitchShifter_ioSamples_toFreq(tPitchShifter* ps, float* in, float* out, int size, float toFreq) | |
| 555 | +void tAutotune_free(tAutotune* const r) | |
| 600 | 556 | { |
| 601 | − float period; | |
| 602 | − | |
| 603 | − tEnvPD_processBlock(&ps->env, in); | |
| 604 | − | |
| 605 | − if(pitchshifter_attackdetect(ps) == 1) | |
| 606 | − { | |
| 607 | − ps->fba = 5; | |
| 608 | − tSOLAD_setReadLag(&ps->sola, ps->windowSize); | |
| 609 | − } | |
| 610 | − | |
| 611 | − tSNAC_ioSamples(&ps->snac, in, out, size); | |
| 612 | − period = tSNAC_getPeriod(&ps->snac); | |
| 613 | − | |
| 614 | − tSOLAD_setPeriod(&ps->sola, period); | |
| 615 | − ps->pitchFactor = period*toFreq; | |
| 616 | − tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor); | |
| 617 | − tSOLAD_ioSamples(&ps->sola, in, out, size); | |
| 618 | − | |
| 619 | − for (int cc = 0; cc < size; ++cc) | |
| 557 | + tPeriodDetection_free(&r->pd); | |
| 558 | + for (int i = 0; i < r->numVoices; ++i) | |
| 620 | 559 | { |
| 621 | − out[cc] = tHighpass_tick(&ps->hp, out[cc]); | |
| 560 | + tPitchShift_free(&r->ps[i]); | |
| 561 | + leaf_free(r->outBuffers[i]); | |
| 622 | 562 | } |
| 563 | + leaf_free(r->ps); | |
| 564 | + leaf_free(r->inBuffer); | |
| 565 | + leaf_free(r->outBuffers); | |
| 623 | 566 | } |
| 624 | 567 | |
| 625 | −void tPitchShifter_ioSamples_toPeriod(tPitchShifter* ps, float* in, float* out, int size, float toPeriod) | |
| 568 | +float* tAutotune_tick(tAutotune* const r, float sample) | |
| 626 | 569 | { |
| 627 | − float period; | |
| 570 | + r->inputPeriod = tPeriodDetection_findPeriod(&r->pd, sample); | |
| 628 | 571 | |
| 629 | − tEnvPD_processBlock(&ps->env, in); | |
| 630 | − | |
| 631 | − if(pitchshifter_attackdetect(ps) == 1) | |
| 572 | + for (int v = 0; v < r->numVoices; ++v) | |
| 632 | 573 | { |
| 633 | − ps->fba = 5; | |
| 634 | − tSOLAD_setReadLag(&ps->sola, ps->windowSize); | |
| 574 | + r->tickOutput[v] = tPitchShift_shiftToFreq(&r->ps[v], r->freq[v]); | |
| 635 | 575 | } |
| 636 | 576 | |
| 637 | − tSNAC_ioSamples(&ps->snac, in, out, size); | |
| 638 | − period = tSNAC_getPeriod(&ps->snac); | |
| 639 | − | |
| 640 | − tSOLAD_setPeriod(&ps->sola, period); | |
| 641 | − ps->pitchFactor = period/toPeriod; | |
| 642 | − tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor); | |
| 643 | − tSOLAD_ioSamples(&ps->sola, in, out, size); | |
| 644 | − | |
| 645 | − for (int cc = 0; cc < size; ++cc) | |
| 646 | − { | |
| 647 | − out[cc] = tHighpass_tick(&ps->hp, out[cc]); | |
| 648 | − } | |
| 577 | + return r->tickOutput; | |
| 649 | 578 | } |
| 650 | 579 | |
| 651 | −void tPitchShifter_ioSamples_toFunc(tPitchShifter* ps, float* in, float* out, int size, float (*fun)(float)) | |
| 580 | +void tAutotune_setNumVoices(tAutotune* const r, int numVoices) | |
| 652 | 581 | { |
| 653 | − float period; | |
| 654 | − | |
| 655 | − tEnvPD_processBlock(&ps->env, in); | |
| 656 | − | |
| 657 | − if(pitchshifter_attackdetect(ps) == 1) | |
| 582 | + for (int i = 0; i < r->numVoices; ++i) | |
| 658 | 583 | { |
| 659 | − ps->fba = 5; | |
| 660 | − tSOLAD_setReadLag(&ps->sola, ps->windowSize); | |
| 584 | + tPitchShift_free(&r->ps[i]); | |
| 585 | + leaf_free(r->outBuffers[i]); | |
| 661 | 586 | } |
| 587 | + leaf_free(r->ps); | |
| 588 | + leaf_free(r->outBuffers); | |
| 662 | 589 | |
| 663 | − tSNAC_ioSamples(&ps->snac, in, out, size); | |
| 664 | − period = tSNAC_getPeriod(&ps->snac); | |
| 590 | + r->numVoices = numVoices; | |
| 665 | 591 | |
| 666 | − tSOLAD_setPeriod(&ps->sola, period); | |
| 667 | − ps->pitchFactor = period/fun(period); | |
| 668 | − tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor); | |
| 669 | − tSOLAD_ioSamples(&ps->sola, in, out, size); | |
| 670 | − | |
| 671 | − for (int cc = 0; cc < size; ++cc) | |
| 592 | + r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices); | |
| 593 | + r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices); | |
| 594 | + for (int i = 0; i < r->numVoices; ++i) | |
| 672 | 595 | { |
| 673 | − out[cc] = tHighpass_tick(&ps->hp, out[cc]); | |
| 596 | + r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize); | |
| 597 | + tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize); | |
| 674 | 598 | } |
| 599 | + | |
| 600 | + | |
| 675 | 601 | } |
| 676 | 602 | |
| 677 | −void tPitchShifter_setPitchFactor(tPitchShifter* ps, float pf) | |
| 603 | +void tAutotune_setFreq(tAutotune* const r, float f, int voice) | |
| 678 | 604 | { |
| 679 | − ps->pitchFactor = pf; | |
| 605 | + for (int i = 0; i < r->numVoices; ++i) | |
| 606 | + { | |
| 607 | + r->freq[i] = f; | |
| 608 | + } | |
| 680 | 609 | } |
| 681 | 610 | |
| 682 | −void tPitchShifter_setTimeConstant(tPitchShifter* ps, float tc) | |
| 611 | +void tAutotune_setTimeConstant(tAutotune* const r, float tc) | |
| 683 | 612 | { |
| 684 | − ps->timeConstant = tc; | |
| 685 | − ps->radius = expf(-1000.0f * ps->hopSize * leaf.invSampleRate / ps->timeConstant); | |
| 613 | + r->timeConstant = tc; | |
| 614 | + r->radius = expf(-1000.0f * r->hopSize * leaf.invSampleRate / r->timeConstant); | |
| 686 | 615 | } |
| 687 | 616 | |
| 688 | −void tPitchShifter_setHopSize(tPitchShifter* ps, int hs) | |
| 617 | +void tAutotune_setHopSize(tAutotune* const r, int hs) | |
| 689 | 618 | { |
| 690 | − ps->hopSize = hs; | |
| 619 | + r->hopSize = hs; | |
| 620 | + tPeriodDetection_setHopSize(&r->pd, r->hopSize); | |
| 691 | 621 | } |
| 692 | 622 | |
| 693 | −void tPitchShifter_setWindowSize(tPitchShifter* ps, int ws) | |
| 623 | +void tAutotune_setWindowSize(tAutotune* const r, int ws) | |
| 694 | 624 | { |
| 695 | − ps->windowSize = ws; | |
| 625 | + r->windowSize = ws; | |
| 626 | + tPeriodDetection_setWindowSize(&r->pd, r->windowSize); | |
| 696 | 627 | } |
| 697 | 628 | |
| 698 | −float tPitchShifter_getPeriod(tPitchShifter* ps) | |
| 629 | +float tAutotune_getInputPeriod(tAutotune* const r) | |
| 699 | 630 | { |
| 700 | − return tSNAC_getPeriod(&ps->snac); | |
| 631 | + return r->inputPeriod; | |
| 701 | 632 | } |
| 702 | 633 | |
| 703 | −static int pitchshifter_attackdetect(tPitchShifter* ps) | |
| 634 | +float tAutotune_getInputFreq(tAutotune* const r) | |
| 704 | 635 | { |
| 705 | − float envout; | |
| 706 | − | |
| 707 | − envout = tEnvPD_tick(&ps->env); | |
| 708 | − | |
| 709 | − if (envout >= 1.0f) | |
| 710 | − { | |
| 711 | − ps->lastmax = ps->max; | |
| 712 | − if (envout > ps->max) | |
| 713 | − { | |
| 714 | − ps->max = envout; | |
| 715 | − } | |
| 716 | − else | |
| 717 | − { | |
| 718 | − ps->deltamax = envout - ps->max; | |
| 719 | − ps->max = ps->max * ps->radius; | |
| 720 | − } | |
| 721 | − ps->deltamax = ps->max - ps->lastmax; | |
| 722 | − } | |
| 723 | − | |
| 724 | − ps->fba = ps->fba ? (ps->fba - 1) : 0; | |
| 725 | − | |
| 726 | − return (ps->fba == 0 && (ps->max > 60 && ps->deltamax > 6)) ? 1 : 0; | |
| 636 | + return 1.0f/r->inputPeriod; | |
| 727 | 637 | } |
| 728 | 638 | |
| 729 | − | |
| 730 | 639 | //============================================================================================================ |
| 731 | 640 | // PITCHSHIFT |
| 732 | 641 | //============================================================================================================ |
| @@ -735,7 +644,7 @@ static int pitchshift_attackdetect(tPitchShift* ps) · 2 unmodified lines | ||
| 735 | 644 | { |
| 736 | 645 | float envout; |
| 737 | 646 | |
| 738 | − envout = tEnvPD_tick(&ps->p->env); | |
| 647 | + envout = tEnv_tick(&ps->p->env); | |
| 739 | 648 | |
| 740 | 649 | if (envout >= 1.0f) |
| 741 | 650 | { |
| @@ -757,7 +666,7 @@ static int pitchshift_attackdetect(tPitchShift* ps) · 15 unmodified lines | ||
| 757 | 666 | return (ps->p->fba == 0 && (ps->p->max > 60 && ps->p->deltamax > 6)) ? 1 : 0; |
| 758 | 667 | } |
| 759 | 668 | |
| 760 | −void tPitchShift_init (tPitchShift* const ps,tPeriodDetection* p, float* out, int bufSize) | |
| 669 | +void tPitchShift_init (tPitchShift* const ps, tPeriodDetection* p, float* out, int bufSize) | |
| 761 | 670 | { |
| 762 | 671 | ps->p = p; |
| 763 | 672 | |