Skip to content

Commit ce06af7

Browse files
committed
Play from step
1 parent d0dc142 commit ce06af7

File tree

3 files changed

+95
-14
lines changed

3 files changed

+95
-14
lines changed

Applications/Sequencer/ControlBar.cpp

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -191,19 +191,33 @@ bool SequencerControlBar::HandleStepPlayKey(KeyInfo *keyInfo)
191191
}
192192
else if (keyInfo->state == RELEASED && keyInfo->Hold() == false)
193193
{
194-
// bool trackPlaying = sequencer->sequence.Playing(sequencer->track);
195-
// if (trackPlaying)
196-
// {
197-
// sequencer->sequence.StopAfter(sequencer->track);
198-
// }
199-
// else
200-
// {
201-
// sequencer->sequence.Play(sequencer->track);
202-
// if (sequencer->currentView == Sequencer::ViewMode::StepDetail)
203-
// {
204-
// sequencer->SetView(Sequencer::ViewMode::Sequencer);
205-
// }
206-
// }
194+
if (sequencer->sequence.Playing(sequencer->track))
195+
{
196+
sequencer->sequence.StopAfter(sequencer->track);
197+
}
198+
else if(sequencer->sequence.Playing())
199+
{
200+
// Launch track in next possible bar
201+
sequencer->sequence.Play(sequencer->track);
202+
uint8_t pattern = std::get<0>(*sequencer->stepSelected.begin());
203+
SequencePosition* pos = sequencer->sequence.GetPosition(sequencer->track);
204+
if(pattern != pos->pattern)
205+
{
206+
sequencer->stepSelected.clear();
207+
sequencer->ClearActiveNotes();
208+
}
209+
}
210+
else
211+
{
212+
if(sequencer->stepSelected.size() == 1)
213+
{
214+
SequencePosition* pos = sequencer->sequence.GetPosition(sequencer->track);
215+
uint8_t currentPattern = pos->pattern;
216+
uint8_t pattern = std::get<0>(*sequencer->stepSelected.begin());
217+
uint8_t step = std::get<1>(*sequencer->stepSelected.begin());
218+
sequencer->sequence.PlayFrom(sequencer->track, pos->clip, pattern, step);
219+
}
220+
}
207221
}
208222
return true;
209223
}

Applications/Sequencer/Sequence.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
250316
void Sequence::Resume()
251317
{
252318
if(CanResume() == false)

Applications/Sequencer/Sequence.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class Sequence
2626
bool clockOutput = false;
2727

2828
// Clip switching timing
29-
uint16_t barLength = 16; // Length of each bay in steps
29+
uint16_t barLength = 16; // Length of each bar in steps
3030

3131
// Internal sequencer timing (96 PPQN)
3232
uint32_t lastPulseTime = 0; // Last time the sequencer tick was processed (microseconds)
@@ -78,6 +78,7 @@ class Sequence
7878
void Play(uint8_t track);
7979
void PlayClip(uint8_t track, uint8_t clip);
8080
void PlayClipForAllTracks(uint8_t clip);
81+
void PlayFrom(uint8_t track, uint8_t clip, uint8_t pattern, uint8_t step);
8182
void Resume();
8283
bool CanResume();
8384
bool Playing();

0 commit comments

Comments
 (0)