Skip to content

Commit ba5723d

Browse files
committed
AudioCommon: Make Mixer use Common::SPSCCircularQueue.
1 parent c1905a5 commit ba5723d

File tree

2 files changed

+17
-25
lines changed

2 files changed

+17
-25
lines changed

Source/Core/AudioCommon/Mixer.cpp

+14-19
Original file line numberDiff line numberDiff line change
@@ -494,11 +494,8 @@ void Mixer::MixerFifo::Enqueue()
494494
0.0002984010f, 0.0002102045f, 0.0001443499f, 0.0000961509f, 0.0000616906f, 0.0000377350f,
495495
0.0000216492f, 0.0000113187f, 0.0000050749f, 0.0000016272f};
496496

497-
const std::size_t head = m_queue_head.load(std::memory_order_acquire);
498-
499497
// 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())
502499
{
503500
WARN_LOG_FMT(AUDIO,
504501
"Granule Queue has completely filled and audio samples are being dropped. "
@@ -509,49 +506,47 @@ void Mixer::MixerFifo::Enqueue()
509506
// By preconstructing the granule window, we have the best chance of
510507
// the compiler optimizing this loop using SIMD instructions.
511508
const std::size_t start_index = m_next_buffer_index;
509+
auto& write_head = m_queue.GetWriteHead();
510+
512511
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];
514513

515-
m_queue_head.store(next_head, std::memory_order_release);
514+
m_queue.AdvanceWriteHead(1);
516515
m_queue_looping.store(false, std::memory_order_relaxed);
517516
}
518517

519518
void Mixer::MixerFifo::Dequeue(Granule* granule)
520519
{
521520
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);
524521

525522
// 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)
527525
{
528526
// 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);
531529
}
532-
533530
// 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)
536532
{
537533
// Only fill gaps when running to prevent stutter on pause.
538534
const bool is_running = Core::GetState(Core::System::GetInstance()) == Core::State::Running;
539535
if (m_mixer->m_config_fill_audio_gaps && is_running)
540536
{
541537
// Jump the playhead to half the queue size behind the head.
542538
// 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);
545541
m_queue_looping.store(true, std::memory_order_relaxed);
546542
}
547543
else
548544
{
549-
std::fill(granule->begin(), granule->end(), StereoPair{0.0f, 0.0f});
545+
std::ranges::fill(*granule, StereoPair{0.0f, 0.0f});
550546
m_queue_looping.store(false, std::memory_order_relaxed);
551547
return;
552548
}
553549
}
554550

555-
*granule = m_queue[tail];
556-
m_queue_tail.store(next_tail, std::memory_order_release);
551+
m_queue.Pop(granule);
557552
}

Source/Core/AudioCommon/Mixer.h

+3-6
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@
33

44
#pragma once
55

6-
#include <algorithm>
76
#include <array>
87
#include <atomic>
98
#include <bit>
10-
#include <cmath>
119

1210
#include "AudioCommon/SurroundDecoder.h"
1311
#include "AudioCommon/WaveFile.h"
12+
#include "Common/CircularQueue.h"
1413
#include "Common/CommonTypes.h"
1514
#include "Common/Config/Config.h"
1615

@@ -61,7 +60,6 @@ class Mixer final
6160
class MixerFifo final
6261
{
6362
static constexpr std::size_t MAX_GRANULE_QUEUE_SIZE = 256;
64-
static constexpr std::size_t GRANULE_QUEUE_MASK = MAX_GRANULE_QUEUE_SIZE - 1;
6563

6664
struct StereoPair final
6765
{
@@ -123,9 +121,8 @@ class Mixer final
123121
Granule m_front, m_back;
124122

125123
std::atomic<std::size_t> m_granule_queue_size{20};
126-
std::array<Granule, MAX_GRANULE_QUEUE_SIZE> m_queue;
127-
std::atomic<std::size_t> m_queue_head{0};
128-
std::atomic<std::size_t> m_queue_tail{0};
124+
Common::SPSCCircularArray<Granule, MAX_GRANULE_QUEUE_SIZE> m_queue;
125+
129126
std::atomic<bool> m_queue_looping{false};
130127
float m_fade_volume = 1.0;
131128

0 commit comments

Comments
 (0)