1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
// license:BSD-3-Clause
// copyright-holders:O. Galibert
#include "emu.h"
#include "sound_module.h"
void sound_module::abuffer::get(int16_t *data, uint32_t samples)
{
uint32_t pos = 0;
while(pos != samples) {
if(m_buffers.empty()) {
while(pos != samples) {
memcpy(data, m_last_sample.data(), m_channels*2);
data += m_channels;
pos ++;
}
break;
}
auto &buf = m_buffers.front();
if(buf.m_data.empty()) {
m_buffers.erase(m_buffers.begin());
continue;
}
uint32_t avail = buf.m_data.size() / m_channels - buf.m_cpos;
if(avail > samples - pos) {
avail = samples - pos;
memcpy(data, buf.m_data.data() + buf.m_cpos * m_channels, avail * 2 * m_channels);
buf.m_cpos += avail;
break;
}
memcpy(data, buf.m_data.data() + buf.m_cpos * m_channels, avail * 2 * m_channels);
m_buffers.erase(m_buffers.begin());
pos += avail;
data += avail * m_channels;
}
}
void sound_module::abuffer::push(const int16_t *data, uint32_t samples)
{
m_buffers.resize(m_buffers.size() + 1);
auto &buf = m_buffers.back();
buf.m_cpos = 0;
buf.m_data.resize(samples * m_channels);
memcpy(buf.m_data.data(), data, samples * 2 * m_channels);
memcpy(m_last_sample.data(), data + (samples-1) * m_channels, 2 * m_channels);
if(m_buffers.size() > 10)
// If there are way too many buffers, drop some so only 10 are left (roughly 0.2s)
m_buffers.erase(m_buffers.begin(), m_buffers.begin() + m_buffers.size() - 10);
else if(m_buffers.size() >= 5)
// If there are too many buffers, remove five samples per buffer
// to slowly resync to reduce latency (4 seconds to
// compensate one buffer, roughly)
buf.m_cpos = 5;
}
|