QString AutomatableModel::displayValue( const float val ) const { switch( m_dataType ) { case Float: return QString::number( castValue<float>( scaledValue( val ) ) ); case Integer: return QString::number( castValue<int>( scaledValue( val ) ) ); case Bool: return QString::number( castValue<bool>( scaledValue( val ) ) ); } return "0"; }
void AutomatableModel::setAutomatedValue( const float value ) { m_oldValue = m_value; ++m_setValueDepth; const float oldValue = m_value; const float scaled_value = scaledValue( value ); m_value = fittedValue( scaled_value ); if( oldValue != m_value ) { // notify linked models for( AutoModelVector::Iterator it = m_linkedModels.begin(); it != m_linkedModels.end(); ++it ) { if( (*it)->m_setValueDepth < 1 && !(*it)->fittedValue( m_value ) != (*it)->m_value ) { (*it)->setAutomatedValue( value ); } } m_valueChanged = true; emit dataChanged(); } --m_setValueDepth; }
void testSine() { typedef Eigen::Spline<double,1> Spline1d; // create data const size_t numData = 1000; Eigen::VectorXd x(numData); Eigen::VectorXd y(numData); const double a = 0; const double b = 4*M_PI; const double dx = (b-a)/double(numData); for(size_t i=0;i<numData;++i) { x(i) = a + i*dx; y(i) = std::sin(x(i)); } // create a spline Spline1d spline( Eigen::SplineFitting<Spline1d>::Interpolate(y.transpose(), std::min<int>(x.rows() - 1, 3),scaledValues(x)) ); std::ofstream outFile; outFile.open("eigenSplinePlot.dat",std::ios::trunc); for(size_t i=0;i<numData;++i) { double xiSc = scaledValue(x.minCoeff(),x.maxCoeff())(x(i)); double yiSpl = spline(xiSc)(0); outFile<<x(i)<<"\t"<<y(i)<<"\t"<<yiSpl<<std::endl; } outFile.close(); }
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; } }
Eigen::RowVectorXd scaledValues(Eigen::VectorXd const& x) { return x.unaryExpr(scaledValue(x.minCoeff(),x.maxCoeff())).transpose(); }
QString BoolModel::displayValue( const float val ) const { return QString::number( castValue<bool>( scaledValue( val ) ) ); }
QString IntModel::displayValue( const float val ) const { return QString::number( castValue<int>( scaledValue( val ) ) ); }