Beispiel #1
0
void SkidderEditor::rateDisplayConvert(float value, char *string, void *temporatestring)
{
	if ( onOffTest(theTempoSync) )
	{
		strcpy(string, (char*)temporatestring);
		if (strlen(string) <= 3)
			strcat(string, "  cycles/beat");
	}
	else
		sprintf(string, "%.3f  Hz", rateScaled(value));
}
Beispiel #2
0
float SkidderEditor::calculateTheCycleRate()
{
  float tempoBPS;

	// tempo sync is being used
	if ( onOffTest(effect->getParameter(kTempoSync)) )
	{
		// "auto" mode; get the current tempo from the effect
		if ( effect->getParameter(kTempo) <= 0.0f )
			tempoBPS = ((Skidder*)effect)->currentTempoBPS;
		// otherwise use the user-inputted tempo
		else
			tempoBPS = tempoScaled(effect->getParameter(kTempo)) / 60.0f;
		return ( tempoBPS * (((Skidder*)effect)->tempoRateTable->getScalar(effect->getParameter(kTempoRate))) );
	}

	// tempo sync is not being used so just return the simple "free" rate value
	else
		return rateScaled(effect->getParameter(kRate));
}
Beispiel #3
0
//-----------------------------------------------------------------------------
void BufferOverride::updateBuffer(long samplePos)
{
    bool doSmoothing = true;	// but in some situations, we shouldn't
    bool barSync = false;	// true if we need to sync up with the next bar start
    float divisorLFOvalue, bufferLFOvalue;	// the current output values of the LFOs
    long prevForcedBufferSize;	// the previous forced buffer size


    // take care of MIDI
    heedBufferOverrideEvents(samplePos);

    readPos = 0;	// reset for starting a new minibuffer
    prevMinibufferSize = minibufferSize;
    prevForcedBufferSize = currentForcedBufferSize;

    //--------------------------PROCESS THE LFOs----------------------------
    // update the LFOs' positions to the current position
    divisorLFO->updatePosition(prevMinibufferSize);
    bufferLFO->updatePosition(prevMinibufferSize);
    // Then get the current output values of the LFOs, which also updates their positions once more.
    // Scale the 0.0 - 1.0 LFO output values to 0.0 - 2.0 (oscillating around 1.0).
    divisorLFOvalue = processLFOzero2two(divisorLFO);
    bufferLFOvalue = 2.0f - processLFOzero2two(bufferLFO);	// inverting it makes more pitch sense
    // & then update the stepSize for each LFO, in case the LFO parameters have changed
    if (onOffTest(divisorLFO->fTempoSync))
        divisorLFO->stepSize = currentTempoBPS * (tempoRateTable->getScalar(divisorLFO->fRate)) * numLFOpointsDivSR;
    else
        divisorLFO->stepSize = LFOrateScaled(divisorLFO->fRate) * numLFOpointsDivSR;
    if (onOffTest(bufferLFO->fTempoSync))
        bufferLFO->stepSize = currentTempoBPS * (tempoRateTable->getScalar(bufferLFO->fRate)) * numLFOpointsDivSR;
    else
        bufferLFO->stepSize = LFOrateScaled(bufferLFO->fRate) * numLFOpointsDivSR;

    //---------------------------CALCULATE FORCED BUFFER SIZE----------------------------
    // check if it's the end of this forced buffer
    if (writePos >= currentForcedBufferSize)
    {
        writePos = 0;	// start up a new forced buffer

        // check on the previous forced & minibuffers; don't smooth if the last forced buffer wasn't divided
        if (prevMinibufferSize >= currentForcedBufferSize)
            doSmoothing = false;
        else
            doSmoothing = true;

        // now update the the size of the current force buffer
        if ( onOffTest(fBufferTempoSync) &&	// the user wants to do tempo sync / beat division rate
                (currentTempoBPS > 0.0f) ) // avoid division by zero
        {
            currentForcedBufferSize = (long) ( SAMPLERATE / (currentTempoBPS * tempoRateTable->getScalar(fBuffer)) );
            // set this true so that we make sure to do the measure syncronisation later on
            if (needResync)
                barSync = true;
        }
        else
            currentForcedBufferSize = forcedBufferSizeSamples(fBuffer);
        // apply the buffer LFO to the forced buffer size
        currentForcedBufferSize = (long) ((float)currentForcedBufferSize * bufferLFOvalue);
        // really low tempos & tempo rate values can cause huge forced buffer sizes,
        // so prevent going outside of the allocated buffer space
        if (currentForcedBufferSize > SUPER_MAX_BUFFER)
            currentForcedBufferSize = SUPER_MAX_BUFFER;
        if (currentForcedBufferSize < 2)
            currentForcedBufferSize = 2;

        // untrue this so that we don't do the measure sync calculations again unnecessarily
        needResync = false;
    }

    //-----------------------CALCULATE THE DIVISOR-------------------------
    currentBufferDivisor = bufferDivisorScaled(fDivisor);
    // apply the divisor LFO to the divisor value if there's an "active" divisor (i.e. 2 or greater)
    if (currentBufferDivisor >= 2.0f)
    {
        currentBufferDivisor *= divisorLFOvalue;
        // now it's possible that the LFO could make the divisor less than 2,
        // which will essentially turn the effect off, so we stop the modulation at 2
        if (currentBufferDivisor < 2.0f)
            currentBufferDivisor = 2.0f;
    }

    //-----------------------CALCULATE THE MINIBUFFER SIZE-------------------------
    // this is not a new forced buffer starting up
    if (writePos > 0)
    {
        // if it's allowed, update the minibuffer size midway through this forced buffer
        if (onOffTest(fBufferInterrupt))
            minibufferSize = (long) ( (float)currentForcedBufferSize / currentBufferDivisor );
        // if it's the last minibuffer, then fill up the forced buffer to the end
        // by extending this last minibuffer to fill up the end of the forced buffer
        long remainingForcedBuffer = currentForcedBufferSize - writePos;
        if ( (minibufferSize*2) >= remainingForcedBuffer )
            minibufferSize = remainingForcedBuffer;
    }
    // this is a new forced buffer just beginning, act accordingly, do bar sync if necessary
    else
    {
        long samplesToBar;
        if (barSync)
        {
            samplesToBar = samplesToNextBar(timeInfo);
            // do beat sync for each LFO if it ought to be done
            if (onOffTest(divisorLFO->fTempoSync))
                divisorLFO->syncToTheBeat(samplesToBar);
            if (onOffTest(bufferLFO->fTempoSync))
                bufferLFO->syncToTheBeat(samplesToBar);
        }
        // because there isn't really any division (given my implementation) when the divisor is < 2
        if (currentBufferDivisor < 2.0f)
        {
            if (barSync)
                minibufferSize = currentForcedBufferSize = samplesToBar % currentForcedBufferSize;
            else
                minibufferSize = currentForcedBufferSize;
        }
        else
        {
            minibufferSize = (long) ( (float)currentForcedBufferSize / currentBufferDivisor );
            if (barSync)
            {
                // calculate how long this forced buffer needs to be
                long countdown = samplesToBar % currentForcedBufferSize;
                // update the forced buffer size & number of minibuffers so that
                // the forced buffers sync up with the musical measures of the song
                if ( countdown < (minibufferSize*2) )	// extend the buffer if it would be too short...
                    currentForcedBufferSize += countdown;
                else	// ...otherwise chop it down to the length of the extra bit needed to sync with the next measure
                    currentForcedBufferSize = countdown;
            }
        }
    }

    //-----------------------CALCULATE SMOOTHING DURATION-------------------------
    // no smoothing if the previous forced buffer wasn't divided
    if (!doSmoothing)
        smoothcount = smoothDur = 0;
    else
    {
        smoothDur = (long) (fSmooth * (float)minibufferSize);
        long maxSmoothDur;
        // if we're just starting a new forced buffer,
        // then the samples beyond the end of the previous one are not valid
        if (writePos <= 0)
            maxSmoothDur = prevForcedBufferSize - prevMinibufferSize;
        // otherwise just make sure that we don't go outside of the allocated arrays
        else
            maxSmoothDur = SUPER_MAX_BUFFER - prevMinibufferSize;
        if (smoothDur > maxSmoothDur)
            smoothDur = maxSmoothDur;
        smoothcount = smoothDur;
        smoothStep = 1.0f / (float)(smoothDur+1);	// the gain increment for each smoothing step

//		sqrtFadeIn = sqrtf(smoothStep);
//		sqrtFadeOut = sqrtf(1.0f - smoothStep);
//		smoothFract = smoothStep;

        fadeOutGain = cosf(PI/(float)(4*smoothDur));
        fadeInGain = sinf(PI/(float)(4*smoothDur));
        realFadePart = (fadeOutGain * fadeOutGain) - (fadeInGain * fadeInGain);	// cosf(3.141592/2/n)
        imaginaryFadePart = 2.0f * fadeOutGain * fadeInGain;	// sinf(3.141592/2/n)
    }
}
Beispiel #4
0
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
void BufferOverride::doTheProcess(float **inputs, float **outputs, long sampleFrames, bool replacing)
{

//-------------------------SAFETY CHECK----------------------
#if LINUX
    // no memory allocations during interrupt
#else
    // there must have not been available memory or something (like WaveLab goofing up),
    // so try to allocate buffers now
    if ( (buffer1 == NULL)
#ifdef BUFFEROVERRIDE_STEREO
            || (buffer2 == NULL)
#endif
       )
        createAudioBuffers();
#endif

    // if the creation failed, then abort audio processing
    if (buffer1 == NULL)
        return;
#ifdef BUFFEROVERRIDE_STEREO
    if (buffer2 == NULL)
        return;
#endif


//-------------------------INITIALIZATIONS----------------------
    // this is a handy value to have during LFO calculations & wasteful to recalculate at every sample
    numLFOpointsDivSR = NUM_LFO_POINTS_FLOAT / SAMPLERATE;
    divisorLFO->pickTheLFOwaveform();
    bufferLFO->pickTheLFOwaveform();

    // calculate this scaler value to minimize calculations later during processOutput()
//	float inputGain = 1.0f - fDryWetMix;
//	float outputGain = fDryWetMix;
    float inputGain = sqrtf(1.0f - fDryWetMix);
    float outputGain = sqrtf(fDryWetMix);


//-----------------------TEMPO STUFF---------------------------
    // figure out the current tempo if we're doing tempo sync
    if ( onOffTest(fBufferTempoSync) ||
            (onOffTest(divisorLFO->fTempoSync) || onOffTest(bufferLFO->fTempoSync)) )
    {
        // calculate the tempo at the current processing buffer
        if ( (fTempo > 0.0f) || (hostCanDoTempo != 1) )	// get the tempo from the user parameter
        {
            currentTempoBPS = tempoScaled(fTempo) / 60.0f;
            needResync = false;	// we don't want it true if we're not syncing to host tempo
        }
        else	// get the tempo from the host
        {
            timeInfo = getTimeInfo(kBeatSyncTimeInfoFlags);
            if (timeInfo)
            {
                if (kVstTempoValid & timeInfo->flags)
                    currentTempoBPS = (float)timeInfo->tempo / 60.0f;
                else
                    currentTempoBPS = tempoScaled(fTempo) / 60.0f;
//				currentTempoBPS = ((float)tempoAt(reportCurrentPosition())) / 600000.0f;
                // but zero & negative tempos are bad, so get the user tempo value instead if that happens
                if (currentTempoBPS <= 0.0f)
                    currentTempoBPS = tempoScaled(fTempo) / 60.0f;
                //
                // check if audio playback has just restarted & reset buffer stuff if it has (for measure sync)
                if (timeInfo->flags & kVstTransportChanged)
                {
                    needResync = true;
                    currentForcedBufferSize = 1;
                    writePos = 1;
                    minibufferSize = 1;
                    prevMinibufferSize = 0;
                    smoothcount = smoothDur = 0;
                }
            }
            else	// do the same stuff as above if the timeInfo gets a null pointer
            {
                currentTempoBPS = tempoScaled(fTempo) / 60.0f;
                needResync = false;	// we don't want it true if we're not syncing to host tempo
            }
        }
    }


//-----------------------AUDIO STUFF---------------------------
    // here we begin the audio output loop, which has two checkpoints at the beginning
    for (long samplecount = 0; (samplecount < sampleFrames); samplecount++)
    {
        // check if it's the end of this minibuffer
        if (readPos >= minibufferSize)
            updateBuffer(samplecount);

        // store the latest input samples into the buffers
        buffer1[writePos] = inputs[0][samplecount];
#ifdef BUFFEROVERRIDE_STEREO
        buffer2[writePos] = inputs[1][samplecount];
#endif

        // get the current output without any smoothing
        float out1 = buffer1[readPos];
#ifdef BUFFEROVERRIDE_STEREO
        float out2 = buffer2[readPos];
#endif

        // and if smoothing is taking place, get the smoothed audio output
        if (smoothcount > 0)
        {
            // crossfade between the current input & its corresponding overlap sample
//			out1 *= 1.0f - (smoothStep * (float)smoothcount);	// current
//			out1 += buffer1[readPos+prevMinibufferSize] * smoothStep*(float)smoothcount;	// + previous
//			float smoothfract = smoothStep * (float)smoothcount;
//			float newgain = sqrt(1.0f - smoothfract);
//			float oldgain = sqrt(smoothfract);
//			out1 = (out1 * newgain) + (buffer1[readPos+prevMinibufferSize] * oldgain);
//			out1 = (out1 * sqrtFadeIn) + (buffer1[readPos+prevMinibufferSize] * sqrtFadeOut);
            out1 = (out1 * fadeInGain) + (buffer1[readPos+prevMinibufferSize] * fadeOutGain);
#ifdef BUFFEROVERRIDE_STEREO
//			out2 *= 1.0f - (smoothStep * (float)smoothcount);	// current
//			out2 += buffer2[readPos+prevMinibufferSize] * smoothStep*(float)smoothcount;	// + previous
//			out2 = (out2 * newgain) + (buffer2[readPos+prevMinibufferSize] * oldgain);
//			out2 = (out2 * sqrtFadeIn) + (buffer2[readPos+prevMinibufferSize] * sqrtFadeOut);
            out2 = (out2 * fadeInGain) + (buffer2[readPos+prevMinibufferSize] * fadeOutGain);
#endif
            smoothcount--;
//			smoothFract += smoothStep;
//			sqrtFadeIn = 0.5f * (sqrtFadeIn + (smoothFract / sqrtFadeIn));
//			sqrtFadeOut = 0.5f * (sqrtFadeOut + ((1.0f-smoothFract) / sqrtFadeOut));
            fadeInGain = (fadeOutGain * imaginaryFadePart) + (fadeInGain * realFadePart);
            fadeOutGain = (realFadePart * fadeOutGain) - (imaginaryFadePart * fadeInGain);
        }

        // write the output samples into the output stream
        if (replacing)
        {
            outputs[0][samplecount] = (out1 * outputGain) + (inputs[0][samplecount] * inputGain);
#ifdef BUFFEROVERRIDE_STEREO
            outputs[1][samplecount] = (out2 * outputGain) + (inputs[1][samplecount] * inputGain);
#endif
        }
        else
        {
            outputs[0][samplecount] += (out1 * outputGain) + (inputs[0][samplecount] * inputGain);
#ifdef BUFFEROVERRIDE_STEREO
            outputs[1][samplecount] += (out2 * outputGain) + (inputs[1][samplecount] * inputGain);
#endif
        }

        // increment the position trackers
        readPos++;
        writePos++;
    }


//-----------------------MIDI STUFF---------------------------
    // check to see if there may be a note or pitchbend message left over that hasn't been implemented
    if (midistuff->numBlockEvents > 0)
    {
        long eventcount;
        for (eventcount = 0; eventcount < midistuff->numBlockEvents; eventcount++)
        {
            if (isNote(midistuff->blockEvents[eventcount].status))
            {
                // regardless of whether it's a note-on or note-off, we've found some note message
                oldNote = true;
                // store the note & update the notes table if it's a note-on message
                if (midistuff->blockEvents[eventcount].status == kMidiNoteOn)
                {
                    midistuff->insertNote(midistuff->blockEvents[eventcount].byte1);
                    lastNoteOn = midistuff->blockEvents[eventcount].byte1;
                    // since we're not doing the fDivisor updating yet, this needs to be falsed
                    divisorWasChangedByHand = false;
                }
                // otherwise remove the note from the notes table
                else
                    midistuff->removeNote(midistuff->blockEvents[eventcount].byte1);
            }
            else if (midistuff->blockEvents[eventcount].status == ccAllNotesOff)
            {
                oldNote = true;
                midistuff->removeAllNotes();
            }
        }
        for (eventcount = (midistuff->numBlockEvents-1); (eventcount >= 0); eventcount--)
        {
            if (midistuff->blockEvents[eventcount].status == kMidiPitchbend)
            {
                // set this pitchbend message as lastPitchbend
                lastPitchbend = midistuff->blockEvents[eventcount].byte2;
                break;	// leave this for loop
            }
        }
    }

    // always reset numBlockEvents because processEvents() may not get called before the next process()
    midistuff->numBlockEvents = 0;
}
Beispiel #5
0
//-----------------------------------------------------------------------------
// called from SkidderEdit
void SkidderEditor::setParameter(long index, float value)
{
	if (!frame)
		return;

	long rateTag = onOffTest(effect->getParameter(kTempoSync)) ? kTempoRate : kRate;

	switch (index)
	{
		case kRate:
		case kTempoRate:
			// store these into the static global variables so that the string convert function can see them
			theCycleRate = calculateTheCycleRate();
			strcpy( tempoRateString, ((Skidder*)effect)->tempoRateTable->getDisplay(effect->getParameter(kTempoRate)) );
			theTempoSync = ((Skidder*)effect)->fTempoSync;
			if (rateTag == index)
			{
				if (rateFader)
					rateFader->setValue(value);
				if (rateDisplay)
					rateDisplay->setValue(value);
				// update the rate random range display
				if (rateRandRangeDisplay)
					rateRandRangeDisplay->setDirty();
			}
			break;

		case kTempoSync:
			strcpy( tempoRateString, ((Skidder*)effect)->tempoRateTable->getDisplay(effect->getParameter(kTempoRate)) );
			theTempoSync = ((Skidder*)effect)->fTempoSync;
			theCycleRate = calculateTheCycleRate();
			if (tempoSyncButton)
				tempoSyncButton->setValue(value);
			// update the rate displays if the sync mode is changed
			if (rateRandRangeDisplay)
				rateRandRangeDisplay->setDirty();
			// see if we need to swap the parameter assignment for the rate controls
			if (rateFader)
			{
				if (rateTag != rateFader->getTag())
				{
					rateFader->setTag(rateTag);
					rateFader->setValue(effect->getParameter(rateTag));
				}
			}
			if (rateDisplay)
			{
				if (rateTag != rateDisplay->getTag())
				{
					rateDisplay->setTag(rateTag);
					rateDisplay->setValue(effect->getParameter(rateTag));
					rateDisplay->setDirty();
				}
			}
			break;

		case kRateRandFactor:
			theCycleRate = calculateTheCycleRate();
			if (rateRandFactorFader)
				rateRandFactorFader->setValue(value);
			if (rateRandFactorDisplay)
				rateRandFactorDisplay->setValue(value);
			if (rangeDisplay)
				rangeDisplay->setValue(value);
			if (rateRandRangeDisplay)
			{
				rateRandRangeDisplay->setValue(value);
				// makes the rate random range display disappear when there's no rate randomness
				if ( effect->getParameter(kRateRandFactor) <= 0.0003f )
				{
					rateRandRangeDisplay->setBackColor(kBackgroundCColor);
					rateRandRangeDisplay->setFrameColor(kBackgroundCColor);
				}
				else
				{
					rateRandRangeDisplay->setBackColor(kMyPaleGreenCColor);
					rateRandRangeDisplay->setFrameColor(kBlackCColor);
				}
				rateRandRangeDisplay->setDirty();
			}
			break;

		case kTempo:
			theCycleRate = calculateTheCycleRate();
			if (tempoFader)
				tempoFader->setValue(value);
			if (tempoTextEdit)
			{
				if ( (value > 0.0f) || (((Skidder*)effect)->hostCanDoTempo != 1) )
					sprintf(tempoString, "%.3f  bpm", tempoScaled(value));
				else
					strcpy(tempoString, "auto");
				tempoTextEdit->setText(tempoString);
			}
			// update the rate random range display
			// (this crashes for some reason?)
//			if (rateRandRangeDisplay)
//				rateRandRangeDisplay->setDirty();
			break;

		case kPulsewidth:
			if (pulsewidthFader)
				pulsewidthFader->setValueTagged(index, value);
			if (pulsewidthDisplay)
				pulsewidthDisplay->setValue(value);
			if (randomMinimumDisplay)
				randomMinimumDisplay->setValue(effect->getParameter(kPulsewidthRandMin));
			if (pulsewidthRandMinDisplay)
				pulsewidthRandMinDisplay->setValue(effect->getParameter(kPulsewidthRandMin));
			// because the regular pulsewidth can affect the random's read-out
			if (pulsewidthRandMinDisplay)
				pulsewidthRandMinDisplay->setDirty();
			if (randomMinimumDisplay)
				randomMinimumDisplay->setDirty();
			break;

		case kPulsewidthRandMin:
			if (pulsewidthFader)
				pulsewidthFader->setValueTagged(index, value);
			if (pulsewidthRandMinDisplay)
				pulsewidthRandMinDisplay->setValue(value);
			if (randomMinimumDisplay)
				randomMinimumDisplay->setValue(value);
			if (pulsewidthDisplay)
				pulsewidthDisplay->setValue(effect->getParameter(kPulsewidth));
			break;

		case kSlope:
			if (slopeFader)
				slopeFader->setValue(value);
			if (slopeDisplay)
				slopeDisplay->setValue(value);
			break;

		case kFloor:
			if (floorFader)
				floorFader->setValueTagged(index, value);
			if (floorDisplay)
				floorDisplay->setValue(value);
			// because the regular floor can affect the random's read-out
			if (floorRandMinDisplay)
				floorRandMinDisplay->setDirty();
			if (randomMinimum2Display)
				randomMinimum2Display->setDirty();
			break;

		case kFloorRandMin:
			if (floorFader)
				floorFader->setValueTagged(index, value);
			if (floorRandMinDisplay)
				floorRandMinDisplay->setValue(value);
			if (randomMinimum2Display)
				randomMinimum2Display->setValue(value);
			break;

		case kPan:
			if (panFader)
				panFader->setValue(value);
			if (panDisplay)
				panDisplay->setValue(value);
			break;

		case kNoise:
			if (noiseFader)
				noiseFader->setValue(value);
			if (noiseDisplay)
				noiseDisplay->setValue(value);
			break;

	#ifdef MSKIDDER
		case kMidiMode:
			if (midiModeButton)
				midiModeButton->setValue(value);
			break;
		case kVelocity:
			if (velocityButton)
				velocityButton->setValue(value);
			break;
	#ifdef HUNGRY
		case kConnect:
			if (connectButton)
				connectButton->setValue(value);
			if (connectDisplay)
				connectDisplay->setValue(value);
			break;
	#endif
	#endif

		default:
			return;
	}

	postUpdate();
}
Beispiel #6
0
//-----------------------------------------------------------------------------
long SkidderEditor::open(void *ptr)
{
  CPoint displayOffset;	// for positioning the background graphic behind display boxes


	// !!! always call this !!!
	AEffGUIEditor::open(ptr);

	// load some bitmaps
	if (!gFaderSlide)
		gFaderSlide = new CBitmap (kFaderSlideID);

	if (!gFaderHandle)
		gFaderHandle = new CBitmap (kFaderHandleID);
	if (!gGlowingFaderHandle)
		gGlowingFaderHandle = new CBitmap (kGlowingFaderHandleID);
	if (!gFaderHandleLeft)
		gFaderHandleLeft = new CBitmap (kFaderHandleLeftID);
	if (!gGlowingFaderHandleLeft)
		gGlowingFaderHandleLeft = new CBitmap (kGlowingFaderHandleLeftID);
	if (!gFaderHandleRight)
		gFaderHandleRight = new CBitmap (kFaderHandleRightID);
	if (!gGlowingFaderHandleRight)
		gGlowingFaderHandleRight = new CBitmap (kGlowingFaderHandleRightID);

	if (!gTempoSyncButton)
		gTempoSyncButton = new CBitmap (kTempoSyncButtonID);

	if (!gMidiLearnButton)
		gMidiLearnButton = new CBitmap (kMidiLearnButtonID);
	if (!gMidiResetButton)
		gMidiResetButton = new CBitmap (kMidiResetButtonID);

	if (!gGoButton)
		gGoButton = new CBitmap (kGoButtonID);
	if (!gDestroyFXlink)
		gDestroyFXlink = new CBitmap (kDestroyFXlinkID);
	if (!gSmartElectronixLink)
		gSmartElectronixLink = new CBitmap (kSmartElectronixLinkID);

#ifdef MSKIDDER
	if (!gMidiModeButton)
		gMidiModeButton = new CBitmap (kMidiModeButtonID);
	if (!gVelocityButton)
		gVelocityButton = new CBitmap (kVelocityButtonID);
#ifdef HUNGRY
	if (!gConnectButton)
		gConnectButton = new CBitmap (kConnectButtonID);
#endif
#endif


	chunk->resetLearning();
	goError = kNoGoDisplay;
	long rateTag = onOffTest(effect->getParameter(kTempoSync)) ? kTempoRate : kRate;


	//--initialize the background frame--------------------------------------
	CRect size (0, 0, gBackground->getWidth(), gBackground->getHeight());
	frame = new CFrame (size, ptr, this);
	frame->setBackground(gBackground);


	//--initialize the faders-----------------------------------------------
	int minPos = kFaderX;
	int maxPos = kFaderX + gFaderSlide->getWidth() - gFaderHandle->getWidth() - 1;
	CPoint point (0, 0);
	CPoint offset (0, 1);

	// rate   (single slider for "free" Hz rate & tempo synced rate)
	// size stores left, top, right, & bottom positions
	size (kFaderX, kFaderY, kFaderX + gFaderSlide->getWidth(), kFaderY + gFaderSlide->getHeight());
	rateFader = new CHorizontalSlider (size, this, rateTag, minPos, maxPos, gFaderHandle, gFaderSlide, point, kLeft);
	rateFader->setOffsetHandle(offset);
	rateFader->setValue(effect->getParameter(rateTag));
	rateFader->setDefaultValue(rateUnscaled(3.0f));
	frame->addView(rateFader);

	// rate random factor
	size.offset (0, kFaderInc);
	rateRandFactorFader = new CHorizontalSlider (size, this, kRateRandFactor, minPos, maxPos, gFaderHandle, gFaderSlide, point, kLeft);
	rateRandFactorFader->setOffsetHandle(offset);
	rateRandFactorFader->setValue(effect->getParameter(kRateRandFactor));
	rateRandFactorFader->setDefaultValue(0.0f);
	frame->addView(rateRandFactorFader);

	// tempo (in bpm)
	size.offset (0, kFaderInc);
	tempoFader = new CHorizontalSlider (size, this, kTempo, minPos, maxPos, gFaderHandle, gFaderSlide, point, kLeft);
	tempoFader->setOffsetHandle(offset);
	tempoFader->setValue(effect->getParameter(kTempo));
	tempoFader->setDefaultValue(0.0f);
	frame->addView(tempoFader);

	int minRPos = kFaderX;
	int maxRPos = kFaderX + gFaderSlide->getWidth();
	// pulsewidth
	size.offset (0, kFaderInc);
	pulsewidthFader = new CHorizontalRangeSlider (size, this, kPulsewidthRandMin, kPulsewidth, minRPos, maxRPos, gFaderHandleLeft, gFaderSlide, point, kLeft, kMaxCanPush, gFaderHandleRight);
	pulsewidthFader->setOffsetHandle(point);
	pulsewidthFader->setValueTagged(kPulsewidth, effect->getParameter(kPulsewidth));
	pulsewidthFader->setValueTagged(kPulsewidthRandMin, effect->getParameter(kPulsewidthRandMin));
	pulsewidthFader->setDefaultValueTagged(kPulsewidth, 0.5f);
	pulsewidthFader->setDefaultValueTagged(kPulsewidthRandMin, 0.5f);
	frame->addView(pulsewidthFader);

	// slope
	size.offset (0, kFaderInc);
	slopeFader = new CHorizontalSlider (size, this, kSlope, minPos, maxPos, gFaderHandle, gFaderSlide, point, kLeft);
	slopeFader->setOffsetHandle(offset);
	slopeFader->setValue(effect->getParameter(kSlope));
	slopeFader->setDefaultValue(3.0f/SLOPEMAX);
	frame->addView(slopeFader);

	// floor
	size.offset (0, kFaderInc);
	floorFader = new CHorizontalRangeSlider (size, this, kFloorRandMin, kFloor, minRPos, maxRPos, gFaderHandleLeft, gFaderSlide, point, kLeft, kMaxCanPush, gFaderHandleRight);
	floorFader->setOffsetHandle(point);
	floorFader->setValueTagged(kFloor, effect->getParameter(kFloor));
	floorFader->setValueTagged(kFloorRandMin, effect->getParameter(kFloorRandMin));
	floorFader->setDefaultValueTagged(kFloor, 0.0f);
	floorFader->setDefaultValueTagged(kFloorRandMin, 0.0f);
	frame->addView(floorFader);

	// pan
	size.offset (0, kFaderInc);
	panFader = new CHorizontalSlider (size, this, kPan, minPos, maxPos, gFaderHandle, gFaderSlide, point, kLeft);
	panFader->setOffsetHandle(offset);
	panFader->setValue(effect->getParameter(kPan));
	panFader->setDefaultValue(0.6f);
	frame->addView(panFader);

	// noise
	size.offset (0, kFaderInc);
	noiseFader = new CHorizontalSlider (size, this, kNoise, minPos, maxPos, gFaderHandle, gFaderSlide, point, kLeft);
	noiseFader->setOffsetHandle(offset);
	noiseFader->setValue(effect->getParameter(kNoise));
	noiseFader->setDefaultValue(1.0f);
	frame->addView(noiseFader);


	//--initialize the buttons----------------------------------------------

	// choose the rate type ("free" or synced)
	size (kTempoSyncButtonX, kTempoSyncButtonY, kTempoSyncButtonX + gTempoSyncButton->getWidth(), kTempoSyncButtonY + (gTempoSyncButton->getHeight())/2);
	tempoSyncButton = new COnOffButton (size, this, kTempoSync, gTempoSyncButton);
	tempoSyncButton->setValue(effect->getParameter(kTempoSync));
	frame->addView(tempoSyncButton);

	// go!
	// size stores left, top, right, & bottom positions
	size (kGoButtonX, kGoButtonY, kGoButtonX + gGoButton->getWidth(), kGoButtonY + (gGoButton->getHeight())/2);
	goButton = new CWebLink (size, this, kGoButtonID, "http://www.whirledbank.org/", gGoButton);
	frame->addView(goButton);

	// Destroy FX web page link
	size (kDestroyFXlinkX, kDestroyFXlinkY, kDestroyFXlinkX + gDestroyFXlink->getWidth(), kDestroyFXlinkY + (gDestroyFXlink->getHeight())/2);
	DestroyFXlink = new CWebLink (size, this, kDestroyFXlinkID, DESTROYFX_URL, gDestroyFXlink);
	frame->addView(DestroyFXlink);

	// Smart Electronix web page link
	size (kSmartElectronixLinkX, kSmartElectronixLinkY, kSmartElectronixLinkX + gSmartElectronixLink->getWidth(), kSmartElectronixLinkY + (gSmartElectronixLink->getHeight())/2);
	SmartElectronixLink = new CWebLink (size, this, kSmartElectronixLinkID, SMARTELECTRONIX_URL, gSmartElectronixLink);
	frame->addView(SmartElectronixLink);

#ifdef MSKIDDER
	// MIDI note control mode button
	size (kMidiModeButtonX, kMidiModeButtonY, kMidiModeButtonX + gMidiModeButton->getWidth(), kMidiModeButtonY + (gMidiModeButton->getHeight())/NUM_MIDI_MODES);
	midiModeButton = new CMultiToggle (size, this, kMidiMode, NUM_MIDI_MODES, gMidiModeButton->getHeight()/NUM_MIDI_MODES, gMidiModeButton, point);
	midiModeButton->setValue(effect->getParameter(kMidiMode));
	frame->addView(midiModeButton);

	// use-note-velocity button
	size (kVelocityButtonX, kVelocityButtonY, kVelocityButtonX + gVelocityButton->getWidth(), kVelocityButtonY + (gVelocityButton->getHeight())/2);
	velocityButton = new COnOffButton (size, this, kVelocity, gVelocityButton);
	velocityButton->setValue(effect->getParameter(kVelocity));
	frame->addView(velocityButton);

	// turn on/off MIDI learn mode for CC parameter automation
	size (kMidiLearnButtonX, kMidiLearnButtonY, kMidiLearnButtonX + gMidiLearnButton->getWidth(), kMidiLearnButtonY + (gMidiLearnButton->getHeight())/2);
	midiLearnButton = new COnOffButton (size, this, kMidiLearnButtonID, gMidiLearnButton);
	midiLearnButton->setValue(0.0f);
	frame->addView(midiLearnButton);

	// clear all MIDI CC assignments
	size (kMidiResetButtonX, kMidiResetButtonY, kMidiResetButtonX + gMidiResetButton->getWidth(), kMidiResetButtonY + (gMidiResetButton->getHeight())/2);
	midiResetButton = new CKickButton (size, this, kMidiResetButtonID, (gMidiResetButton->getHeight())/2, gMidiResetButton, point);
	midiResetButton->setValue(0.0f);
	frame->addView(midiResetButton);

#ifdef HUNGRY
	if ( ((Skidder*)effect)->foodEater->hostIsLogic )
	{
		// connect to food
		size (kConnectButtonX, kConnectButtonY, kConnectButtonX + gConnectButton->getWidth(), kConnectButtonY + (gConnectButton->getHeight())/2);
		connectButton = new COnOffButton (size, this, kConnect, gConnectButton);
		connectButton->setValue(effect->getParameter(kConnect));
		frame->addView(connectButton);
	}
#endif

#endif


	//--initialize the displays---------------------------------------------

	// first store the proper values for all of the globals so that displays are correct
	strcpy( tempoRateString, ((Skidder*)effect)->tempoRateTable->getDisplay(effect->getParameter(kTempoRate)) );
	theTempoSync = ((Skidder*)effect)->fTempoSync;
	theCycleRate = calculateTheCycleRate();

	// rate   (unified display for "free" Hz rate & tempo synced rate)
	size (kDisplayX, kDisplayY, kDisplayX + kDisplayWidth, kDisplayY + kDisplayHeight);
	rateDisplay = new CParamDisplay (size, gBackground);
	displayOffset (kDisplayX, kDisplayY);
	rateDisplay->setBackOffset(displayOffset);
	rateDisplay->setHoriAlign(kLeftText);
	rateDisplay->setFont(kNormalFontSmall);
	rateDisplay->setFontColor(kWhiteCColor);
	rateDisplay->setValue(effect->getParameter(rateTag));
	rateDisplay->setStringConvert(rateDisplayConvert, tempoRateString);
	rateDisplay->setTag(rateTag);
	frame->addView(rateDisplay);

	// rate random factor
	size.offset (0, kFaderInc);
	rateRandFactorDisplay = new CParamDisplay (size, gBackground);
	displayOffset (kDisplayX, kDisplayY);
	rateRandFactorDisplay->setBackOffset(displayOffset);
	rateRandFactorDisplay->setHoriAlign(kLeftText);
	rateRandFactorDisplay->setFont(kNormalFontSmall);
	rateRandFactorDisplay->setFontColor(kWhiteCColor);
	rateRandFactorDisplay->setValue(effect->getParameter(kRateRandFactor));
	rateRandFactorDisplay->setStringConvert(rateRandFactorDisplayConvert);
	rateRandFactorDisplay->setTag(kRateRandFactor);
	frame->addView(rateRandFactorDisplay);

	// tempo (in bpm)   (editable)
	size.offset (0, kFaderInc);
	tempoTextEdit = new CTextEdit (size, this, kTempoTextEdit, 0, gBackground);
	displayOffset.offset (0, kFaderInc);
	tempoTextEdit->setBackOffset(displayOffset);
	tempoTextEdit->setFont (kNormalFontSmall);
	tempoTextEdit->setFontColor (kWhiteCColor);
	tempoTextEdit->setHoriAlign (kLeftText);
	frame->addView (tempoTextEdit);
	// this makes it display the current value
	setParameter(kTempo, effect->getParameter(kTempo));

	// pulsewidth
	size.offset (0, kFaderInc - 1);
	pulsewidthDisplay = new CNumberBox (size, this, kPulsewidth, gBackground, 0, kVertical);
	displayOffset.offset (0, kFaderInc - 1);
	pulsewidthDisplay->setBackOffset(displayOffset);
	pulsewidthDisplay->setHoriAlign(kLeftText);
	pulsewidthDisplay->setFont(kNormalFontSmall);
	pulsewidthDisplay->setFontColor(kWhiteCColor);
	pulsewidthDisplay->setValue(effect->getParameter(kPulsewidth));
	pulsewidthDisplay->setStringConvert(pulsewidthDisplayConvert);
	pulsewidthDisplay->setTag(kPulsewidth);
	frame->addView(pulsewidthDisplay);

	// pulsewidth random minimum
	size.offset (1, kRandomMinimumIncY + 1);
	pulsewidthRandMinDisplay = new CParamDisplay (size, gBackground);
	displayOffset.offset (1, kRandomMinimumIncY + 1);
	pulsewidthRandMinDisplay->setBackOffset(displayOffset);
	pulsewidthRandMinDisplay->setHoriAlign(kLeftText);
	pulsewidthRandMinDisplay->setFont(kNormalFontVerySmall);
	pulsewidthRandMinDisplay->setFontColor(kWhiteCColor);
	pulsewidthRandMinDisplay->setValue(effect->getParameter(kPulsewidthRandMin));
	pulsewidthRandMinDisplay->setStringConvert( pulsewidthRandMinDisplayConvert, &(((Skidder*)effect)->fPulsewidth) );
	pulsewidthRandMinDisplay->setTag(kPulsewidthRandMin);
	frame->addView(pulsewidthRandMinDisplay);

	// the words "random minimum"
	size (kRandomMinimumX, kDisplayY + (kFaderInc*3) + kRandomMinimumIncY, kRandomMinimumX + kRandomMinimumWidth, kDisplayY + (kFaderInc*3) + kRandomMinimumIncY + kDisplayHeight);
	randomMinimumDisplay = new CParamDisplay (size, gBackground);
	displayOffset (kRandomMinimumX, kDisplayY + (kFaderInc*4) + kRandomMinimumIncY + 1);
	randomMinimumDisplay->setBackOffset(displayOffset);
	randomMinimumDisplay->setHoriAlign(kRightText);
	randomMinimumDisplay->setFont(kNormalFontVerySmall);
	randomMinimumDisplay->setFontColor(kWhiteCColor);
	randomMinimumDisplay->setValue(effect->getParameter(kPulsewidthRandMin));
	randomMinimumDisplay->setStringConvert( randomMinimumDisplayConvert, &(((Skidder*)effect)->fPulsewidth) );
	randomMinimumDisplay->setTag(kPulsewidthRandMin);
	frame->addView(randomMinimumDisplay);

	// slope
	size (kDisplayX, kDisplayY + (kFaderInc*4), kDisplayX + kDisplayWidth, kDisplayY + (kFaderInc*4) + kDisplayHeight);
	slopeDisplay = new CParamDisplay (size, gBackground);
	displayOffset (kDisplayX, kDisplayY + (kFaderInc*5));
	slopeDisplay->setBackOffset(displayOffset);
	slopeDisplay->setHoriAlign(kLeftText);
	slopeDisplay->setFont(kNormalFontSmall);
	slopeDisplay->setFontColor(kWhiteCColor);
	slopeDisplay->setValue(effect->getParameter(kSlope));
	slopeDisplay->setStringConvert(slopeDisplayConvert);
	frame->addView(slopeDisplay);

	// floor
	size.offset (0, kFaderInc - 1);
	floorDisplay = new CParamDisplay (size, gBackground);
	displayOffset.offset (0, kFaderInc - 1);
	floorDisplay->setBackOffset(displayOffset);
	floorDisplay->setHoriAlign(kLeftText);
	floorDisplay->setFont(kNormalFontSmall);
	floorDisplay->setFontColor(kWhiteCColor);
	floorDisplay->setValue(effect->getParameter(kFloor));
	floorDisplay->setStringConvert(floorDisplayConvert);
	frame->addView(floorDisplay);

	// floor random minimum
	size.offset (1, kRandomMinimumIncY + 1);
	floorRandMinDisplay = new CParamDisplay (size, gBackground);
	displayOffset.offset (1, kRandomMinimumIncY + 1);
	floorRandMinDisplay->setBackOffset(displayOffset);
	floorRandMinDisplay->setHoriAlign(kLeftText);
	floorRandMinDisplay->setFont(kNormalFontVerySmall);
	floorRandMinDisplay->setFontColor(kWhiteCColor);
	floorRandMinDisplay->setValue(effect->getParameter(kFloorRandMin));
	floorRandMinDisplay->setStringConvert( floorRandMinDisplayConvert, &(((Skidder*)effect)->fFloor) );
	floorRandMinDisplay->setTag(kFloorRandMin);
	frame->addView(floorRandMinDisplay);

	// the words "random minimum" again
	size (kRandomMinimumX, kDisplayY + (kFaderInc*5) + kRandomMinimumIncY, kRandomMinimumX + kRandomMinimumWidth, kDisplayY + (kFaderInc*5) + kRandomMinimumIncY + kDisplayHeight);
	randomMinimum2Display = new CParamDisplay (size, gBackground);
	displayOffset (kRandomMinimumX, kDisplayY + (kFaderInc*6) + kRandomMinimumIncY + 1);
	randomMinimum2Display->setBackOffset(displayOffset);
	randomMinimum2Display->setHoriAlign(kRightText);
	randomMinimum2Display->setFont(kNormalFontVerySmall);
	randomMinimum2Display->setFontColor(kWhiteCColor);
	randomMinimum2Display->setValue(effect->getParameter(kFloorRandMin));
	randomMinimum2Display->setStringConvert( randomMinimumDisplayConvert, &(((Skidder*)effect)->fFloor) );
	randomMinimum2Display->setTag(kFloorRandMin);
	frame->addView(randomMinimum2Display);

	// pan
	size (kDisplayX, kDisplayY + (kFaderInc*6), kDisplayX + kDisplayWidth, kDisplayY + (kFaderInc*6) + kDisplayHeight);
	panDisplay = new CParamDisplay (size, gBackground);
	displayOffset.offset (0, kFaderInc);
	panDisplay->setBackOffset(displayOffset);
	panDisplay->setHoriAlign(kLeftText);
	panDisplay->setFont(kNormalFontSmall);
	panDisplay->setFontColor(kWhiteCColor);
	panDisplay->setValue(effect->getParameter(kPan));
	panDisplay->setStringConvert(panDisplayConvert);
	frame->addView(panDisplay);

	// noise
	size.offset (0, kFaderInc);
	noiseDisplay = new CParamDisplay (size, gBackground);
	displayOffset.offset (0, kFaderInc);
	noiseDisplay->setBackOffset(displayOffset);
	noiseDisplay->setHoriAlign(kLeftText);
	noiseDisplay->setFont(kNormalFontSmall);
	noiseDisplay->setFontColor(kWhiteCColor);
	noiseDisplay->setValue(effect->getParameter(kNoise));
	noiseDisplay->setStringConvert(noiseDisplayConvert);
	frame->addView(noiseDisplay);

	// the word "range"
	size (kRangeDisplayX, kRangeDisplayY, kRangeDisplayX + kRangeDisplayWidth, kRangeDisplayY + kRangeDisplayHeight);
	rangeDisplay = new CParamDisplay (size, gBackground);
	displayOffset (kRangeDisplayX, kRangeDisplayY);
	rangeDisplay->setBackOffset(displayOffset);
	rangeDisplay->setHoriAlign(kLeftText);
	rangeDisplay->setFont(kNormalFontVerySmall);
	rangeDisplay->setFontColor(kBlackCColor);
	rangeDisplay->setValue(effect->getParameter(kRateRandFactor));
	rangeDisplay->setStringConvert(rangeDisplayConvert);
	frame->addView(rangeDisplay);

	// the rate random factor range read-out
	size (kRateRandRangeDisplayX, kRateRandRangeDisplayY, kRateRandRangeDisplayX + kRateRandRangeDisplayWidth, kRateRandRangeDisplayY + kRateRandRangeDisplayHeight);
	rateRandRangeDisplay = new CParamDisplay (size);
	// if/else stuff to make this display disappear when there's no rate randomness
	if ( effect->getParameter(kRateRandFactor) <= 0.0f )
	{
		rateRandRangeDisplay->setBackColor(kBackgroundCColor);
		rateRandRangeDisplay->setFrameColor(kBackgroundCColor);
	}
	else
	{
		rateRandRangeDisplay->setBackColor(kMyPaleGreenCColor);
		rateRandRangeDisplay->setFrameColor(kBlackCColor);
	}
	rateRandRangeDisplay->setHoriAlign(kCenterText);
	rateRandRangeDisplay->setFont(kNormalFontVerySmall);
	rateRandRangeDisplay->setFontColor(kMyDarkBlueCColor);
	rateRandRangeDisplay->setValue(effect->getParameter(kRateRandFactor));
	rateRandRangeDisplay->setStringConvert(rateRandRangeDisplayConvert, &theCycleRate);
	frame->addView(rateRandRangeDisplay);

	// go! error/success display
	size (kGoButtonX, kGoButtonY + 17, kGoButtonX + gGoButton->getWidth(), kGoButtonY + kDisplayHeight + 17);
	goDisplay = new CParamDisplay (size, gBackground);
	displayOffset (kGoButtonX, kGoButtonY + 17);
	goDisplay->setBackOffset(displayOffset);
	goDisplay->setHoriAlign(kCenterText);
	goDisplay->setFont(kNormalFontSmall);
	goDisplay->setFontColor(kWhiteCColor);
	goDisplay->setValue(0.0f);
	goDisplay->setStringConvert(goDisplayConvert, &goError);
	frame->addView(goDisplay);

#ifdef MSKIDDER
#ifdef HUNGRY
	if ( ((Skidder*)effect)->foodEater->hostIsLogic )
	{
		// connect to food error display
		size (kConnectButtonX, kConnectButtonY + 17, kConnectButtonX + gConnectButton->getWidth(), kConnectButtonY + kDisplayHeight + 17);
		connectDisplay = new CParamDisplay (size, gBackground);
		displayOffset (kConnectButtonX, kConnectButtonY + 17);
		connectDisplay->setBackOffset(displayOffset);
		connectDisplay->setHoriAlign(kCenterText);
		connectDisplay->setFont(kNormalFontSmall);
		connectDisplay->setFontColor(kWhiteCColor);
		connectDisplay->setValue(effect->getParameter(kConnect));
		connectDisplay->setStringConvert( connectDisplayConvert, &(((Skidder*)effect)->foodEater->foodError) );
		frame->addView(connectDisplay);
	}
#endif
#endif


	for (long i=0; i < NUM_PARAMETERS; i++)
		faders[i] = NULL;
	faders[kRateRandFactor] = rateRandFactorFader;
	faders[kTempo] = tempoFader;
	faders[kSlope] = slopeFader;
	faders[kPan] = panFader;
	faders[kNoise] = noiseFader;


	isOpen = true;

	return true;
}
Beispiel #7
0
//-----------------------------------------------------------------------------------------
void skidder::processReplacing(float **inputs, float **outputs, long sampleFrames, bool replacing) {

  float *in1  = inputs[0];
  float *in2  = inputs[1];
  float *out1 = outputs[0];
  float *out2 = outputs[1];

  float SAMPLERATE = Samplerate();
	// just in case the host responds with something wacky
	if (SAMPLERATE <= 0.0f)   SAMPLERATE = 44100.0f;

  long samplecount;


	floor = gainScaled(fFloor);	// the parameter scaled real value
	gainRange = 1.0f - floor;	// the range of the skidding on/off gain
	useRandomFloor = (fFloorRandMin < fFloor);

	// figure out the current tempo if we're doing tempo sync
	if (onOffTest(fTempoSync))
	{
		// calculate the tempo at the current processing buffer
		currentTempoBPS = tempoScaled(fTempo) / 60.0f;

	}

	for (samplecount=0; (samplecount < sampleFrames); samplecount++)
	{
		switch (state)
		{
			case slopeIn:
				// get the average sqareroot of the current input samples
				rms += sqrtf( fabsf(((*in1)+(*in2))*0.5f) );
				rmscount++;	// this counter is later used for getting the mean
				processSlopeIn();
				break;
			case plateau:
				rms += sqrtf( fabsf(((*in1)+(*in2))*0.5f) );
				rmscount++;
				processPlateau();
				break;
			case slopeOut:
				processSlopeOut();
				break;
			case valley:
				processValley(SAMPLERATE);
				break;
		}

		// ((panRander*fPan)+1.0) ranges from 0.0 to 2.0
		if (replacing)
		{
			*out1 = processOutput( *in1, *in2, ((panRander*fPan)+1.0f) );
			*out2 = processOutput( *in2, *in1, (2.0f - ((panRander*fPan)+1.0f)) );
		}
		else
		{
			*out1 += processOutput( *in1, *in2, ((panRander*fPan)+1.0f) );
			*out2 += processOutput( *in2, *in1, (2.0f - ((panRander*fPan)+1.0f)) );
		}
		// move forward in the i/o sample streams
		in1++;
		in2++;
		out1++;
		out2++;
	}
}
Beispiel #8
0
//-----------------------------------------------------------------------------------------
void skidder::processValley(float SAMPLERATE)
{
  float rateRandFactor = rateRandFactorScaled(fRateRandFactor);	// stores the real value
  float cycleRate;	// the base current skid rate value
  float randFloat, randomRate;	// the current randomized rate value
  float fPulsewidthRandomized;	// stores the latest randomized pulsewidth 0.0 - 1.0 value
  bool barSync = false;	// true if we need to sync up with the next bar start
  long countdown;


	if (useRandomFloor)
		amp = randomFloor;
	else
		amp = floor;

	valleySamples--;

	if (valleySamples <= 0)
	{
		rms = 0.0f;	// reset rms now because valley is over
		//
		// This is where we figure out how many samples long each 
		// envelope section is for the next skid cycle.
		//
		if (onOffTest(fTempoSync))	// the user wants to do tempo sync / beat division rate
		{
			cycleRate = currentTempoBPS * (tempoRateTable->getScalar(fTempoRate));
			// set this true so that we make sure to do the measure syncronisation later on
		}
		else
			cycleRate = rateScaled(fRate);
		//
		if (fRateRandFactor > 0.0f)
		{
			// get a random value from 0.0 to 1.0
			randFloat = (float)rand() * ONE_DIV_RAND_MAX;
			// square-scale the random value & then scale it with the random rate range
			randomRate = ( randFloat * randFloat * 
							((cycleRate*rateRandFactor)-(cycleRate/rateRandFactor)) ) + 
							(cycleRate/rateRandFactor);
			cycleSamples = (long) (SAMPLERATE / randomRate);
			barSync = false;	// we can't do the bar sync if the skids durations are random
		}
		else
			cycleSamples = (long) (SAMPLERATE / cycleRate);
		//
		if (fPulsewidth > fPulsewidthRandMin)
		{
			fPulsewidthRandomized = ( ((float)rand()*ONE_DIV_RAND_MAX) * (fPulsewidth-fPulsewidthRandMin) ) + fPulsewidthRandMin;
			pulseSamples = (long) ( ((float)cycleSamples) * pulsewidthScaled(fPulsewidthRandomized) );
		}
		else
			pulseSamples = (long) ( ((float)cycleSamples) * pulsewidthScaled(fPulsewidth) );
		valleySamples = cycleSamples - pulseSamples;
		slopeSamples = (long) ((SAMPLERATE/1000.0f)*(fSlope*(SLOPEMAX)));
		slopeDur = slopeSamples;
		slopeStep = 1.0f / (float)slopeDur;	// calculate the fade increment scalar
		plateauSamples = pulseSamples - (slopeSamples * 2);
		if (plateauSamples < 1)	// this shrinks the slope to 1/3 of the pulse if the user sets slope too high
		{
			slopeSamples = (long) (((float)pulseSamples) / 3.0f);
			slopeDur = slopeSamples;
			slopeStep = 1.0f / (float)slopeDur;	// calculate the fade increment scalar
			plateauSamples = pulseSamples - (slopeSamples * 2);
		}

		// go to slopeIn next if slope is not 0.0, otherwise go to plateau
		if (slopeDur > 0)
			state = slopeIn;
		else
			state = plateau;

		// this puts random float values from -1.0 to 1.0 into panRander
		panRander = ( ((float)rand()*ONE_DIV_RAND_MAX) * 2.0f ) - 1.0f;

	} //end of the "valley is over" if-statement
}