summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2026-03-12 12:40:59 +0100
committer hap <happppp@users.noreply.github.com>2026-03-12 12:41:08 +0100
commit70d4b9bc5d488bf71e571c14eec46615319e2c2c (patch)
treed3f326cb677a79bd04c0e1696953b9060a97a9a7 /src/osd
parentba6db4a6c2f8d5f31598bb3d482daac0b6b9f7cc (diff)
sound abuffer: derive min_buffers from max_buffers, add over/underrun stats
Diffstat (limited to 'src/osd')
-rw-r--r--src/osd/modules/sound/sound_module.cpp28
-rw-r--r--src/osd/modules/sound/sound_module.h5
2 files changed, 21 insertions, 12 deletions
diff --git a/src/osd/modules/sound/sound_module.cpp b/src/osd/modules/sound/sound_module.cpp
index 801edb74df1..20220cf2c77 100644
--- a/src/osd/modules/sound/sound_module.cpp
+++ b/src/osd/modules/sound/sound_module.cpp
@@ -40,6 +40,8 @@ void sound_module::abuffer::clear()
m_delta = 0;
m_delta2 = 0;
+ m_underruns = 0;
+ m_overruns = 0;
}
void sound_module::abuffer::get(int16_t *data, uint32_t samples) noexcept
@@ -50,6 +52,7 @@ void sound_module::abuffer::get(int16_t *data, uint32_t samples) noexcept
while(pos != samples) {
if(!m_used_buffers) {
m_delta2 += samples - pos;
+ m_underruns++;
while(pos != samples) {
std::copy_n(m_last_sample.data(), m_channels, data);
data += m_channels;
@@ -77,7 +80,7 @@ void sound_module::abuffer::get(int16_t *data, uint32_t samples) noexcept
pos += avail;
data += avail * m_channels;
}
- //printf("# %d %d %d\n", m_used_buffers, m_delta, m_delta2);
+ //printf("%d -%d +%d # %d %d\n", m_used_buffers, m_underruns, m_overruns, m_delta, m_delta2);
}
void sound_module::abuffer::push(const int16_t *data, uint32_t samples)
@@ -90,6 +93,13 @@ void sound_module::abuffer::push(const int16_t *data, uint32_t samples)
std::copy_n(data, samples * m_channels, buf.m_data.data());
std::copy_n(data + ((samples - 1) * m_channels), m_channels, m_last_sample.data());
+ // maximum number of buffers relative to samples
+ const uint32_t max_buffers = std::max(m_max_buffers * 48000 / samples / 50, 4U);
+
+ // minimum number of buffers after overrun
+ // (lower limit of 2 prevents buffer underruns with push(this), get, get, push)
+ const uint32_t min_buffers = std::max(max_buffers / 4, 2U);
+
m_history[m_hindex] = m_used_buffers_prev - m_used_buffers;
m_hindex = (m_hindex + 1) % m_history.size();
@@ -104,25 +114,21 @@ void sound_module::abuffer::push(const int16_t *data, uint32_t samples)
};
if(m_overrun && std::accumulate(m_history.begin(), m_history.end(), 0) >= -2) {
- if(m_used_buffers > 2) {
- // Once it's stabilized after an overrun, reduce buffers to 2
- flush_buffers(2);
+ if(m_used_buffers > min_buffers) {
+ // Once it's stabilized after an overrun, reduce buffers to minimum latency
+ flush_buffers(min_buffers);
std::fill(m_history.begin(), m_history.end(), 0);
}
m_overrun = false;
- }
-
- // maximum amount of buffers relative to samples
- const uint32_t max_buffers = std::max(m_max_buffers * 48000 / samples / 50, 4U);
-
- if(m_used_buffers > max_buffers) {
+ } else if(m_used_buffers > max_buffers) {
// If there are too many buffers, drop some and mark this event as an overrun
flush_buffers(max_buffers);
m_overrun = true;
+ m_overruns++;
}
m_used_buffers_prev = m_used_buffers;
- //printf("# %d %d %d\n", m_used_buffers, m_delta, m_delta2);
+ //printf("%d -%d +%d # %d %d\n", m_used_buffers, m_underruns, m_overruns, m_delta, m_delta2);
}
uint32_t sound_module::abuffer::available() const noexcept
diff --git a/src/osd/modules/sound/sound_module.h b/src/osd/modules/sound/sound_module.h
index 5c90433ce55..8d1697931dc 100644
--- a/src/osd/modules/sound/sound_module.h
+++ b/src/osd/modules/sound/sound_module.h
@@ -64,7 +64,6 @@ protected:
void pop_buffer() noexcept;
buffer &push_buffer();
- int32_t m_delta, m_delta2;
uint32_t m_channels;
uint32_t m_used_buffers;
uint32_t m_used_buffers_prev;
@@ -74,6 +73,10 @@ protected:
bool m_overrun;
std::vector<int16_t> m_last_sample;
std::vector<buffer> m_buffers;
+
+ // statistics
+ int32_t m_delta, m_delta2;
+ uint32_t m_underruns, m_overruns;
};
};