Try to fix resampler to be thread-safe.

This commit is contained in:
BearOso 2023-06-27 15:33:52 -05:00
parent 376e6de81c
commit c13e4d8330
2 changed files with 31 additions and 27 deletions

View File

@ -9,19 +9,15 @@
#include <cstring>
#include <cassert>
#if __cplusplus >= 201103L
#include <cstdint>
#else
#include <stdint.h>
#endif
#include <cmath>
class Resampler
{
public:
int size;
volatile int end;
int buffer_size;
int start;
volatile int start;
int16_t *buffer;
float r_step;
@ -87,7 +83,7 @@ class Resampler
return;
start = 0;
size = 0;
end = 0;
memset(buffer, 0, buffer_size * 2);
r_frac = 0.0;
@ -100,13 +96,14 @@ class Resampler
if (space_filled() < num_samples)
return false;
memcpy(dst, buffer + start, min(num_samples, buffer_size - start) * 2);
int first_block_size = buffer_size - start;
if (num_samples > (buffer_size - start))
memcpy(dst + (buffer_size - start), buffer, (num_samples - (buffer_size - start)) * 2);
memcpy(dst, buffer + start, min(num_samples, first_block_size) * 2);
if (num_samples > first_block_size)
memcpy(dst + first_block_size, buffer, (num_samples - first_block_size) * 2);
start = (start + num_samples) % buffer_size;
size -= num_samples;
return true;
}
@ -115,12 +112,9 @@ class Resampler
{
if (space_empty() >= 2)
{
int end = start + size;
if (end >= buffer_size)
end -= buffer_size;
buffer[end] = l;
buffer[end + 1] = r;
size += 2;
end = (end + 2) % buffer_size;
}
}
@ -129,17 +123,14 @@ class Resampler
if (space_empty() < num_samples)
return false;
int end = start + size;
if (end > buffer_size)
end -= buffer_size;
int first_write_size = min(num_samples, buffer_size - end);
int first_block_size = min(num_samples, buffer_size - end);
memcpy(buffer + end, src, first_write_size * 2);
memcpy(buffer + end, src, first_block_size * 2);
if (num_samples > first_write_size)
memcpy(buffer, src + first_write_size, (num_samples - first_write_size) * 2);
if (num_samples > first_block_size)
memcpy(buffer, src + first_block_size, (num_samples - first_block_size) * 2);
size += num_samples;
end = (end + num_samples) % buffer_size;
return true;
}
@ -156,7 +147,7 @@ class Resampler
assert((num_samples & 1) == 0); // resampler always processes both stereo samples
int o_position = 0;
while (o_position < num_samples && size > 0)
while (o_position < num_samples && space_filled() >= 2)
{
int s_left = buffer[start];
int s_right = buffer[start + 1];
@ -191,23 +182,26 @@ class Resampler
start += 2;
if (start >= buffer_size)
start -= buffer_size;
size -= 2;
}
}
}
inline int space_empty(void) const
{
return buffer_size - size;
return buffer_size - 2 - space_filled();
}
inline int space_filled(void) const
{
int size = end - start;
if (size < 0)
size += buffer_size;
return size;
}
inline int avail(void)
{
int size = space_filled();
//If we are outputting the exact same ratio as the input, find out directly from the input buffer
if (r_step == 1.0)
return size;

View File

@ -71,7 +71,17 @@ long data_callback(cubeb_stream *stream, void *user_ptr,
long S9xCubebSoundDriver::data_callback(cubeb_stream *stream, void const *input_buffer, void *output_buffer, long nframes)
{
buffer.read((int16_t *)output_buffer, nframes * 2);
auto avail = buffer.avail();
if (avail < nframes * 2)
{
auto zeroed_samples = nframes * 2 - avail;
memset(output_buffer, 0, zeroed_samples);
buffer.read((int16_t *)output_buffer + zeroed_samples, nframes * 2 - zeroed_samples);
}
else
{
buffer.read((int16_t *)output_buffer, nframes * 2);
}
return nframes;
}