@@ -48,13 +48,11 @@ void PerformerController::Release(uint32_t performer_index) noexcept {
4848uint32_t PerformerController::AcquireTask (uint32_t performer_index, double position,
4949 double duration, int32_t priority,
5050 BarelyTaskCallback callback, void * user_data) noexcept {
51+ assert (duration >= 0.0 );
5152 const uint32_t task_index = engine_.task_pool .Acquire ();
5253 if (task_index != kInvalidIndex ) {
5354 TaskState& task = engine_.GetTask (task_index);
54- task = {
55- {callback, user_data}, position, std::max (duration, kMinTaskDuration ), priority,
56- performer_index,
57- };
55+ task = {{callback, user_data}, position, duration, priority, performer_index};
5856 InsertInactiveTask (engine_.GetPerformer (performer_index), task_index);
5957 }
6058 return task_index;
@@ -116,17 +114,7 @@ void PerformerController::SetPosition(uint32_t performer_index, double position)
116114 }
117115 } else {
118116 performer.position = position;
119- uint32_t task_index = performer.first_active_task_index ;
120- while (task_index != kInvalidIndex ) {
121- auto & task = engine_.GetTask (task_index);
122- if (task.IsInside (performer.position )) {
123- task_index = task.next_task_index ;
124- } else {
125- SetTaskActive (performer, task_index, false );
126- // Restart the iteration since links can get invalidated after a callback.
127- task_index = performer.first_active_task_index ;
128- }
129- }
117+ UpdateActiveTasks (performer);
130118 }
131119}
132120
@@ -143,9 +131,9 @@ void PerformerController::Stop(uint32_t performer_index) noexcept {
143131}
144132
145133void PerformerController::SetTaskDuration (uint32_t task_index, double duration) noexcept {
134+ assert (duration >= 0.0 );
146135 auto & task = engine_.GetTask (task_index);
147136 auto & performer = engine_.GetPerformer (task.performer_index );
148- duration = std::max (duration, kMinTaskDuration );
149137 if (task.duration == duration) return ;
150138 task.duration = duration;
151139 if (task.is_active ) {
@@ -195,7 +183,8 @@ void PerformerController::SetTaskPriority(uint32_t task_index, int32_t priority)
195183 }
196184}
197185
198- void PerformerController::ProcessAllTasksAtPosition (int32_t max_priority) noexcept {
186+ void PerformerController::ProcessAllTasksAtPosition (const std::optional<int32_t >& min_priority,
187+ int32_t max_priority) noexcept {
199188 for (uint32_t i = 0 ; i < engine_.performer_pool .ActiveCount (); ++i) {
200189 auto & performer = engine_.GetPerformer (engine_.performer_pool .GetActive (i));
201190 if (!performer.is_playing ) {
@@ -204,23 +193,16 @@ void PerformerController::ProcessAllTasksAtPosition(int32_t max_priority) noexce
204193 // Active tasks get processed in `SetPosition`, so we only need to process inactive tasks.
205194 for (uint32_t task_index = GetNextInactiveTask (performer); task_index != kInvalidIndex ;
206195 task_index = GetNextInactiveTask (performer)) {
207- const auto & task = engine_.GetTask (task_index);
208- if (!task.IsInside (performer.position ) ||
209- (task.position >= performer.position && task.priority > max_priority)) {
196+ auto & task = engine_.GetTask (task_index);
197+ if (task.IsInside (performer.position ) ||
198+ (task.position == performer.position && task.priority <= max_priority &&
199+ (task.duration > 0.0 || !min_priority.has_value () || task.priority > *min_priority))) {
200+ SetTaskActive (performer, task_index, true );
201+ } else {
210202 break ;
211203 }
212- SetTaskActive (performer, task_index, true );
213- }
214- }
215- }
216-
217- void PerformerController::Update (double duration) noexcept {
218- assert (duration > 0.0 );
219- for (uint32_t i = 0 ; i < engine_.performer_pool .ActiveCount (); ++i) {
220- const uint32_t performer_index = engine_.performer_pool .GetActive (i);
221- if (const auto & performer = engine_.GetPerformer (performer_index); performer.is_playing ) {
222- SetPosition (performer_index, performer.position + duration);
223204 }
205+ UpdateActiveTasks (performer);
224206 }
225207}
226208
@@ -320,6 +302,20 @@ void PerformerController::SetTaskActive(PerformerState& performer, uint32_t task
320302 }
321303}
322304
305+ void PerformerController::UpdateActiveTasks (PerformerState& performer) noexcept {
306+ uint32_t task_index = performer.first_active_task_index ;
307+ while (task_index != kInvalidIndex ) {
308+ auto & task = engine_.GetTask (task_index);
309+ if (task.IsInside (performer.position )) {
310+ task_index = task.next_task_index ;
311+ } else {
312+ SetTaskActive (performer, task_index, false );
313+ // Restart the iteration since links can get invalidated after a callback.
314+ task_index = performer.first_active_task_index ;
315+ }
316+ }
317+ }
318+
323319uint32_t PerformerController::GetNextInactiveTask (const PerformerState& performer) const noexcept {
324320 if (!performer.is_playing ) {
325321 return kInvalidIndex ;
@@ -335,8 +331,9 @@ uint32_t PerformerController::GetNextInactiveTask(const PerformerState& performe
335331 return kInvalidIndex ;
336332}
337333
338- void PerformerController::GetNextTaskEvent (const PerformerState& performer, double & duration,
339- int32_t & priority) const noexcept {
334+ void PerformerController::GetNextTaskEvent (const PerformerState& performer,
335+ const std::optional<int32_t >& min_priority,
336+ double & duration, int32_t & priority) const noexcept {
340337 if (!performer.is_playing ) {
341338 return ;
342339 }
@@ -347,30 +344,33 @@ void PerformerController::GetNextTaskEvent(const PerformerState& performer, doub
347344 uint32_t task_index = performer.first_inactive_task_index ;
348345 while (task_index != kInvalidIndex ) {
349346 const auto & task = engine_.GetTask (task_index);
350- if (task.position < performer.position ||
351- (task.position == performer.position && task.priority <= priority)) {
347+ if (task.position <= performer.position ) {
352348 // If the performer position is inside an inactive task, we can return immediately.
353- if (task.GetEndPosition () > performer.position ) {
349+ if (task.GetEndPosition () > performer.position ||
350+ (task.position == performer.position &&
351+ (!min_priority.has_value () || *min_priority < task.priority ))) {
352+ priority = (duration > 0.0 ) ? task.priority : std::min (task.priority , priority);
354353 duration = 0.0 ;
355- priority = std::min (task.priority , priority);
356354 return ;
357355 }
358356 if (performer.is_looping && task.position >= performer.loop_begin_position &&
359357 task.position < loop_end_position) {
360- const double looped_inactive_duration =
361- task.position - performer.position + performer.loop_length ;
362- if (looped_inactive_duration < duration ||
363- (looped_inactive_duration == duration && task.priority < priority)) {
358+ if (const double looped_inactive_duration =
359+ task.position - performer.position + performer.loop_length ;
360+ looped_inactive_duration < duration) {
364361 duration = looped_inactive_duration;
365362 priority = task.priority ;
363+ } else if (looped_inactive_duration == duration && task.priority < priority) {
364+ priority = task.priority ;
366365 }
367366 }
368367 } else {
369- const double inactive_duration = task.position - performer.position ;
370- if (inactive_duration < duration ||
371- (inactive_duration == duration && task.priority < priority)) {
368+ if (const double inactive_duration = task.position - performer.position ;
369+ inactive_duration < duration) {
372370 duration = inactive_duration;
373371 priority = task.priority ;
372+ } else if (inactive_duration == duration && task.priority < priority) {
373+ priority = task.priority ;
374374 }
375375 break ;
376376 }
@@ -383,11 +383,12 @@ void PerformerController::GetNextTaskEvent(const PerformerState& performer, doub
383383 const double end_position = performer.is_looping
384384 ? std::min (active_task.GetEndPosition (), loop_end_position)
385385 : active_task.GetEndPosition ();
386- const double active_duration = end_position - performer.position ;
387- if (active_duration < duration ||
388- (active_duration == duration && active_task.priority < priority)) {
386+ if (const double active_duration = end_position - performer.position ;
387+ active_duration < duration) {
389388 duration = active_duration;
390389 priority = active_task.priority ;
390+ } else if (active_duration == duration && active_task.priority < priority) {
391+ priority = active_task.priority ;
391392 }
392393 }
393394}
0 commit comments