Beispiel #1
0
float AutomatableModel::globalAutomationValueAt( const MidiTime& time )
{
	// get patterns that connect to this model
	QVector<AutomationPattern *> patterns = AutomationPattern::patternsForModel( this );
	if( patterns.isEmpty() )
	{
		// if no such patterns exist, return current value
		return m_value;
	}
	else
	{
		// of those patterns:
		// find the patterns which overlap with the miditime position
		QVector<AutomationPattern *> patternsInRange;
		for( QVector<AutomationPattern *>::ConstIterator it = patterns.begin(); it != patterns.end(); it++ )
		{
			int s = ( *it )->startPosition();
			int e = ( *it )->endPosition();
			if( s <= time && e >= time ) { patternsInRange += ( *it ); }
		}

		AutomationPattern * latestPattern = NULL;

		if( ! patternsInRange.isEmpty() )
		{
			// if there are more than one overlapping patterns, just use the first one because
			// multiple pattern behaviour is undefined anyway
			latestPattern = patternsInRange[0];
		}
		else
		// if we find no patterns at the exact miditime, we need to search for the last pattern before time and use that
		{
			int latestPosition = 0;

			for( QVector<AutomationPattern *>::ConstIterator it = patterns.begin(); it != patterns.end(); it++ )
			{
				int e = ( *it )->endPosition();
				if( e <= time && e > latestPosition )
				{
					latestPosition = e;
					latestPattern = ( *it );
				}
			}
		}

		if( latestPattern )
		{
			// scale/fit the value appropriately and return it
			const float value = latestPattern->valueAt( time - latestPattern->startPosition() );
			const float scaled_value = scaledValue( value );
			return fittedValue( scaled_value );
		}
		// if we still find no pattern, the value at that time is undefined so
		// just return current value as the best we can do
		else return m_value;
	}
}
Beispiel #2
0
	smfMidiCC & putValue( MidiTime time, AutomatableModel * objModel, float value )
	{
		if( !ap || time > lastPos + DefaultTicksPerTact )
		{
			MidiTime pPos = MidiTime( time.getTact(), 0 );
			ap = dynamic_cast<AutomationPattern*>(
				at->createTCO(0) );
			ap->movePosition( pPos );
			ap->addObject( objModel );
		}

		lastPos = time;
		time = time - ap->startPosition();
		ap->putValue( time, value, false );
		ap->changeLength( MidiTime( time.getTact() + 1, 0 ) ); 

		return *this;
	}
bool AutomationTrack::play( const MidiTime & _start, const fpp_t _frames,
							const f_cnt_t _frame_base, int _tco_num )
{
	if( isMuted() )
	{
		return false;
	}

	tcoVector tcos;
	if( _tco_num >= 0 )
	{
		TrackContentObject * tco = getTCO( _tco_num );
		tcos.push_back( tco );
	}
	else
	{
		getTCOsInRange( tcos, _start, _start + static_cast<int>(
					_frames / Engine::framesPerTick()) );
	}

	for( tcoVector::iterator it = tcos.begin(); it != tcos.end(); ++it )
	{
		AutomationPattern * p = dynamic_cast<AutomationPattern *>( *it );
		if( p == NULL || ( *it )->isMuted() )
		{
			continue;
		}
		MidiTime cur_start = _start;
		if( _tco_num < 0 )
		{
			cur_start -= p->startPosition();
		}
		p->processMidiTime( cur_start );
	}
	return false;
}