    001
    002package ibxm;
    003
    004public 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