mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-03-21 05:33:49 -04:00
examples: improve the ring2 example
Make a function to make a block of samples that we then push into the ringbuffer. This should match more with what audio backends need to handle.
This commit is contained in:
parent
63747e2e40
commit
273a2b65a2
1 changed files with 48 additions and 27 deletions
|
|
@ -29,6 +29,11 @@
|
||||||
|
|
||||||
#define BUFFER_SIZE (16*1024)
|
#define BUFFER_SIZE (16*1024)
|
||||||
|
|
||||||
|
#define MIN_SIZE 256
|
||||||
|
#define MAX_SIZE BUFFER_SIZE
|
||||||
|
|
||||||
|
static float samples[BUFFER_SIZE * DEFAULT_CHANNELS];
|
||||||
|
|
||||||
struct data {
|
struct data {
|
||||||
struct pw_thread_loop *thread_loop;
|
struct pw_thread_loop *thread_loop;
|
||||||
struct pw_loop *loop;
|
struct pw_loop *loop;
|
||||||
|
|
@ -42,7 +47,7 @@ struct data {
|
||||||
float buffer[BUFFER_SIZE * DEFAULT_CHANNELS];
|
float buffer[BUFFER_SIZE * DEFAULT_CHANNELS];
|
||||||
};
|
};
|
||||||
|
|
||||||
static void fill_f32(struct data *d, uint32_t offset, int n_frames)
|
static void fill_f32(struct data *d, float *samples, int n_frames)
|
||||||
{
|
{
|
||||||
float val;
|
float val;
|
||||||
int i, c;
|
int i, c;
|
||||||
|
|
@ -54,40 +59,52 @@ static void fill_f32(struct data *d, uint32_t offset, int n_frames)
|
||||||
|
|
||||||
val = sinf(d->accumulator) * DEFAULT_VOLUME;
|
val = sinf(d->accumulator) * DEFAULT_VOLUME;
|
||||||
for (c = 0; c < DEFAULT_CHANNELS; c++)
|
for (c = 0; c < DEFAULT_CHANNELS; c++)
|
||||||
d->buffer[((offset + i) % BUFFER_SIZE) * DEFAULT_CHANNELS + c] = val;
|
samples[i * DEFAULT_CHANNELS + c] = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this is called from the main-thread as fast as possible. It will block until
|
/* this can be called from any thread with a block of samples to write into
|
||||||
* more data can be written */
|
* the ringbuffer. It will block until all data has been written */
|
||||||
static void push_refill(void *userdata)
|
static void push_samples(void *userdata, float *samples, uint32_t n_samples)
|
||||||
{
|
{
|
||||||
struct data *data = userdata;
|
struct data *data = userdata;
|
||||||
int32_t filled;
|
int32_t filled;
|
||||||
uint32_t index, avail;
|
uint32_t index, avail, stride = sizeof(float) * DEFAULT_CHANNELS;
|
||||||
uint64_t count;
|
uint64_t count;
|
||||||
|
float *s = samples;
|
||||||
|
|
||||||
while (true) {
|
while (n_samples > 0) {
|
||||||
filled = spa_ringbuffer_get_write_index(&data->ring, &index);
|
while (true) {
|
||||||
/* we xrun, this can not happen because we never read more
|
filled = spa_ringbuffer_get_write_index(&data->ring, &index);
|
||||||
* than what there is in the ringbuffer and we never write more than
|
/* we xrun, this can not happen because we never read more
|
||||||
* what is left */
|
* than what there is in the ringbuffer and we never write more than
|
||||||
spa_assert(filled >= 0);
|
* what is left */
|
||||||
spa_assert(filled <= BUFFER_SIZE);
|
spa_assert(filled >= 0);
|
||||||
|
spa_assert(filled <= BUFFER_SIZE);
|
||||||
|
|
||||||
/* this is how much samples we can write */
|
/* this is how much samples we can write */
|
||||||
avail = BUFFER_SIZE - filled;
|
avail = BUFFER_SIZE - filled;
|
||||||
if (avail > 0)
|
if (avail > 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* no space.. block and wait for free space */
|
/* no space.. block and wait for free space */
|
||||||
spa_system_eventfd_read(data->loop->system, data->eventfd, &count);
|
spa_system_eventfd_read(data->loop->system, data->eventfd, &count);
|
||||||
|
}
|
||||||
|
if (avail > n_samples)
|
||||||
|
avail = n_samples;
|
||||||
|
|
||||||
|
spa_ringbuffer_write_data(&data->ring,
|
||||||
|
data->buffer, BUFFER_SIZE * stride,
|
||||||
|
(index % BUFFER_SIZE) * stride,
|
||||||
|
s, avail * stride);
|
||||||
|
|
||||||
|
s += avail * DEFAULT_CHANNELS;
|
||||||
|
n_samples -= avail;
|
||||||
|
|
||||||
|
/* and advance the ringbuffer */
|
||||||
|
spa_ringbuffer_write_update(&data->ring, index + avail);
|
||||||
}
|
}
|
||||||
/* write new samples to the ringbuffer from the given index */
|
|
||||||
fill_f32(data, index, avail);
|
|
||||||
|
|
||||||
/* and advance the ringbuffer */
|
|
||||||
spa_ringbuffer_write_update(&data->ring, index + avail);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* our data processing function is in general:
|
/* our data processing function is in general:
|
||||||
|
|
@ -226,15 +243,19 @@ int main(int argc, char *argv[])
|
||||||
params, 1);
|
params, 1);
|
||||||
|
|
||||||
/* prefill the ringbuffer */
|
/* prefill the ringbuffer */
|
||||||
push_refill(&data);
|
fill_f32(&data, samples, BUFFER_SIZE);
|
||||||
|
push_samples(&data, samples, BUFFER_SIZE);
|
||||||
|
|
||||||
|
srand(time(NULL));
|
||||||
|
|
||||||
pw_thread_loop_start(data.thread_loop);
|
pw_thread_loop_start(data.thread_loop);
|
||||||
pw_thread_loop_unlock(data.thread_loop);
|
pw_thread_loop_unlock(data.thread_loop);
|
||||||
|
|
||||||
while (data.running) {
|
while (data.running) {
|
||||||
/* just keep on pushing data as fast as we can, this can be done
|
uint32_t size = rand() % ((MAX_SIZE - MIN_SIZE + 1) + MIN_SIZE);
|
||||||
* from any thread. */
|
/* make new random sized block of samples and push */
|
||||||
push_refill(&data);
|
fill_f32(&data, samples, size);
|
||||||
|
push_samples(&data, samples, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
pw_thread_loop_lock(data.thread_loop);
|
pw_thread_loop_lock(data.thread_loop);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue