    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