示例#1
0
 void ADSRcurve::release()
 {
   if(released)
     return;
   if(currentState < EnvStageSustain) {
     // early release - recalculate release stage
     calcRelease(currentAmp, timeScale, Release_Normal);
   }
   released = true;
   currentState = EnvStageRelease;
 }
示例#2
0
dynProcEffect::dynProcEffect( Model * _parent,
			const Descriptor::SubPluginFeatures::Key * _key ) :
	Effect( &dynamicsprocessor_plugin_descriptor, _parent, _key ),
	m_dpControls( this )
{
	m_currentPeak[0] = m_currentPeak[1] = DYN_NOISE_FLOOR;
	m_rms[0] = new RmsHelper( 64 * Engine::mixer()->processingSampleRate() / 44100 );
	m_rms[1] = new RmsHelper( 64 * Engine::mixer()->processingSampleRate() / 44100 );
	calcAttack();
	calcRelease();
}
示例#3
0
 void ADSRcurve::fastRelease()
 {
   released = true;
   calcRelease(currentAmp, timeScale, Release_Fast);
   currentState = EnvStageRelease;
 }
示例#4
0
  void ADSRcurve::createEnvelope(ADSRcurveParams& inParams)
  {
    // parameter check
    assert(inParams.sustainLevel >= 0.0   &&
           inParams.sustainLevel <= 100.0 &&
           inParams.timeScale    >= 0.0);

    // percent to decimal
    inParams.timeScale    *= kPercToDec;
    inParams.sustainLevel *= kPercToDec;

#ifdef CACHE_ENV

    /*
     * Envelope stage caching system:
     *
     * The previously used input parameters are stored
     * as lastParams, the previously calculated envelope
     * stages are stored in lastStateMachine[].
     *
     * Received input parameters are compared to those
     * stored from the last calculation, and re-used if
     * they haven't changed.
     *
     * NB: Due to the introduction of the ModuleCache,
     * this functionality's usefulness has been significantly
     * reduced. It may not be obsolete.
     */

    timeScaleUnchanged = attackUnchanged = decayUnchanged =
        sustainUnchanged = releaseUnchanged   = false;

    timeScaleUnchanged = Utility::fpEqual(inParams.timeScale,     lastParams.timeScale);
    // A time scale changes requires a full recalculation
    if(timeScaleUnchanged) {
      // examine individual stages
      attackUnchanged    = Utility::fpEqual(inParams.attackTime,  lastParams.attackTime);
      decayUnchanged     = Utility::fpEqual(inParams.decayTime,   lastParams.decayTime);
      sustainUnchanged   = Utility::fpEqual(inParams.sustainLevel,lastParams.sustainLevel);
      releaseUnchanged   = Utility::fpEqual(inParams.releaseTime, lastParams.releaseTime);
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#endif
    
    /*
     * ATTACK
     */
#ifdef CACHE_ENV
    // compare input to previous values
    if(timeScaleUnchanged && attackUnchanged && sustainUnchanged)
    {
      // A. no change - use cached values
      memcpy(&stateMachine[EnvStageAttack], 
             &lastStateMachine[EnvStageAttack], 
             sizeof(StateStructure));
    } else {
#endif
      // B1. changed - calculate for these input settings
      stateMachine[EnvStageAttack].nextState    = EnvStageDecay;
      stateMachine[EnvStageAttack].finalAmp     = kAmpMax;
      stateMachine[EnvStageAttack].range        = kAmpMax;
      stateMachine[EnvStageAttack].offset       = 0.0;
      stateMachine[EnvStageAttack].duration     = timeToSampleDuration(samplingRate,
                                                                       inParams.attackTime);
      if(stateMachine[EnvStageAttack].duration) {
        stateMachine[EnvStageAttack].scale1    =
        std::pow( static_cast<double>(inParams.timeScale/(inParams.timeScale+1)),
                 static_cast<double>(1.0/stateMachine[EnvStageAttack].duration));
        stateMachine[EnvStageAttack].scale2     = inParams.timeScale + 1;
      }
#ifdef CACHE_ENV
      // B2. cache the new values
      memcpy(&lastStateMachine[EnvStageAttack],
             &stateMachine[EnvStageAttack],
             sizeof(StateStructure));
    }
#endif

    /*
     * DECAY
     */
#ifdef CACHE_ENV
    // compare
    if(timeScaleUnchanged && decayUnchanged && sustainUnchanged)
    {
      // A.
      memcpy(&stateMachine[EnvStageDecay], 
             &lastStateMachine[EnvStageDecay], 
             sizeof(StateStructure));
    } else {      
#endif
      // B1.
      stateMachine[EnvStageDecay].nextState     = EnvStageSustain;
      stateMachine[EnvStageDecay].finalAmp      = inParams.sustainLevel;
      stateMachine[EnvStageDecay].range         = 1.0 - inParams.sustainLevel;
      stateMachine[EnvStageDecay].offset        = inParams.sustainLevel;
      stateMachine[EnvStageDecay].duration      = timeToSampleDuration(samplingRate,
                                                                       inParams.decayTime);
      if(stateMachine[EnvStageDecay].duration) {
        stateMachine[EnvStageDecay].scale1      =
            std::pow( static_cast<double>((timeScale+1)/inParams.timeScale),
                      static_cast<double>(1.0/stateMachine[EnvStageDecay].duration));
        stateMachine[EnvStageDecay].scale2      = inParams.timeScale;
      }
#ifdef CACHE_ENV
      // B2.
      memcpy(&lastStateMachine[EnvStageDecay],
             &stateMachine[EnvStageDecay],
             sizeof(StateStructure));
    }
#endif

    /*
     * SUSTAIN
     */
#ifdef CACHE_ENV
    // as before...
    if(sustainUnchanged)
    {
      // A.
      memcpy(&stateMachine[EnvStageSustain], 
             &lastStateMachine[EnvStageSustain], 
             sizeof(StateStructure));
    } else {  
#endif
      // B1.
      stateMachine[EnvStageSustain].nextState   = EnvStageRelease;
      stateMachine[EnvStageSustain].finalAmp    = inParams.sustainLevel;
      stateMachine[EnvStageSustain].duration    = kSustained;
      stateMachine[EnvStageSustain].sustainFlag = true;
      stateMachine[EnvStageSustain].scale1      = 1.0;
      stateMachine[EnvStageSustain].scale2      = 1.0;
#ifdef CACHE_ENV
      // B2.
      memcpy(&lastStateMachine[EnvStageSustain],
             &stateMachine[EnvStageSustain],
             sizeof(StateStructure));
    }
#endif

    /*
     * RELEASE
     */
#ifdef CACHE_ENV
    // ....
    if(timeScaleUnchanged && releaseUnchanged && sustainUnchanged)
    {
      // ...
      memcpy(&stateMachine[EnvStageRelease], 
             &lastStateMachine[EnvStageRelease], 
             sizeof(StateStructure));
    } else {  
#endif
      // ...
      stateMachine[EnvStageRelease].nextState   = _EnvStageNoteOff_;
      stateMachine[EnvStageRelease].finalAmp    = 0.0;
      stateMachine[EnvStageRelease].offset      = 0.0;      
      stateMachine[EnvStageRelease].duration    = timeToSampleDuration(samplingRate,
                                                                       inParams.releaseTime);
      calcRelease(inParams.sustainLevel,
                  inParams.timeScale,
                  Release_Normal);
#ifdef CACHE_ENV
      // ...
      memcpy(&lastStateMachine[EnvStageRelease],
             &stateMachine[EnvStageRelease],
             sizeof(StateStructure));
    }
#endif

    // Note off - final stage
    stateMachine[_EnvStageNoteOff_].nextState   = _EnvStageNoteOff_;
    stateMachine[_EnvStageNoteOff_].finalAmp    = 0.0;
    stateMachine[_EnvStageNoteOff_].duration    = kSustained;
    stateMachine[_EnvStageNoteOff_].scale1      = 0.0;
    stateMachine[_EnvStageNoteOff_].scale2      = 0.0;
    
    // general
    timeScale = inParams.timeScale;
    // ready for note on
    reset();
    
#ifdef CACHE_ENV
    // cache the last params
    memcpy(&lastParams, &inParams, sizeof(inParams));
#endif
  }
示例#5
0
bool dynProcEffect::processAudioBuffer( sampleFrame * _buf,
							const fpp_t _frames )
{
	if( !isEnabled() || !isRunning () )
	{
//apparently we can't keep running after the decay value runs out so we'll just set the peaks to zero
		m_currentPeak[0] = m_currentPeak[1] = DYN_NOISE_FLOOR;
		return( false );
	}
	//qDebug( "%f %f", m_currentPeak[0], m_currentPeak[1] );

// variables for effect
	int i = 0;

	float sm_peak[2] = { 0.0f, 0.0f };
	float gain;

	double out_sum = 0.0;
	const float d = dryLevel();
	const float w = wetLevel();
	
	const int stereoMode = m_dpControls.m_stereomodeModel.value();
	const float inputGain = m_dpControls.m_inputModel.value();
	const float outputGain = m_dpControls.m_outputModel.value();
	
	const float * samples = m_dpControls.m_wavegraphModel.samples();

// debug code
//	qDebug( "peaks %f %f", m_currentPeak[0], m_currentPeak[1] );

	if( m_needsUpdate )
	{
		m_rms[0]->setSize( 64 * Engine::mixer()->processingSampleRate() / 44100 );
		m_rms[1]->setSize( 64 * Engine::mixer()->processingSampleRate() / 44100 );
		calcAttack();
		calcRelease();
		m_needsUpdate = false;
	}
	else
	{
		if( m_dpControls.m_attackModel.isValueChanged() )
		{
			calcAttack();
		}
		if( m_dpControls.m_releaseModel.isValueChanged() )
		{
			calcRelease();
		}
	}

	for( fpp_t f = 0; f < _frames; ++f )
	{
		double s[2] = { _buf[f][0], _buf[f][1] };

// apply input gain
		s[0] *= inputGain;
		s[1] *= inputGain;

// update peak values
		for ( i=0; i <= 1; i++ )
		{
			const double t = m_rms[i]->update( s[i] );
			if( t > m_currentPeak[i] )
			{
				m_currentPeak[i] = qMin( m_currentPeak[i] * m_attCoeff, t );
			}
			else
			if( t < m_currentPeak[i] )
			{
				m_currentPeak[i] = qMax( m_currentPeak[i] * m_relCoeff, t );
			}

			m_currentPeak[i] = qBound( DYN_NOISE_FLOOR, m_currentPeak[i], 10.0f );
		}

// account for stereo mode
		switch( stereoMode )
		{
			case dynProcControls::SM_Maximum:
			{
				sm_peak[0] = sm_peak[1] = qMax( m_currentPeak[0], m_currentPeak[1] );
				break;
			}
			case dynProcControls::SM_Average:
			{
				sm_peak[0] = sm_peak[1] = ( m_currentPeak[0] + m_currentPeak[1] ) * 0.5;
				break;
			}
			case dynProcControls::SM_Unlinked:
			{
				sm_peak[0] = m_currentPeak[0];
				sm_peak[1] = m_currentPeak[1];
				break;
			}
		}

// start effect

		for ( i=0; i <= 1; i++ )
		{
			const int lookup = static_cast<int>( sm_peak[i] * 200.0f );
			const float frac = fraction( sm_peak[i] * 200.0f );

			if( sm_peak[i] > DYN_NOISE_FLOOR )
			{
				if ( lookup < 1 )
				{
					gain = frac * samples[0];
				}
				else
				if ( lookup < 200 )
				{
					gain = linearInterpolate( samples[ lookup - 1 ],
							samples[ lookup ], frac );
				}
				else
				{
					gain = samples[199];
				};

				s[i] *= gain; 
				s[i] /= sm_peak[i];
			}
		}

// apply output gain
		s[0] *= outputGain;
		s[1] *= outputGain;

		out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1];
// mix wet/dry signals
		_buf[f][0] = d * _buf[f][0] + w * s[0];
		_buf[f][1] = d * _buf[f][1] + w * s[1];
	}

	checkGate( out_sum / _frames );

	return( isRunning() );
}