Fixed bug in circular buffer management inside linux output stream driver, added unit test for circular buffer mode.

TG-220
md1702
Niccolò Izzo 2022-07-23 17:27:32 +02:00 zatwierdzone przez Silvano Seva
rodzic 58c1c3bbd6
commit adbd1f070d
2 zmienionych plików z 78 dodań i 18 usunięć

Wyświetl plik

@ -47,27 +47,38 @@ static enum BufMode buf_mode; // Buffer operation mode
static stream_sample_t *buf = NULL; // Playback buffer
static size_t buf_len = 0; // Buffer length
static bool first_half_active = true; // Circular addressing mode flag
static size_t offset = 0; // Playback offset
static void buf_circ_write_cb(pa_stream *s, size_t length, void *userdata)
{
(void) userdata;
// TODO: We can play length more bytes of data
// Start playback of the other half
stream_sample_t *active_buf = (first_half_active) ?
buf : buf + buf_len / 2;
first_half_active = !first_half_active;
size_t active_buf_len = buf_len / 2;
size_t remaining = 0;
if (!s || length <= 0)
return;
if (pa_stream_begin_write(s, (void **) &active_buf, &active_buf_len) < 0)
{
fprintf(stderr, "pa_stream_begin_write() failed: %s", pa_strerror(pa_context_errno(p->context)));
return;
}
if (offset >= buf_len / 2)
first_half_active = false;
pa_stream_write(s, active_buf, active_buf_len, NULL, 0, PA_SEEK_RELATIVE);
remaining = buf_len - offset;
// We can play all the rest of the buffer
if (length > remaining)
{
pa_stream_write(s, buf + offset, remaining, NULL, 0, PA_SEEK_RELATIVE);
if(first_half_active == true)
first_half_active = false;
else
first_half_active = true;
offset = 0;
}
else
{
pa_stream_write(s, buf + offset, length, NULL, 0, PA_SEEK_RELATIVE);
offset += length;
}
}
streamId outputStream_start(const enum AudioSink destination,
@ -124,6 +135,12 @@ streamId outputStream_start(const enum AudioSink destination,
{
assert(p->stream && "Invalid PulseAudio Stream!");
if (pa_simple_write(p, buf, length / 2, &error) < 0) {
fprintf(stderr, __FILE__": pa_simple_write() failed: %s\n", pa_strerror(error));
return -1;
}
offset = length / 2;
// Register write callback
pa_stream_set_write_callback(p->stream, buf_circ_write_cb, NULL);
}
@ -155,7 +172,10 @@ bool outputStream_sync(const streamId id, const bool bufChanged)
return false;
}
running = false;
if (buf_mode == BUF_LINEAR)
{
running = false;
}
return true;
}

Wyświetl plik

@ -24,6 +24,7 @@
#include <interfaces/audio_stream.h>
#include <math.h>
#include <stdio.h>
#define BUF_LEN 4096 * 10
#define AMPLITUDE 20000
@ -37,16 +38,21 @@
int16_t buffer[BUF_LEN] = { 0 };
int main()
void fill_buffer_sine(int16_t *buffer, size_t len)
{
int id = 0;
// Create 440 Hz sine wave
for(int i = 0; i < BUF_LEN; i++)
for(size_t i = 0; i < len; i++)
{
buffer[i] = AMPLITUDE * sin(2 * PI * i *
((float) FREQUENCY / SAMPLE_RATE));
}
}
void play_sine_linear()
{
int id = 0;
// Create 440 Hz sine wave
fill_buffer_sine(buffer, BUF_LEN);
// Play back sine wave
for(int i = 0; i < 10; i++)
@ -64,3 +70,37 @@ int main()
outputStream_stop(id);
outputStream_terminate(id);
}
void play_sine_circular()
{
int id = 0;
stream_sample_t *buf = NULL;
// Fill first half of buffer with sine
fill_buffer_sine(buffer, BUF_LEN / 2);
// Play back sine wave
id = outputStream_start(SINK_SPK,
PRIO_PROMPT,
buffer,
BUF_LEN,
BUF_CIRC_DOUBLE,
SAMPLE_RATE);
for(int i = 0; i < 10; i++)
{
buf = outputStream_getIdleBuffer(id);
fill_buffer_sine(buf, BUF_LEN / 2);
outputStream_sync(id, true);
}
// Sync, flush, terminate
outputStream_stop(id);
outputStream_terminate(id);
}
int main()
{
//play_sine_linear();
play_sine_circular();
}