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 | #define LOOPSIZE (2048*2) // (4096*2) // loop size must be power of two | 90 | #define LOOPSIZE (2048*2) // (4096*2) // loop size must be power of two |
| 91 | #define LOOPMASK (LOOPSIZE - 1) | 91 | #define LOOPMASK (LOOPSIZE - 1) |
| 92 | #define PITCHFACTORDEFAULT 1.0f | 92 | #define PITCHFACTORDEFAULT 1.0f |
| @@ -111,99 +111,122 @@ typedef struct _tSOLAD · 18 unmodified lines | |||
| 111 | 111 | ||
| 112 | void tSOLAD_init (tSOLAD* const); | 112 | void tSOLAD_init (tSOLAD* const); |
| 113 | void tSOLAD_free (tSOLAD* const); | 113 | void tSOLAD_free (tSOLAD* const); |
| 114 | |||
| 115 | // send one block of input samples, receive one block of output samples | 114 | // send one block of input samples, receive one block of output samples |
| 116 | void tSOLAD_ioSamples (tSOLAD *w, float* in, float* out, int blocksize); | 115 | void tSOLAD_ioSamples (tSOLAD *w, float* in, float* out, int blocksize); |
| 117 | |||
| 118 | // set periodicity analysis data | 116 | // set periodicity analysis data |
| 119 | void tSOLAD_setPeriod (tSOLAD *w, float period); | 117 | void tSOLAD_setPeriod (tSOLAD *w, float period); |
| 120 | |||
| 121 | // set pitch factor between 0.25 and 4 | 118 | // set pitch factor between 0.25 and 4 |
| 122 | void tSOLAD_setPitchFactor (tSOLAD *w, float pitchfactor); | 119 | void tSOLAD_setPitchFactor (tSOLAD *w, float pitchfactor); |
| 123 | |||
| 124 | // force readpointer lag | 120 | // force readpointer lag |
| 125 | void tSOLAD_setReadLag (tSOLAD *w, float readlag); | 121 | void tSOLAD_setReadLag (tSOLAD *w, float readlag); |
| 126 | |||
| 127 | // reset state variables | 122 | // reset state variables |
| 128 | void tSOLAD_resetState (tSOLAD *w); | 123 | void tSOLAD_resetState (tSOLAD *w); |
| 129 | 124 | ||
| 130 | // Pitch shifter | 125 | // Pitch shift |
| 131 | typedef struct _tPitchShifter | 126 | typedef struct _tPitchShift |
| 132 | { | 127 | { |
| 133 | tEnvPD env; | ||
| 134 | tSNAC snac; | ||
| 135 | tSOLAD sola; | 128 | tSOLAD sola; |
| 136 | tHighpass hp; | 129 | tHighpass hp; |
| 130 | tPeriodDetection* p; | ||
| 137 | 131 | ||
| 138 | float* inBuffer; | ||
| 139 | float* outBuffer; | 132 | float* outBuffer; |
| 140 | int frameSize; | 133 | int frameSize; |
| 141 | int bufSize; | 134 | int bufSize; |
| 135 | |||
| 142 | int framesPerBuffer; | 136 | int framesPerBuffer; |
| 143 | int curBlock; | 137 | int curBlock; |
| 144 | int lastBlock; | 138 | int lastBlock; |
| 145 | int index; | 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 | uint16_t hopSize; | 165 | uint16_t hopSize; |
| 148 | uint16_t windowSize; | 166 | uint16_t windowSize; |
| 149 | uint8_t fba; | 167 | uint8_t fba; |
| 150 | 168 | ||
| 151 | float pitchFactor; | 169 | float* pitchFactor; |
| 152 | float timeConstant; | 170 | float timeConstant; |
| 153 | float radius; | 171 | float radius; |
| 154 | float max; | 172 | |
| 155 | float lastmax; | 173 | float inputPeriod; |
| 156 | float deltamax; | 174 | |
| 157 | 175 | int numVoices; | |
| 158 | } tPitchShifter; | 176 | } tRetune; |
| 159 | 177 | ||
| 160 | void tPitchShifter_init (tPitchShifter* const, float* in, float* out, int bufSize, int frameSize); | 178 | void tRetune_init (tRetune* const, int numVoices, int bufSize, int frameSize); |
| 161 | void tPitchShifter_free (tPitchShifter* const); | 179 | void tRetune_free (tRetune* const); |
| 162 | 180 | ||
| 163 | float tPitchShifter_tick (tPitchShifter* const, float sample); | 181 | float* tRetune_tick (tRetune* const, float sample); |
| 164 | float tPitchShifterToFreq_tick (tPitchShifter* const, float sample, float freq); | 182 | void tRetune_setNumVoices (tRetune* const, int numVoices); |
| 165 | float tPitchShifterToFunc_tick (tPitchShifter* const, float sample, float (*fun)(float)); | 183 | void tRetune_setPitchFactors (tRetune* const, float pf); |
| 166 | void tPitchShifter_ioSamples_toFreq (tPitchShifter* const, float* in, float* out, int size, float toFreq); | 184 | void tRetune_setPitchFactor (tRetune* const, float pf, int voice); |
| 167 | void tPitchShifter_ioSamples_toPeriod(tPitchShifter* const, float* in, float* out, int size, float toPeriod); | 185 | void tRetune_setTimeConstant (tRetune* const, float tc); |
| 168 | void tPitchShifter_ioSamples_toFunc (tPitchShifter* const, float* in, float* out, int size, float (*fun)(float)); | 186 | void tRetune_setHopSize (tRetune* const, int hs); |
| 169 | void tPitchShifter_setPitchFactor (tPitchShifter* const, float pf); | 187 | void tRetune_setWindowSize (tRetune* const, int ws); |
| 170 | void tPitchShifter_setTimeConstant (tPitchShifter* const, float tc); | 188 | float tRetune_getInputPeriod (tRetune* const); |
| 171 | void tPitchShifter_setHopSize (tPitchShifter* const, int hs); | 189 | float tRetune_getInputFreq (tRetune* const); |
| 172 | void tPitchShifter_setWindowSize (tPitchShifter* const, int ws); | 190 | |
| 173 | float tPitchShifter_getPeriod (tPitchShifter* const); | 191 | // Autotune |
| 174 | 192 | typedef struct _tAutotune | |
| 175 | //============================================================================== | ||
| 176 | |||
| 177 | // Pitch shift | ||
| 178 | typedef struct _tPitchShift | ||
| 179 | { | 193 | { |
| 180 | tSOLAD sola; | 194 | tPeriodDetection pd; |
| 181 | tHighpass hp; | 195 | tPitchShift* ps; |
| 182 | tPeriodDetection* p; | ||
| 183 | 196 | ||
| 184 | float* outBuffer; | 197 | float* inBuffer; |
| 198 | float** outBuffers; | ||
| 199 | float* tickOutput; | ||
| 185 | int frameSize; | 200 | int frameSize; |
| 186 | int bufSize; | 201 | int bufSize; |
| 187 | 202 | ||
| 188 | int framesPerBuffer; | 203 | uint16_t hopSize; |
| 189 | int curBlock; | 204 | uint16_t windowSize; |
| 190 | int lastBlock; | 205 | uint8_t fba; |
| 191 | int index; | ||
| 192 | 206 | ||
| 193 | float pitchFactor; | 207 | float* freq; |
| 194 | float timeConstant; | 208 | float timeConstant; |
| 195 | float radius; | 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); | 216 | void tAutotune_init (tAutotune* const, int numVoices, int bufSize, int frameSize); |
| 199 | void tPitchShift_free (tPitchShift* const); | 217 | void tAutotune_free (tAutotune* const); |
| 200 | 218 | ||
| 201 | float tPitchShift_shift (tPitchShift* const); | 219 | float* tAutotune_tick (tAutotune* const, float sample); |
| 202 | float tPitchShift_shiftToFunc (tPitchShift* const, float (*fun)(float)); | 220 | void tAutotune_setNumVoices (tAutotune* const, int numVoices); |
| 203 | float tPitchShift_shiftToFreq (tPitchShift* const, float freq); | 221 | void tAutotune_setFreq (tAutotune* const, float f, int voice); |
| 204 | void tPitchShift_setPitchFactor (tPitchShift* const, float pf); | 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 | #define FORD 7 | 231 | #define FORD 7 |
| 209 | #define FORMANT_BUFFER_SIZE 2048 | 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; | 410 | r->bufSize = bufSize; |
| 412 | ps->outBuffer = out; | 411 | r->frameSize = frameSize; |
| 413 | ps->bufSize = bufSize; | 412 | r->numVoices = numVoices; |
| 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; | ||
| 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); | 417 | r->hopSize = DEFHOPSIZE; |
| 427 | 418 | r->windowSize = DEFWINDOWSIZE; | |
| 428 | tSOLAD_init(&ps->sola); | 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); | 436 | tPeriodDetection_free(&r->pd); |
| 440 | tSNAC_free(&ps->snac); | 437 | for (int i = 0; i < r->numVoices; ++i) |
| 441 | tSOLAD_free(&ps->sola); | 438 | { |
| 442 | tHighpass_free(&ps->hp); | 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; | 449 | r->inputPeriod = tPeriodDetection_findPeriod(&r->pd, sample); |
| 448 | int i, iLast; | ||
| 449 | |||
| 450 | i = (ps->curBlock*ps->frameSize); | ||
| 451 | iLast = (ps->lastBlock*ps->frameSize)+ps->index; | ||
| 452 | 450 | ||
| 453 | out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]); | 451 | for (int v = 0; v < r->numVoices; ++v) |
| 454 | ps->inBuffer[i+ps->index] = sample; | ||
| 455 | |||
| 456 | ps->index++; | ||
| 457 | if (ps->index >= ps->frameSize) | ||
| 458 | { | 452 | { |
| 459 | ps->index = 0; | 453 | r->tickOutput[v] = tPitchShift_shift(&r->ps[v]); |
| 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 | |||
| 484 | } | 454 | } |
| 485 | 455 | ||
| 486 | return out; | 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; | 461 | for (int i = 0; i < r->numVoices; ++i) |
| 492 | int i, iLast; | 462 | { |
| 493 | 463 | tPitchShift_free(&r->ps[i]); | |
| 494 | i = (ps->curBlock*ps->frameSize); | 464 | leaf_free(r->outBuffers[i]); |
| 495 | iLast = (ps->lastBlock*ps->frameSize)+ps->index; | 465 | } |
| 466 | leaf_free(r->ps); | ||
| 467 | leaf_free(r->outBuffers); | ||
| 496 | 468 | ||
| 497 | out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]); | 469 | r->numVoices = numVoices; |
| 498 | ps->inBuffer[i+ps->index] = sample; | ||
| 499 | 470 | ||
| 500 | ps->index++; | 471 | r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices); |
| 501 | if (ps->index >= ps->frameSize) | 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; | 475 | r->outBuffers[i] = (float*) leaf_alloc(sizeof(float) * r->bufSize); |
| 504 | 476 | tPitchShift_init(&r->ps[i], &r->pd, r->outBuffers[i], r->bufSize); | |
| 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; | ||
| 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; | 484 | for (int i = 0; i < r->numVoices; ++i) |
| 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) | ||
| 544 | { | 485 | { |
| 545 | ps->index = 0; | 486 | r->pitchFactor[i] = pf; |
| 546 | 487 | tPitchShift_setPitchFactor(&r->ps[i], r->pitchFactor[i]); | |
| 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; | ||
| 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; | 493 | r->pitchFactor[voice] = pf; |
| 576 | 494 | tPitchShift_setPitchFactor(&r->ps[voice], r->pitchFactor[voice]); | |
| 577 | tEnvPD_processBlock(&ps->env, in); | 495 | } |
| 578 | 496 | ||
| 579 | if(pitchshifter_attackdetect(ps) == 1) | 497 | void tRetune_setTimeConstant(tRetune* const r, float tc) |
| 580 | { | 498 | { |
| 581 | ps->fba = 5; | 499 | r->timeConstant = tc; |
| 582 | tSOLAD_setReadLag(&ps->sola, ps->windowSize); | 500 | r->radius = expf(-1000.0f * r->hopSize * leaf.invSampleRate / r->timeConstant); |
| 583 | } | 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); | 535 | r->inBuffer = (float*) leaf_alloc(sizeof(float) * r->bufSize); |
| 586 | period = tSNAC_getPeriod(&ps->snac); | 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); | 543 | tPeriodDetection_init(&r->pd, r->inBuffer, r->outBuffers[0], r->bufSize, r->frameSize); |
| 591 | tSOLAD_ioSamples(&ps->sola, in, out, size); | ||
| 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; | 557 | tPeriodDetection_free(&r->pd); |
| 602 | 558 | for (int i = 0; i < r->numVoices; ++i) | |
| 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) | ||
| 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); | 572 | for (int v = 0; v < r->numVoices; ++v) |
| 630 | |||
| 631 | if(pitchshifter_attackdetect(ps) == 1) | ||
| 632 | { | 573 | { |
| 633 | ps->fba = 5; | 574 | r->tickOutput[v] = tPitchShift_shiftToFreq(&r->ps[v], r->freq[v]); |
| 634 | tSOLAD_setReadLag(&ps->sola, ps->windowSize); | ||
| 635 | } | 575 | } |
| 636 | 576 | ||
| 637 | tSNAC_ioSamples(&ps->snac, in, out, size); | 577 | return r->tickOutput; |
| 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 | } | ||
| 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; | 582 | for (int i = 0; i < r->numVoices; ++i) |
| 654 | |||
| 655 | tEnvPD_processBlock(&ps->env, in); | ||
| 656 | |||
| 657 | if(pitchshifter_attackdetect(ps) == 1) | ||
| 658 | { | 583 | { |
| 659 | ps->fba = 5; | 584 | tPitchShift_free(&r->ps[i]); |
| 660 | tSOLAD_setReadLag(&ps->sola, ps->windowSize); | 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); | 590 | r->numVoices = numVoices; |
| 664 | period = tSNAC_getPeriod(&ps->snac); | ||
| 665 | 591 | ||
| 666 | tSOLAD_setPeriod(&ps->sola, period); | 592 | r->outBuffers = (float**) leaf_alloc(sizeof(float*) * r->numVoices); |
| 667 | ps->pitchFactor = period/fun(period); | 593 | r->ps = (tPitchShift*) leaf_alloc(sizeof(tPitchShift) * r->numVoices); |
| 668 | tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor); | 594 | for (int i = 0; i < r->numVoices; ++i) |
| 669 | tSOLAD_ioSamples(&ps->sola, in, out, size); | ||
| 670 | |||
| 671 | for (int cc = 0; cc < size; ++cc) | ||
| 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; | 613 | r->timeConstant = tc; |
| 685 | ps->radius = expf(-1000.0f * ps->hopSize * leaf.invSampleRate / ps->timeConstant); | 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; | 636 | return 1.0f/r->inputPeriod; |
| 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; | ||
| 727 | } | 637 | } |
| 728 | 638 | ||
| 729 | |||
| 730 | //============================================================================================================ | 639 | //============================================================================================================ |
| 731 | // PITCHSHIFT | 640 | // PITCHSHIFT |
| 732 | //============================================================================================================ | 641 | //============================================================================================================ |
| @@ -735,7 +644,7 @@ static int pitchshift_attackdetect(tPitchShift* ps) · 2 unmodified lines | |||
| 735 | { | 644 | { |
| 736 | float envout; | 645 | float envout; |
| 737 | 646 | ||
| 738 | envout = tEnvPD_tick(&ps->p->env); | 647 | envout = tEnv_tick(&ps->p->env); |
| 739 | 648 | ||
| 740 | if (envout >= 1.0f) | 649 | if (envout >= 1.0f) |
| 741 | { | 650 | { |
| @@ -757,7 +666,7 @@ static int pitchshift_attackdetect(tPitchShift* ps) · 15 unmodified lines | |||
| 757 | return (ps->p->fba == 0 && (ps->p->max > 60 && ps->p->deltamax > 6)) ? 1 : 0; | 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 | ps->p = p; | 671 | ps->p = p; |
| 763 | 672 | ||