#include "externals.hh" #include "sync.hh" const T_SyncVariable T_SyncData::MissingVariable_{ }; T_SyncData::T_SyncData( __rd__ const uint32_t duration , __rd__ const float units ) noexcept : duration_( duration ) , units_( units ) { } T_SyncData::T_VarHelper_::T_VarHelper_( __rw__ T_SyncVariable&& v , __rd__ const uint32_t duration ) noexcept : variable( std::move( v ) ) { const auto n( variable.size( ) ); uint32_t s = 0; for ( auto i = 0u ; i < n ; i ++ ) { auto const& v( variable[ i ] ); assert( v.nPoints >= 2 ); assert( v.durations.size( ) == v.nPoints - 1 ); const auto nd( v.nPoints - 1 ); for ( auto j = 0u ; j < nd ; j ++ ) { segStarts.push_back( s ); segRefs.push_back( std::make_pair( i , j ) ); s += v.durations[ j ]; if ( s > duration ) { return; } } } } void T_SyncData::setSyncVariable( __rd__ std::string const& name , __rw__ T_SyncVariable&& variable ) noexcept { variables_.erase( name ); if ( !variable.empty( ) ) { variables_.emplace( name , T_VarHelper_{ std::move( variable ) , duration_ } ); } } T_SyncVariable const& T_SyncData::variable( __rd__ std::string const& name ) const noexcept { auto pos( variables_.find( name ) ); if ( pos == variables_.end( ) ) { return MissingVariable_; } return pos->second.variable; } float T_SyncData::valueOf( __rd__ std::string const& name , __rd__ const float time ) const noexcept { assert( time >= 0 ); auto pos( variables_.find( name ) ); if ( pos == variables_.end( ) ) { return 0; } // Find segment auto const& var( pos->second ); const uint32_t tu( std::min( duration_ , uint32_t( floor( time / units_ ) ) ) ); uint32_t s( 0 ); for ( auto ss : var.segStarts ) { if ( ss > tu ) { break; } s ++; } assert( s > 0 ); s --; const auto sid( var.segRefs[ s ].first ); auto const& seg( var.variable[ sid ] ); const auto pid( var.segRefs[ s ].second ); // Interpolation factor const float st( var.segStarts[ s ] * units_ ); const float et( ( var.segStarts[ s ] + seg.durations[ pid ] ) * units_ ); const float v0 = ( time - st ) / ( et - st ); float v = v0; if ( seg.type != E_SyncSegment::LINEAR ) { v *= v0; if ( seg.type == E_SyncSegment::SMOOTH ) { v *= 3 - 2 * v0; } } const float sv( seg.values[ pid ] ); const float ev( seg.values[ pid + 1 ] ); return v * ( ev - sv ) + sv; }