@@ -247,6 +247,72 @@ void Sequence::PlayClipForAllTracks(uint8_t clip)
247247 }
248248}
249249
250+ void Sequence::PlayFrom (uint8_t track, uint8_t clip, uint8_t pattern, uint8_t step)
251+ {
252+ // Validate clip exists
253+ if (!ClipExists (track, clip)) return ;
254+
255+ // Validate pattern exists
256+ if (pattern >= GetPatternCount (track, clip)) return ;
257+
258+ // Get the pattern to validate step
259+ SequencePattern* targetPattern = GetPattern (track, clip, pattern);
260+ if (!targetPattern) return ;
261+
262+ // Validate step is within pattern bounds
263+ if (step >= targetPattern->steps ) return ;
264+
265+ // Initialize timing if not already playing
266+ if (!playing) {
267+ playing = true ;
268+ clocksTillStart = record ? 24 * 4 + 1 : 1 ;
269+ currentPulse = UINT16_MAX;
270+ pulseSinceStart = 0 ;
271+ currentRecordLayer = 0 ;
272+
273+ for (uint8_t i = 0 ; i < trackPlayback.size (); i++) {
274+ // Reset positions and prepare for playback
275+ trackPlayback[i].position .pattern = 0 ;
276+ trackPlayback[i].position .step = 0 ;
277+ trackPlayback[i].position .pulse = UINT16_MAX; // so first advance lands on 0
278+
279+ // Clear playback state
280+ trackPlayback[i].nextClip = 255 ;
281+ trackPlayback[i].playing = false ;
282+ trackPlayback[i].canResume = false ; // Clear resume state when starting fresh playback
283+ trackPlayback[i].noteOffMap .clear ();
284+ trackPlayback[i].noteOffQueue .clear ();
285+ }
286+ }
287+
288+ // Set the track position directly to our target location
289+ trackPlayback[track].position .clip = clip;
290+ trackPlayback[track].position .pattern = pattern;
291+ trackPlayback[track].position .step = step;
292+ trackPlayback[track].position .pulse = UINT16_MAX; // Will advance to 0 on first tick
293+
294+ // Start playback for this track
295+ trackPlayback[track].playing = true ;
296+ trackPlayback[track].nextClip = 255 ; // No queued clip change
297+
298+ // Calculate steps elapsed from clip start to our starting position
299+ uint16_t stepSinceStart = 0 ;
300+
301+ // Sum up all steps in patterns before our target pattern
302+ for (uint8_t p = 0 ; p < pattern; p++) {
303+ SequencePattern* pat = GetPattern (track, clip, p);
304+ if (pat) {
305+ stepSinceStart += pat->steps ;
306+ }
307+ }
308+
309+ // Add steps within the target pattern up to our starting step
310+ stepSinceStart += step;
311+
312+ // Set currentStep to sync with bar boundaries
313+ currentStep = stepSinceStart % barLength;
314+ }
315+
250316void Sequence::Resume ()
251317{
252318 if (CanResume () == false )
0 commit comments