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