void testInlineAutomation()
	{
		auto song = Engine::getSong();

		InstrumentTrack* instrumentTrack =
				dynamic_cast<InstrumentTrack*>(Track::create(Track::InstrumentTrack, song));

		Pattern* notePattern = dynamic_cast<Pattern*>(instrumentTrack->createTCO(0));
		notePattern->changeLength(MidiTime(4, 0));
		Note* note = notePattern->addNote(Note(MidiTime(4, 0)), false);
		note->createDetuning();

		DetuningHelper* dh = note->detuning();
		auto pattern = dh->automationPattern();
		pattern->setProgressionType( AutomationPattern::LinearProgression );
		pattern->putValue(MidiTime(0, 0), 0.0);
		pattern->putValue(MidiTime(4, 0), 1.0);

		QCOMPARE(pattern->valueAt(MidiTime(0, 0)), 0.0f);
		QCOMPARE(pattern->valueAt(MidiTime(1, 0)), 0.25f);
		QCOMPARE(pattern->valueAt(MidiTime(2, 0)), 0.5f);
		QCOMPARE(pattern->valueAt(MidiTime(4, 0)), 1.0f);
	}
NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack,
								const f_cnt_t _offset,
								const f_cnt_t _frames,
								const Note& n,
								NotePlayHandle *parent,
								int midiEventChannel,
								Origin origin ) :
	PlayHandle( TypeNotePlayHandle, _offset ),
	Note( n.length(), n.pos(), n.key(), n.getVolume(), n.getPanning(), n.detuning() ),
	m_pluginData( NULL ),
	m_filter( NULL ),
	m_instrumentTrack( instrumentTrack ),
	m_frames( 0 ),
	m_totalFramesPlayed( 0 ),
	m_framesBeforeRelease( 0 ),
	m_releaseFramesToDo( 0 ),
	m_releaseFramesDone( 0 ),
	m_subNotes(),
	m_released( false ),
	m_hasParent( parent != NULL  ),
	m_parent( parent ),
	m_hadChildren( false ),
	m_muted( false ),
	m_bbTrack( NULL ),
	m_origTempo( Engine::getSong()->getTempo() ),
	m_origBaseNote( instrumentTrack->baseNote() ),
	m_frequency( 0 ),
	m_unpitchedFrequency( 0 ),
	m_baseDetuning( NULL ),
	m_songGlobalParentOffset( 0 ),
	m_midiChannel( midiEventChannel >= 0 ? midiEventChannel : instrumentTrack->midiPort()->realOutputChannel() ),
	m_origin( origin ),
	m_frequencyNeedsUpdate( false )
{
	lock();
	if( hasParent() == false )
	{
		m_baseDetuning = new BaseDetuning( detuning() );
		m_instrumentTrack->m_processHandles.push_back( this );
	}
	else
	{
		m_baseDetuning = parent->m_baseDetuning;

		parent->m_subNotes.push_back( this );
		parent->m_hadChildren = true;

		m_bbTrack = parent->m_bbTrack;

		parent->setUsesBuffer( false );
	}

	updateFrequency();

	setFrames( _frames );

	// inform attached components about new MIDI note (used for recording in Piano Roll)
	if( m_origin == OriginMidiInput )
	{
		m_instrumentTrack->midiNoteOn( *this );
	}

	if( hasParent() || ! m_instrumentTrack->isArpeggioEnabled() )
	{
		const int baseVelocity = m_instrumentTrack->midiPort()->baseVelocity();

		// send MidiNoteOn event
		m_instrumentTrack->processOutEvent(
			MidiEvent( MidiNoteOn, midiChannel(), midiKey(), midiVelocity( baseVelocity ) ),
			MidiTime::fromFrames( offset(), Engine::framesPerTick() ),
			offset() );
	}

	if( m_instrumentTrack->instrument()->flags() & Instrument::IsSingleStreamed )
	{
		setUsesBuffer( false );
	}

	setAudioPort( instrumentTrack->audioPort() );

	unlock();
}