001 002 package ibxm; 003 004 public class Sample { 005 public String name; 006 public boolean set_panning; 007 public int volume, panning; 008 public int transpose; 009 010 private int loop_start, loop_length; 011 private short[] sample_data; 012 013 /* For the sinc interpolator.*/ 014 private static final int POINT_SHIFT = 4; 015 private static final int POINTS = 1 << POINT_SHIFT; 016 private static final int OVERLAP = POINTS >> 1; 017 private static final int INTERP_SHIFT = IBXM.FP_SHIFT - 4; 018 private static final int INTERP_BITMASK = ( 1 << INTERP_SHIFT ) - 1; 019 private static final short[] sinc_table = { 020 0, -7, 27, -71, 142, -227, 299, 32439, 299, -227, 142, -71, 27, -7, 0, 0, 021 0, 0, -5, 36, -142, 450, -1439, 32224, 2302, -974, 455, -190, 64, -15, 2, 0, 022 0, 6, -33, 128, -391, 1042, -2894, 31584, 4540, -1765, 786, -318, 105, -25, 3, 0, 023 0, 10, -55, 204, -597, 1533, -4056, 30535, 6977, -2573, 1121, -449, 148, -36, 5, 0, 024 -1, 13, -71, 261, -757, 1916, -4922, 29105, 9568, -3366, 1448, -578, 191, -47, 7, 0, 025 -1, 15, -81, 300, -870, 2185, -5498, 27328, 12263, -4109, 1749, -698, 232, -58, 9, 0, 026 -1, 15, -86, 322, -936, 2343, -5800, 25249, 15006, -4765, 2011, -802, 269, -68, 10, 0, 027 -1, 15, -87, 328, -957, 2394, -5849, 22920, 17738, -5298, 2215, -885, 299, -77, 12, 0, 028 0, 14, -83, 319, -938, 2347, -5671, 20396, 20396, -5671, 2347, -938, 319, -83, 14, 0, 029 0, 12, -77, 299, -885, 2215, -5298, 17738, 22920, -5849, 2394, -957, 328, -87, 15, -1, 030 0, 10, -68, 269, -802, 2011, -4765, 15006, 25249, -5800, 2343, -936, 322, -86, 15, -1, 031 0, 9, -58, 232, -698, 1749, -4109, 12263, 27328, -5498, 2185, -870, 300, -81, 15, -1, 032 0, 7, -47, 191, -578, 1448, -3366, 9568, 29105, -4922, 1916, -757, 261, -71, 13, -1, 033 0, 5, -36, 148, -449, 1121, -2573, 6977, 30535, -4056, 1533, -597, 204, -55, 10, 0, 034 0, 3, -25, 105, -318, 786, -1765, 4540, 31584, -2894, 1042, -391, 128, -33, 6, 0, 035 0, 2, -15, 64, -190, 455, -974, 2302, 32224, -1439, 450, -142, 36, -5, 0, 0, 036 0, 0, -7, 27, -71, 142, -227, 299, 32439, 299, -227, 142, -71, 27, -7, 0 037 }; 038 039 public Sample() { 040 name = ""; 041 set_sample_data( new short[ 0 ], 0, 0, false ); 042 } 043 044 public void set_sample_data( short[] data, int loop_start, int loop_length, boolean ping_pong ) { 045 int offset; 046 short sample; 047 if( loop_start < 0 ) { 048 loop_start = 0; 049 } 050 if( loop_start >= data.length ) { 051 loop_start = data.length - 1; 052 } 053 if( loop_start + loop_length > data.length ) { 054 loop_length = data.length - loop_start; 055 } 056 if( loop_length <= 1 ) { 057 sample_data = new short[ OVERLAP + data.length + OVERLAP * 3 ]; 058 System.arraycopy( data, 0, sample_data, OVERLAP, data.length ); 059 offset = 0; 060 while( offset < OVERLAP ) { 061 sample = sample_data[ OVERLAP + data.length - 1 ]; 062 sample = ( short ) ( sample * ( OVERLAP - offset ) / OVERLAP ); 063 sample_data[ OVERLAP + data.length + offset ] = sample; 064 offset += 1; 065 } 066 loop_start = OVERLAP + data.length + OVERLAP; 067 loop_length = 1; 068 } else { 069 if( ping_pong ) { 070 sample_data = new short[ OVERLAP + loop_start + loop_length * 2 + OVERLAP * 2 ]; 071 System.arraycopy( data, 0, sample_data, OVERLAP, loop_start + loop_length ); 072 offset = 0; 073 while( offset < loop_length ) { 074 sample = data[ loop_start + loop_length - offset - 1 ]; 075 sample_data[ OVERLAP + loop_start + loop_length + offset ] = sample; 076 offset += 1; 077 } 078 loop_start = loop_start + OVERLAP; 079 loop_length = loop_length * 2; 080 } else { 081 sample_data = new short[ OVERLAP + loop_start + loop_length + OVERLAP * 2 ]; 082 System.arraycopy( data, 0, sample_data, OVERLAP, loop_start + loop_length ); 083 loop_start = loop_start + OVERLAP; 084 } 085 offset = 0; 086 while( offset < OVERLAP * 2 ) { 087 sample = sample_data[ loop_start + offset ]; 088 sample_data[ loop_start + loop_length + offset ] = sample; 089 offset += 1; 090 } 091 } 092 this.loop_start = loop_start; 093 this.loop_length = loop_length; 094 } 095 096 public void resample_nearest( 097 int sample_idx, int sample_frac, int step, int left_gain, int right_gain, 098 int[] mix_buffer, int frame_offset, int frames ) { 099 int loop_end, offset, end, max_sample_idx; 100 sample_idx += OVERLAP; 101 loop_end = loop_start + loop_length - 1; 102 offset = frame_offset << 1; 103 end = ( frame_offset + frames - 1 ) << 1; 104 while( frames > 0 ) { 105 if( sample_idx > loop_end ) { 106 if( loop_length <= 1 ) { 107 break; 108 } 109 sample_idx = loop_start + ( sample_idx - loop_start ) % loop_length; 110 } 111 max_sample_idx = sample_idx + ( ( sample_frac + ( frames - 1 ) * step ) >> IBXM.FP_SHIFT ); 112 if( max_sample_idx > loop_end ) { 113 while( sample_idx <= loop_end ) { 114 mix_buffer[ offset++ ] += sample_data[ sample_idx ] * left_gain >> IBXM.FP_SHIFT; 115 mix_buffer[ offset++ ] += sample_data[ sample_idx ] * right_gain >> IBXM.FP_SHIFT; 116 sample_frac += step; 117 sample_idx += sample_frac >> IBXM.FP_SHIFT; 118 sample_frac &= IBXM.FP_MASK; 119 } 120 } else { 121 while( offset <= end ) { 122 mix_buffer[ offset++ ] += sample_data[ sample_idx ] * left_gain >> IBXM.FP_SHIFT; 123 mix_buffer[ offset++ ] += sample_data[ sample_idx ] * right_gain >> IBXM.FP_SHIFT; 124 sample_frac += step; 125 sample_idx += sample_frac >> IBXM.FP_SHIFT; 126 sample_frac &= IBXM.FP_MASK; 127 } 128 } 129 frames = ( end - offset + 2 ) >> 1; 130 } 131 } 132 133 public void resample_linear( 134 int sample_idx, int sample_frac, int step, int left_gain, int right_gain, 135 int[] mix_buffer, int frame_offset, int frames ) { 136 int loop_end, offset, end, max_sample_idx, amplitude; 137 sample_idx += OVERLAP; 138 loop_end = loop_start + loop_length - 1; 139 offset = frame_offset << 1; 140 end = ( frame_offset + frames - 1 ) << 1; 141 while( frames > 0 ) { 142 if( sample_idx > loop_end ) { 143 if( loop_length <= 1 ) { 144 break; 145 } 146 sample_idx = loop_start + ( sample_idx - loop_start ) % loop_length; 147 } 148 max_sample_idx = sample_idx + ( ( sample_frac + ( frames - 1 ) * step ) >> IBXM.FP_SHIFT ); 149 if( max_sample_idx > loop_end ) { 150 while( sample_idx <= loop_end ) { 151 amplitude = sample_data[ sample_idx ]; 152 amplitude += ( sample_data[ sample_idx + 1 ] - amplitude ) * sample_frac >> IBXM.FP_SHIFT; 153 mix_buffer[ offset++ ] += amplitude * left_gain >> IBXM.FP_SHIFT; 154 mix_buffer[ offset++ ] += amplitude * right_gain >> IBXM.FP_SHIFT; 155 sample_frac += step; 156 sample_idx += sample_frac >> IBXM.FP_SHIFT; 157 sample_frac &= IBXM.FP_MASK; 158 } 159 } else { 160 while( offset <= end ) { 161 amplitude = sample_data[ sample_idx ]; 162 amplitude += ( sample_data[ sample_idx + 1 ] - amplitude ) * sample_frac >> IBXM.FP_SHIFT; 163 mix_buffer[ offset++ ] += amplitude * left_gain >> IBXM.FP_SHIFT; 164 mix_buffer[ offset++ ] += amplitude * right_gain >> IBXM.FP_SHIFT; 165 sample_frac += step; 166 sample_idx += sample_frac >> IBXM.FP_SHIFT; 167 sample_frac &= IBXM.FP_MASK; 168 } 169 } 170 frames = ( end - offset + 2 ) >> 1; 171 } 172 } 173 174 public void resample_sinc( 175 int sample_idx, int sample_frac, int step, int left_gain, int right_gain, 176 int[] mix_buffer, int frame_offset, int frames ) { 177 int offset, end, loop_end, table_idx, a1, a2, amplitude; 178 loop_end = loop_start + loop_length - 1; 179 offset = frame_offset << 1; 180 end = ( frame_offset + frames - 1 ) << 1; 181 while( offset <= end ) { 182 if( sample_idx > loop_end ) { 183 if( loop_length <= 1 ) { 184 break; 185 } 186 sample_idx = loop_start + ( sample_idx - loop_start ) % loop_length; 187 } 188 table_idx = ( sample_frac >> INTERP_SHIFT ) << POINT_SHIFT; 189 a1 = sinc_table[ table_idx + 0 ] * sample_data[ sample_idx + 0 ] >> 15; 190 a1 += sinc_table[ table_idx + 1 ] * sample_data[ sample_idx + 1 ] >> 15; 191 a1 += sinc_table[ table_idx + 2 ] * sample_data[ sample_idx + 2 ] >> 15; 192 a1 += sinc_table[ table_idx + 3 ] * sample_data[ sample_idx + 3 ] >> 15; 193 a1 += sinc_table[ table_idx + 4 ] * sample_data[ sample_idx + 4 ] >> 15; 194 a1 += sinc_table[ table_idx + 5 ] * sample_data[ sample_idx + 5 ] >> 15; 195 a1 += sinc_table[ table_idx + 6 ] * sample_data[ sample_idx + 6 ] >> 15; 196 a1 += sinc_table[ table_idx + 7 ] * sample_data[ sample_idx + 7 ] >> 15; 197 a1 += sinc_table[ table_idx + 8 ] * sample_data[ sample_idx + 8 ] >> 15; 198 a1 += sinc_table[ table_idx + 9 ] * sample_data[ sample_idx + 9 ] >> 15; 199 a1 += sinc_table[ table_idx + 10 ] * sample_data[ sample_idx + 10 ] >> 15; 200 a1 += sinc_table[ table_idx + 11 ] * sample_data[ sample_idx + 11 ] >> 15; 201 a1 += sinc_table[ table_idx + 12 ] * sample_data[ sample_idx + 12 ] >> 15; 202 a1 += sinc_table[ table_idx + 13 ] * sample_data[ sample_idx + 13 ] >> 15; 203 a1 += sinc_table[ table_idx + 14 ] * sample_data[ sample_idx + 14 ] >> 15; 204 a1 += sinc_table[ table_idx + 15 ] * sample_data[ sample_idx + 15 ] >> 15; 205 a2 = sinc_table[ table_idx + 16 ] * sample_data[ sample_idx + 0 ] >> 15; 206 a2 += sinc_table[ table_idx + 17 ] * sample_data[ sample_idx + 1 ] >> 15; 207 a2 += sinc_table[ table_idx + 18 ] * sample_data[ sample_idx + 2 ] >> 15; 208 a2 += sinc_table[ table_idx + 19 ] * sample_data[ sample_idx + 3 ] >> 15; 209 a2 += sinc_table[ table_idx + 20 ] * sample_data[ sample_idx + 4 ] >> 15; 210 a2 += sinc_table[ table_idx + 21 ] * sample_data[ sample_idx + 5 ] >> 15; 211 a2 += sinc_table[ table_idx + 22 ] * sample_data[ sample_idx + 6 ] >> 15; 212 a2 += sinc_table[ table_idx + 23 ] * sample_data[ sample_idx + 7 ] >> 15; 213 a2 += sinc_table[ table_idx + 24 ] * sample_data[ sample_idx + 8 ] >> 15; 214 a2 += sinc_table[ table_idx + 25 ] * sample_data[ sample_idx + 9 ] >> 15; 215 a2 += sinc_table[ table_idx + 26 ] * sample_data[ sample_idx + 10 ] >> 15; 216 a2 += sinc_table[ table_idx + 27 ] * sample_data[ sample_idx + 11 ] >> 15; 217 a2 += sinc_table[ table_idx + 28 ] * sample_data[ sample_idx + 12 ] >> 15; 218 a2 += sinc_table[ table_idx + 29 ] * sample_data[ sample_idx + 13 ] >> 15; 219 a2 += sinc_table[ table_idx + 30 ] * sample_data[ sample_idx + 14 ] >> 15; 220 a2 += sinc_table[ table_idx + 31 ] * sample_data[ sample_idx + 15 ] >> 15; 221 amplitude = a1 + ( ( a2 - a1 ) * ( sample_frac & INTERP_BITMASK ) >> INTERP_SHIFT ); 222 mix_buffer[ offset ] += amplitude * left_gain >> IBXM.FP_SHIFT; 223 mix_buffer[ offset + 1 ] += amplitude * right_gain >> IBXM.FP_SHIFT; 224 offset += 2; 225 sample_frac += step; 226 sample_idx += sample_frac >> IBXM.FP_SHIFT; 227 sample_frac &= IBXM.FP_MASK; 228 } 229 } 230 231 public boolean has_finished( int sample_idx ) { 232 boolean finished; 233 finished = false; 234 if( loop_length <= 1 && sample_idx > loop_start ) { 235 finished = true; 236 } 237 return finished; 238 } 239 }