22
33#[ derive( Debug , Default ) ]
44struct Channel {
5- sample_num : u8 ,
5+ sample_data : Option < * const u8 > ,
6+ sample_loops : bool ,
7+ sample_length : usize ,
8+ repeat_length : usize ,
9+ repeat_point : usize ,
610 volume : u8 ,
711 note_period : u16 ,
812 sample_position : neotracker:: Fractional ,
13+ note_step : neotracker:: Fractional ,
914 effect : Option < neotracker:: Effect > ,
1015}
1116
@@ -103,12 +108,20 @@ impl<'a> Player<'a> {
103108 if note. is_empty ( ) {
104109 let _ = write ! ( out, "--- -----|" ) ;
105110 } else {
106- if let Some ( sample) = self . modfile . sample_info ( note. sample_no ( ) ) {
111+ if let Some ( sample) = self . modfile . sample ( note. sample_no ( ) ) {
112+ // if the period is zero, keep playing the old note
107113 if note. period ( ) != 0 {
108114 ch. note_period = note. period ( ) ;
115+ ch. note_step = self
116+ . clock_ticks_per_device_sample
117+ . apply_period ( ch. note_period ) ;
109118 }
110119 ch. volume = sample. volume ( ) ;
111- ch. sample_num = note. sample_no ( ) ;
120+ ch. sample_data = Some ( sample. raw_sample_bytes ( ) . as_ptr ( ) ) ;
121+ ch. sample_loops = sample. loops ( ) ;
122+ ch. sample_length = sample. sample_length_bytes ( ) ;
123+ ch. repeat_length = sample. repeat_length_bytes ( ) ;
124+ ch. repeat_point = sample. repeat_point_bytes ( ) ;
112125 ch. sample_position = neotracker:: Fractional :: default ( ) ;
113126 }
114127 let _ = write ! (
@@ -177,6 +190,9 @@ impl<'a> Player<'a> {
177190 neotracker:: shift_period ( ch. note_period , half_steps)
178191 {
179192 ch. note_period = new_period;
193+ ch. note_step = self
194+ . clock_ticks_per_device_sample
195+ . apply_period ( ch. note_period ) ;
180196 }
181197 } else if self . ticks_left == lower_third {
182198 let first_half_steps = n >> 4 ;
@@ -186,14 +202,23 @@ impl<'a> Player<'a> {
186202 second_half_steps - first_half_steps,
187203 ) {
188204 ch. note_period = new_period;
205+ ch. note_step = self
206+ . clock_ticks_per_device_sample
207+ . apply_period ( ch. note_period ) ;
189208 }
190209 }
191210 }
192211 Some ( neotracker:: Effect :: SlideUp ( n) ) => {
193212 ch. note_period -= u16:: from ( n) ;
213+ ch. note_step = self
214+ . clock_ticks_per_device_sample
215+ . apply_period ( ch. note_period ) ;
194216 }
195217 Some ( neotracker:: Effect :: SlideDown ( n) ) => {
196218 ch. note_period += u16:: from ( n) ;
219+ ch. note_step = self
220+ . clock_ticks_per_device_sample
221+ . apply_period ( ch. note_period ) ;
197222 }
198223 Some ( neotracker:: Effect :: VolumeSlide ( n) ) => {
199224 let new_volume = ( ch. volume as i8 ) + n;
@@ -215,34 +240,27 @@ impl<'a> Player<'a> {
215240 let mut left_sample = 0 ;
216241 let mut right_sample = 0 ;
217242 for ( ch_idx, ch) in self . channels . iter_mut ( ) . enumerate ( ) {
218- if ch. sample_num == 0 || ch. note_period == 0 {
243+ if ch. note_period == 0 || ch. sample_length == 0 {
219244 continue ;
220245 }
221- let current_sample = self . modfile . sample ( ch. sample_num ) . expect ( "bad sample" ) ;
222- let sample_data = current_sample. raw_sample_bytes ( ) ;
223- if sample_data. is_empty ( ) {
246+ let Some ( sample_data) = ch. sample_data else {
224247 continue ;
225- }
248+ } ;
226249 let integer_pos = ch. sample_position . as_index ( ) ;
227- let sample_byte = sample_data. get ( integer_pos) . cloned ( ) . unwrap_or_default ( ) ;
250+ let sample_byte = unsafe { sample_data. add ( integer_pos) . read ( ) } as i8 ;
228251 let mut channel_value = ( sample_byte as i8 ) as i32 ;
229252 // max channel vol (64), sample range [-128,127] scaled to [-32768, 32767]
230253 channel_value *= 256 ;
231254 channel_value *= i32:: from ( ch. volume ) ;
232255 channel_value /= 64 ;
233256 // move the sample index by a non-integer amount
234- ch. sample_position += self
235- . clock_ticks_per_device_sample
236- . apply_period ( ch. note_period ) ;
257+ ch. sample_position += ch. note_step ;
237258 // loop sample if required
238- if current_sample. loops ( ) {
239- if ch. sample_position . as_index ( )
240- >= ( current_sample. repeat_point_bytes ( ) + current_sample. repeat_length_bytes ( ) )
241- {
242- ch. sample_position =
243- neotracker:: Fractional :: new ( current_sample. repeat_point_bytes ( ) as u32 ) ;
259+ if ch. sample_loops {
260+ if ch. sample_position . as_index ( ) >= ( ch. repeat_point + ch. repeat_length ) {
261+ ch. sample_position = neotracker:: Fractional :: new ( ch. repeat_point as u32 ) ;
244262 }
245- } else if ch. sample_position . as_index ( ) >= current_sample . sample_length_bytes ( ) {
263+ } else if ch. sample_position . as_index ( ) >= ch . sample_length {
246264 // stop playing sample
247265 ch. note_period = 0 ;
248266 }
0 commit comments