com.softsynth.jmsl.util
Class LinearAccelerator

java.lang.Object
  extended by com.softsynth.jmsl.util.LinearAccelerator

public class LinearAccelerator
extends java.lang.Object

Calculate the accelerated duration of an event, given the acceleration, the event's starting time, and its duration.

Accelerando is expressed as beats/sec change over some number of beats.

 EXPLANATION...

 Formula for instantaneous tempo v as a function of unaccelerated time x.
 v(x) = Vi + Dx / (n)

 Where:
 Vi is initial tempo in b/s,
 D is the amount the tempo changes
 n is the number of beats over which the tempo changes.

 For example:

 to calculate instantaneous tempo which accelerates from 1 b/s to 2 b/s over 4 beats:
 V(x) = 1 + (1)x/4
 To find instantaeous tempo at beat 2,
 V(2) = 1 + 2/4 = 1.5

 We can not apply instanteous tempo to the duration of an event to get its accelerated duration.  Easiest to
 see this if you imagine that the first event would not have its tempo altered, since the tempo at 
 accelerando time 0 is equal to Vinitial.  You can also imagine easily that an event list containing 
 one event of 1.0 would fall out of synch with an event list containing 2 events of 0.5 seconds each. 


 Instead we need to take the integral of 1/V(x) between the x initial and x final.  
 For example, for an event  of duration 1.0 beginning at time x=1.0, we'd need the 
 integral between x=2.0 and x=3.0 (since it starts at x=2 and lasts until x=3).

 1/V(x) = n/(nVi + Dx)

 The integral of this with respect to dx is:

 n ln(nVi + Dx)

 EXAMPLE PROBLEM:

 A MusicShape has four elements each of whose durations is 1.0.
 The initial tempo is 1 b/s (ie 1.0 lasts 1 second)
 The final tempo is 2 b/s
 The duration over which this acceleration takes place is 4.0
 Calculate the duration of the third event.

 SOLUTION:
 n=4
 Vi=1
 D=1

 Evaluate the integral 4 ln(4 + 1x) at x=2.0 (the event's starting time) and at x=3.0 (the events finishing time).
 Find the difference.
 The accelerated duration is 0.61660271930903321717150154024991

  

Author:
Nick Didkovsky, Eli Chen 4/16/00

Constructor Summary
LinearAccelerator(double startTempo, double endTempo, double numBeats)
          Create a new accelerando calculator given the starting tempo (beats per second), the ending tempo, and the number of "beats" over which to linearly interpolate this change.
 
Method Summary
 double acceleratedDuration(double startTime, double dur)
          Calculate the new duration of an event starting at startTime with duration dur.
static void main(java.lang.String[] args)
          Test accelerando.
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

LinearAccelerator

public LinearAccelerator(double startTempo,
                         double endTempo,
                         double numBeats)
Create a new accelerando calculator given the starting tempo (beats per second), the ending tempo, and the number of "beats" over which to linearly interpolate this change.

Method Detail

acceleratedDuration

public double acceleratedDuration(double startTime,
                                  double dur)
Calculate the new duration of an event starting at startTime with duration dur. Note that startTime and dur are NON-accelerated time. That is, the start time is just an accumulation of non-acceleared event durations.

Returns:
accelerated duration

main

public static void main(java.lang.String[] args)
Test accelerando. Comment out one or the other eventDurations array. Notice that the total accelerando time for both is the same. notice, too, that every other accelerated start time of the array of 0.5 durations coincides with the accelerated starting times of the array of 1.0 durations. In other words, these two would play in synch during the accelerando.

Source:
public static void main(String args[]) {
   // accelerate from 1 bps to 2 bps over 4 beats
   LinearAccelerator accel = new LinearAccelerator(1, 2, 4);
   double[] eventDurations = {1.0, 1.0, 1.0, 1.0};
   double nonAccelStartTime=0.0;                // needed to calculate
   double acceleratedStartTime = 0.0;   // just for fun
   for (int i=0; i < eventDurations.length; i++) {
      double nonAccelDur = eventDurations[i];
      double accelDur = accel.acceleratedDuration(nonAccelStartTime, nonAccelDur);
      System.out.println("event " + i);
      System.out.print("Non-accelerated starting time=" + nonAccelStartTime );
      System.out.print(", Non-accelerated dur= " + nonAccelDur);
      System.out.print(", Accelerated starting time=" + acceleratedStartTime );
      System.out.println(", Accelerated dur = " + accelDur);
      nonAccelStartTime += nonAccelDur;
      acceleratedStartTime += accelDur;
   }
   System.out.println("Total duration of accelerando =" +  acceleratedStartTime);
}