Esempio n. 1
0
double Envelope::IntegralOfInverse( double t0, double t1 )
{
   if(t0 == t1)
      return 0.0;
   if(t0 > t1)
   {
      return -IntegralOfInverse(t1, t0); // this makes more sense than returning the default value
   }

   unsigned int count = mEnv.Count();
   if(count == 0) // 'empty' envelope
      return (t1 - t0) / mDefaultValue;

   double total = 0.0, lastT, lastVal;
   unsigned int i; // this is the next point to check
   if(t0 < mEnv[0]->GetT()) // t0 preceding the first point
   {
      if(t1 <= mEnv[0]->GetT())
         return (t1 - t0) / mEnv[0]->GetVal();
      i = 1;
      lastT = mEnv[0]->GetT();
      lastVal = mEnv[0]->GetVal();
      total += (lastT - t0) / lastVal;
   }
   else if(t0 >= mEnv[count - 1]->GetT()) // t0 following the last point
   {
      return (t1 - t0) / mEnv[count - 1]->GetVal();
   }
   else // t0 enclosed by points
   {
      // Skip any points that come before t0 using binary search
      int lo, hi;
      BinarySearchForTime(lo, hi, t0);
      lastVal = InterpolatePoints(mEnv[lo]->GetVal(), mEnv[hi]->GetVal(), (t0 - mEnv[lo]->GetT()) / (mEnv[hi]->GetT() - mEnv[lo]->GetT()), mDB);
      lastT = t0;
      i = hi; // the point immediately after t0.
   }

   // loop through the rest of the envelope points until we get to t1
   while (1)
   {
      if(i >= count) // the requested range extends beyond the last point
      {
         return total + (t1 - lastT) / lastVal;
      }
      else if(mEnv[i]->GetT() >= t1) // this point follows the end of the range
      {
         double thisVal = InterpolatePoints(mEnv[i - 1]->GetVal(), mEnv[i]->GetVal(), (t1 - mEnv[i - 1]->GetT()) / (mEnv[i]->GetT() - mEnv[i - 1]->GetT()), mDB);
         return total + IntegrateInverseInterpolated(lastVal, thisVal, t1 - lastT, mDB);
      }
      else // this point preceeds the end of the range
      {
         total += IntegrateInverseInterpolated(lastVal, mEnv[i]->GetVal(), mEnv[i]->GetT() - lastT, mDB);
         lastT = mEnv[i]->GetT();
         lastVal = mEnv[i]->GetVal();
         i++;
      }
   }
}
Esempio n. 2
0
double Envelope::NextPointAfter(double t)
{
   if( mEnv[mEnv.Count()-1]->GetT() < t )
      return t;
   else if( t < mEnv[0]->GetT() )
      return mEnv[0]->GetT();
   else
   {
      int lo,hi;
      BinarySearchForTime( lo, hi, t );
      if( mEnv[hi]->GetT() == t )
         return mEnv[hi+1]->GetT();
      else
         return mEnv[hi]->GetT();
   }
}
Esempio n. 3
0
int Envelope::NumberOfPointsAfter(double t)
{
   if( t >= mEnv[mEnv.Count()-1]->GetT() )
      return 0;
   else if( t < mEnv[0]->GetT() )
      return mEnv.Count();
   else
   {
      int lo,hi;
      BinarySearchForTime( lo, hi, t );

      if( mEnv[hi]->GetT() == t )
         return mEnv.Count() - (hi+1);
      else
         return mEnv.Count() - hi;
   }
}
Esempio n. 4
0
double Envelope::SolveIntegralOfInverse( double t0, double area )
{
   if(area == 0.0)
      return t0;

   unsigned int count = mEnv.Count();
   if(count == 0) // 'empty' envelope
      return t0 + area * mDefaultValue;

   double lastT, lastVal;
   int i; // this is the next point to check
   if(t0 < mEnv[0]->GetT()) // t0 preceding the first point
   {
      if (area < 0) {
         return t0 + area * mEnv[0]->GetVal();
      }
      else {
         i = 1;
         lastT = mEnv[0]->GetT();
         lastVal = mEnv[0]->GetVal();
         double added = (lastT - t0) / lastVal;
         if(added >= area)
            return t0 + area * mEnv[0]->GetVal();
         area -= added;
      }
   }
   else if(t0 >= mEnv[count - 1]->GetT()) // t0 following the last point
   {
      if (area < 0) {
         i = count - 2;
         lastT = mEnv[count - 1]->GetT();
         lastVal = mEnv[count - 1]->GetVal();
         double added = (lastT - t0) / lastVal; // negative
         if(added <= area)
            return t0 + area * mEnv[count - 1]->GetVal();
         area -= added;
      }
      else {
         return t0 + area * mEnv[count - 1]->GetVal();
      }
   }
   else // t0 enclosed by points
   {
      // Skip any points that come before t0 using binary search
      int lo, hi;
      BinarySearchForTime(lo, hi, t0);
      lastVal = InterpolatePoints(mEnv[lo]->GetVal(), mEnv[hi]->GetVal(), (t0 - mEnv[lo]->GetT()) / (mEnv[hi]->GetT() - mEnv[lo]->GetT()), mDB);
      lastT = t0;
      if (area < 0)
         i = lo;
      else
         i = hi; // the point immediately after t0.
   }

   if (area < 0) {
      // loop BACKWARDS through the rest of the envelope points until we get to t1
      // (which is less than t0)
      while (1)
      {
         if(i < 0) // the requested range extends beyond the leftmost point
         {
            return lastT + area * lastVal;
         }
         else
         {
            double added =
               -IntegrateInverseInterpolated(mEnv[i]->GetVal(), lastVal, lastT - mEnv[i]->GetT(), mDB);
            if(added <= area)
               return lastT - SolveIntegrateInverseInterpolated(lastVal, mEnv[i]->GetVal(), lastT - mEnv[i]->GetT(), -area, mDB);
            area -= added;
            lastT = mEnv[i]->GetT();
            lastVal = mEnv[i]->GetVal();
            --i;
         }
      }
   }
   else {
      // loop through the rest of the envelope points until we get to t1
      while (1)
      {
         if(i >= count) // the requested range extends beyond the last point
         {
            return lastT + area * lastVal;
         }
         else
         {
            double added = IntegrateInverseInterpolated(lastVal, mEnv[i]->GetVal(), mEnv[i]->GetT() - lastT, mDB);
            if(added >= area)
               return lastT + SolveIntegrateInverseInterpolated(lastVal, mEnv[i]->GetVal(), mEnv[i]->GetT() - lastT, area, mDB);
            area -= added;
            lastT = mEnv[i]->GetT();
            lastVal = mEnv[i]->GetVal();
            i++;
         }
      }
   }
}
Esempio n. 5
0
void Envelope::GetValues(double *buffer, int bufferLen,
                         double t0, double tstep) const
{
   t0 -= mOffset;

   // JC: If bufferLen ==0 we have probably just allocated a zero sized buffer.
   wxASSERT( bufferLen > 0 );

   int len = mEnv.Count();

   double t = t0;
   double tprev, vprev, tnext = 0, vnext, vstep = 0;

   for (int b = 0; b < bufferLen; b++) {

      // Get easiest cases out the way first...
      // IF empty envelope THEN default value
      if (len <= 0) {
         buffer[b] = mDefaultValue;
         t += tstep;
         continue;
      }
      // IF before envelope THEN first value
      if (t <= mEnv[0]->GetT()) {
         buffer[b] = mEnv[0]->GetVal();
         t += tstep;
         continue;
      }
      // IF after envelope THEN last value
      if (t >= mEnv[len - 1]->GetT()) {
         buffer[b] = mEnv[len - 1]->GetVal();
         t += tstep;
         continue;
      }

      if (b == 0 || t > tnext) {

         // We're beyond our tnext, so find the next one.
         // Don't just increment lo or hi because we might
         // be zoomed far out and that could be a large number of
         // points to move over.  That's why we binary search.

         int lo,hi;
         BinarySearchForTime( lo, hi, t );
         tprev = mEnv[lo]->GetT();
         tnext = mEnv[hi]->GetT();

         vprev = GetInterpolationStartValueAtPoint( lo );
         vnext = GetInterpolationStartValueAtPoint( hi );

         // Interpolate, either linear or log depending on mDB.
         double dt = (tnext - tprev);
         double to = t - tprev;
         double v;
         if (dt > 0.0)
         {
            v = (vprev * (dt - to) + vnext * to) / dt;
            vstep = (vnext - vprev) * tstep / dt;
         }
         else
         {
            v = vnext;
            vstep = 0.0;
         }

         // An adjustment if logarithmic scale.
         if( mDB )
         {
            v = pow(10.0, v);
            vstep = pow( 10.0, vstep );
         }

         buffer[b] = v;
      } else {
         if (mDB){
            buffer[b] = buffer[b - 1] * vstep;
         }else{
            buffer[b] = buffer[b - 1] + vstep;
         }
      }

      t += tstep;
   }
}
Esempio n. 6
0
// We should be able to write a very efficient memoizer for this
// but make sure it gets reset when the envelope is changed.
double Envelope::Integral( double t0, double t1 )
{
    //printf( "\n\nIntegral:  t0=%f, t1=%f\n", t0, t1 );
    double total=0;

    if( t0 == t1 )
        return 0;
    if( t0 > t1 )
    {
        printf( "Odd things happening in Integral!\n" );
        return mDefaultValue;
    }

    unsigned int i = 0;
    double lastT, lastVal;

    // t0 is one of three cases:

    // 0) in an 'empty' envelope
    // 1) preceeding the first point
    // 2) enclosed by points
    // 3) following the last point

    if( mEnv.Count() < 1 )                      // 0: 'empty' envelope
    {
        return (t1 - t0) * mDefaultValue;
    }
    else if( t0 < mEnv[0]->t )                  // 1: preceeds the first
    {
        if( t1 <= mEnv[0]->t ) {
            return (t1 - t0) * mEnv[0]->val;
        }
        total += (mEnv[0]->t - t0) * mEnv[0]->val;
        lastT = mEnv[0]->t;
        lastVal = mEnv[0]->val;
    }
    else if( t0 >= mEnv[mEnv.Count()-1]->t )    // 3: follows the last
    {
        return (t1 - t0) * mEnv[mEnv.Count()-1]->val;
    }
    else
    {   // 2: bracketed
        // Skip any points that come before t0 using binary search
        int lo,hi;
        BinarySearchForTime( lo, hi, t0 );
        i = lo;
        // i is now the point immediately before t0.
        lastVal = ((mEnv[i]->val * (mEnv[i+1]->t - t0))
                   + (mEnv[i+1]->val *(t0 - mEnv[i]->t)))
                  / (mEnv[i+1]->t - mEnv[i]->t); // value at t0
        lastT = t0;
    }

    // loop through the rest of the envelope points until we get to t1
    while (1)
    {

        if(i >= mEnv.Count()-1)
        {
            // the requested range extends beyond last point
            return total + (t1 - lastT) * lastVal;
        }
        else if (mEnv[i+1]->t >= t1)
        {
            // last,i+1 bracket t1
            double thisVal = ((mEnv[i]->val * (mEnv[i+1]->t - t1))
                              + (mEnv[i+1]->val *(t1 - mEnv[i]->t)))
                             / (mEnv[i+1]->t - mEnv[i]->t);

            return total + (t1 - lastT) * (thisVal + lastVal) / 2;
        }
        else
        {
            // t1 still follows last,i+1
            total += (mEnv[i+1]->t - lastT) *  (mEnv[i+1]->val + lastVal) / 2;
            lastT = mEnv[i+1]->t;
            lastVal = mEnv[i+1]->val;
            i++;
        }
    }
}