audio: switch waveout backend to pull rendering
This commit is contained in:
@@ -64,8 +64,7 @@ bool WaveOutBackend::Initialize(const AudioConfig& config) {
|
||||
const size_t bufferSampleCount = static_cast<size_t>(config.bufferSize) * config.channels;
|
||||
m_audioBuffer1.assign(bufferSampleCount, 0);
|
||||
m_audioBuffer2.assign(bufferSampleCount, 0);
|
||||
m_pendingMixBuffer.assign(bufferSampleCount, 0.0f);
|
||||
m_hasPendingMix = false;
|
||||
m_renderBuffer.assign(bufferSampleCount, 0.0f);
|
||||
m_buffer1Available = true;
|
||||
m_buffer2Available = true;
|
||||
|
||||
@@ -152,7 +151,7 @@ void WaveOutBackend::Start() {
|
||||
|
||||
void WaveOutBackend::Stop() {
|
||||
m_isRunning = false;
|
||||
m_dataReadyCond.notify_all();
|
||||
m_bufferReadyCond.notify_all();
|
||||
|
||||
if (m_hWaveOut != nullptr) {
|
||||
waveOutReset(m_hWaveOut);
|
||||
@@ -180,20 +179,15 @@ void WaveOutBackend::Resume() {
|
||||
|
||||
void WaveOutBackend::ProcessAudio(float* buffer, uint32 frameCount,
|
||||
uint32 channels, uint32 sampleRate) {
|
||||
(void)buffer;
|
||||
(void)frameCount;
|
||||
(void)channels;
|
||||
(void)sampleRate;
|
||||
}
|
||||
|
||||
if (buffer == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32 sampleCount = frameCount * channels;
|
||||
void WaveOutBackend::SetRenderCallback(RenderCallback callback) {
|
||||
std::lock_guard<std::mutex> lock(m_bufferMutex);
|
||||
m_pendingMixBuffer.assign(m_pendingMixBuffer.size(), 0.0f);
|
||||
for (uint32 i = 0; i < sampleCount && i < m_pendingMixBuffer.size(); ++i) {
|
||||
m_pendingMixBuffer[i] = buffer[i];
|
||||
}
|
||||
m_hasPendingMix = true;
|
||||
m_dataReadyCond.notify_one();
|
||||
m_renderCallback = std::move(callback);
|
||||
}
|
||||
|
||||
MMRESULT WaveOutBackend::InitDevice() {
|
||||
@@ -269,9 +263,8 @@ DWORD WINAPI WaveOutBackend::AudioThreadProc(LPVOID lpParameter) {
|
||||
void WaveOutBackend::AudioThread() {
|
||||
while (m_isRunning.load()) {
|
||||
std::unique_lock<std::mutex> lock(m_bufferMutex);
|
||||
m_dataReadyCond.wait(lock, [this] {
|
||||
return !m_isRunning.load() ||
|
||||
(m_hasPendingMix && (m_buffer1Available || m_buffer2Available));
|
||||
m_bufferReadyCond.wait(lock, [this] {
|
||||
return !m_isRunning.load() || m_buffer1Available || m_buffer2Available;
|
||||
});
|
||||
|
||||
if (!m_isRunning.load()) {
|
||||
@@ -293,10 +286,31 @@ void WaveOutBackend::AudioThread() {
|
||||
continue;
|
||||
}
|
||||
|
||||
FillPcm16Buffer(*targetBuffer, m_pendingMixBuffer);
|
||||
m_hasPendingMix = false;
|
||||
RenderCallback renderCallback;
|
||||
const uint32 frameCount = m_config.bufferSize;
|
||||
const uint32 channels = m_config.channels;
|
||||
const uint32 sampleRate = m_config.sampleRate;
|
||||
const size_t sampleCount = static_cast<size_t>(frameCount) * channels;
|
||||
|
||||
if (targetBuffer->size() != sampleCount) {
|
||||
targetBuffer->assign(sampleCount, 0);
|
||||
} else {
|
||||
std::fill(targetBuffer->begin(), targetBuffer->end(), 0);
|
||||
}
|
||||
|
||||
if (m_renderBuffer.size() != sampleCount) {
|
||||
m_renderBuffer.assign(sampleCount, 0.0f);
|
||||
} else {
|
||||
std::fill(m_renderBuffer.begin(), m_renderBuffer.end(), 0.0f);
|
||||
}
|
||||
renderCallback = m_renderCallback;
|
||||
lock.unlock();
|
||||
|
||||
if (renderCallback && !m_renderBuffer.empty()) {
|
||||
renderCallback(m_renderBuffer.data(), frameCount, channels, sampleRate);
|
||||
}
|
||||
FillPcm16Buffer(*targetBuffer, m_renderBuffer);
|
||||
|
||||
if (SubmitBuffer(*targetHeader, *targetBuffer) != MMSYSERR_NOERROR) {
|
||||
std::lock_guard<std::mutex> restoreLock(m_bufferMutex);
|
||||
if (targetHeader == &m_waveHeader1) {
|
||||
@@ -304,6 +318,7 @@ void WaveOutBackend::AudioThread() {
|
||||
} else {
|
||||
m_buffer2Available = true;
|
||||
}
|
||||
m_bufferReadyCond.notify_one();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -322,7 +337,7 @@ void WaveOutBackend::OnAudioCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstan
|
||||
} else if (completedHeader == &m_waveHeader2) {
|
||||
m_buffer2Available = true;
|
||||
}
|
||||
m_dataReadyCond.notify_one();
|
||||
m_bufferReadyCond.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user