001
002 package ibxm;
003
004 public class Envelope {
005 public boolean sustain, looped;
006 private int sustain_tick, loop_start_tick, loop_end_tick;
007 private int[] ticks, ampls;
008
009 public Envelope() {
010 set_num_points( 1 );
011 }
012
013 public void set_num_points( int num_points ) {
014 int point;
015 if( num_points <= 0 ) {
016 num_points = 1;
017 }
018 ticks = new int[ num_points ];
019 ampls = new int[ num_points ];
020 set_point( 0, 0, 0, false );
021 }
022
023 /* When you set a point, all subsequent points are reset. */
024 public void set_point( int point, int tick, int ampl, boolean delta ) {
025 if( point >= 0 && point < ticks.length ) {
026 if( point == 0 ) {
027 tick = 0;
028 }
029 if( point > 0 ) {
030 if( delta ) tick += ticks[ point - 1 ];
031 if( tick <= ticks[ point - 1 ] ) {
032 System.out.println( "Envelope: Point not valid (" + tick + " <= " + ticks[ point - 1 ] + ")");
033 tick = ticks[ point - 1 ] + 1;
034 }
035 }
036 ticks[ point ] = tick;
037 ampls[ point ] = ampl;
038 point += 1;
039 while( point < ticks.length ) {
040 ticks[ point ] = ticks[ point - 1 ] + 1;
041 ampls[ point ] = 0;
042 point += 1;
043 }
044 }
045 }
046
047 public void set_sustain_point( int point ) {
048 if( point < 0 ) {
049 point = 0;
050 }
051 if( point >= ticks.length ) {
052 point = ticks.length - 1;
053 }
054 sustain_tick = ticks[ point ];
055 }
056
057 public void set_loop_points( int start, int end ) {
058 if( start < 0 ) {
059 start = 0;
060 }
061 if( start >= ticks.length ) {
062 start = ticks.length - 1;
063 }
064 if( end < start || end >= ticks.length ) {
065 end = start;
066 }
067 loop_start_tick = ticks[ start ];
068 loop_end_tick = ticks[ end ];
069 }
070
071 public int next_tick( int tick, boolean key_on ) {
072 tick = tick + 1;
073 if( looped && tick >= loop_end_tick ) {
074 tick = loop_start_tick;
075 }
076 if( sustain && key_on && tick >= sustain_tick ) {
077 tick = sustain_tick;
078 }
079 return tick;
080 }
081
082 public int calculate_ampl( int tick ) {
083 int idx, point, delta_t, delta_a, ampl;
084 ampl = ampls[ ticks.length - 1 ];
085 if( tick < ticks[ ticks.length - 1 ] ) {
086 point = 0;
087 for( idx = 1; idx < ticks.length; idx++ ) {
088 if( ticks[ idx ] <= tick ) {
089 point = idx;
090 }
091 }
092 delta_t = ticks[ point + 1 ] - ticks[ point ];
093 delta_a = ampls[ point + 1 ] - ampls[ point ];
094 ampl = ( delta_a << IBXM.FP_SHIFT ) / delta_t;
095 ampl = ampl * ( tick - ticks[ point ] ) >> IBXM.FP_SHIFT;
096 ampl = ampl + ampls[ point ];
097 }
098 return ampl;
099 }
100
101 public void dump() {
102 int idx, tick;
103 for( idx = 0; idx < ticks.length; idx++ ) {
104 System.out.println( ticks[ idx ] + ", " + ampls[ idx ] );
105 }
106 for( tick = 0; tick < 222; tick++ ) {
107 System.out.print( calculate_ampl( tick ) + ", " );
108 }
109 }
110 }
111