@@ -494,11 +494,8 @@ void Mixer::MixerFifo::Enqueue()
494
494
0 .0002984010f , 0 .0002102045f , 0 .0001443499f , 0 .0000961509f , 0 .0000616906f , 0 .0000377350f ,
495
495
0 .0000216492f , 0 .0000113187f , 0 .0000050749f , 0 .0000016272f };
496
496
497
- const std::size_t head = m_queue_head.load (std::memory_order_acquire);
498
-
499
497
// Check if we run out of space in the circular queue. (rare)
500
- std::size_t next_head = (head + 1 ) & GRANULE_QUEUE_MASK;
501
- if (next_head == m_queue_tail.load (std::memory_order_acquire))
498
+ if (m_queue.Size (std::memory_order_relaxed) == m_queue.Capacity ())
502
499
{
503
500
WARN_LOG_FMT (AUDIO,
504
501
" Granule Queue has completely filled and audio samples are being dropped. "
@@ -509,49 +506,47 @@ void Mixer::MixerFifo::Enqueue()
509
506
// By preconstructing the granule window, we have the best chance of
510
507
// the compiler optimizing this loop using SIMD instructions.
511
508
const std::size_t start_index = m_next_buffer_index;
509
+ auto & write_head = m_queue.GetWriteHead ();
510
+
512
511
for (std::size_t i = 0 ; i < GRANULE_SIZE; ++i)
513
- m_queue[head] [i] = m_next_buffer[(i + start_index) & GRANULE_MASK] * GRANULE_WINDOW[i];
512
+ write_head [i] = m_next_buffer[(i + start_index) & GRANULE_MASK] * GRANULE_WINDOW[i];
514
513
515
- m_queue_head. store (next_head, std::memory_order_release );
514
+ m_queue. AdvanceWriteHead ( 1 );
516
515
m_queue_looping.store (false , std::memory_order_relaxed);
517
516
}
518
517
519
518
void Mixer::MixerFifo::Dequeue (Granule* granule)
520
519
{
521
520
const std::size_t granule_queue_size = m_granule_queue_size.load (std::memory_order_relaxed);
522
- const std::size_t head = m_queue_head.load (std::memory_order_acquire);
523
- std::size_t tail = m_queue_tail.load (std::memory_order_acquire);
524
521
525
522
// Checks to see if the queue has gotten too long.
526
- if (granule_queue_size < ((head - tail) & GRANULE_QUEUE_MASK))
523
+ const auto size = m_queue.Size ();
524
+ if (size > granule_queue_size)
527
525
{
528
526
// Jump the playhead to half the queue size behind the head.
529
- const std::size_t gap = ( granule_queue_size >> 1 ) + 1 ;
530
- tail = (head - gap) & GRANULE_QUEUE_MASK ;
527
+ const std::size_t desired_size = granule_queue_size / 2 ;
528
+ m_queue. AdvanceReadHead (size - desired_size) ;
531
529
}
532
-
533
530
// Checks to see if the queue is empty.
534
- std::size_t next_tail = (tail + 1 ) & GRANULE_QUEUE_MASK;
535
- if (next_tail == head)
531
+ else if (size == 0 )
536
532
{
537
533
// Only fill gaps when running to prevent stutter on pause.
538
534
const bool is_running = Core::GetState (Core::System::GetInstance ()) == Core::State::Running;
539
535
if (m_mixer->m_config_fill_audio_gaps && is_running)
540
536
{
541
537
// Jump the playhead to half the queue size behind the head.
542
538
// This provides smoother audio playback than suddenly stopping.
543
- const std::size_t gap = std::max<std::size_t >(2 , granule_queue_size >> 1 ) - 1 ;
544
- next_tail = (head - gap) & GRANULE_QUEUE_MASK ;
539
+ const std::size_t adjustment = 0u - std::max<std::size_t >(1 , granule_queue_size / 2 ) ;
540
+ m_queue. AdvanceReadHead (adjustment) ;
545
541
m_queue_looping.store (true , std::memory_order_relaxed);
546
542
}
547
543
else
548
544
{
549
- std::fill (granule-> begin (), granule-> end () , StereoPair{0 .0f , 0 .0f });
545
+ std::ranges:: fill (* granule, StereoPair{0 .0f , 0 .0f });
550
546
m_queue_looping.store (false , std::memory_order_relaxed);
551
547
return ;
552
548
}
553
549
}
554
550
555
- *granule = m_queue[tail];
556
- m_queue_tail.store (next_tail, std::memory_order_release);
551
+ m_queue.Pop (granule);
557
552
}
0 commit comments