void run(int frameCount, float* outL, float* outR)
        {
            float originalFrequency = phs->freq;
            phs->freq *= kernel->detuningMultiplier;
            phs->freq += kernel->detuningOffset;
            phs->freq = clamp(phs->freq, 0.0f, 22050.0f);
            pdhalf->amount = kernel->phaseDistortion;

            adsr->atk = (float)kernel->attackDuration;
            adsr->dec = (float)kernel->decayDuration;
            adsr->sus = (float)kernel->sustainLevel;
            adsr->rel = (float)kernel->releaseDuration;

            for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {
                float temp = 0;
                float pd = 0;
                float ph = 0;
                sp_adsr_compute(kernel->sp, adsr, &internalGate, &amp);

                sp_phasor_compute(kernel->sp, phs, NULL, &ph);
                sp_pdhalf_compute(kernel->sp, pdhalf, &ph, &pd);
                tab->index = pd;
                sp_tabread_compute(kernel->sp, tab, NULL, &temp);

                *outL++ += velocityAmp * amp * temp;
                *outR++ += velocityAmp * amp * temp;
                
            }
            phs->freq = originalFrequency;
            if (stage == stageRelease && amp < 0.00001) {
                clear();
                remove();
            }
        }
    void process(AUAudioFrameCount frameCount, AUAudioFrameCount bufferOffset) override {

        for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) {

            int frameOffset = int(frameIndex + bufferOffset);
            
            startPoint = double(startPointRamper.getAndStep());
            endPoint = double(endPointRamper.getAndStep());
            rate = double(rateRamper.getAndStep());
            volume = double(volumeRamper.getAndStep());
            
            SPFLOAT dur = (SPFLOAT)ftbl_size / sp->sr;
            
            //length of playableSample vs actual
            int subsectionLength = endPoint - startPoint;
            float percentLen = (float)subsectionLength / (float)ftbl_size;
            phasor->freq = fabs(1.0 / dur  * rate / percentLen);
            
            for (int channel = 0; channel < channels; ++channel) {
                float *out = (float *)outBufferListPtr->mBuffers[channel].mData + frameOffset;
                if (started) {
                    if (channel == 0) {
                        sp_phasor_compute(sp, phasor, NULL, &position);
                        tabread1->index = position * percentLen + (startPoint / ftbl_size);
                        tabread2->index = position * percentLen + (startPoint / ftbl_size);
                        sp_tabread_compute(sp, tabread1, NULL, out);
                    } else {
                        sp_tabread_compute(sp, tabread2, NULL, out);
                    }
                    *out *= volume;
                } else {
                    *out = 0;
                }
            }
            if (!loop && position < lastPosition) {
                started = false;
                completionHandler();
            } else {
                lastPosition = position;
            }
        }
    }