experimenting with pipewire api
This commit is contained in:
parent
5ff2e93195
commit
04e5688d82
1 changed files with 72 additions and 24 deletions
96
lib/main.c
96
lib/main.c
|
|
@ -1,15 +1,16 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <spa/param/audio/format-utils.h>
|
#include <spa/param/audio/format-utils.h>
|
||||||
|
|
||||||
#include <pipewire/pipewire.h>
|
#include <pipewire/pipewire.h>
|
||||||
|
|
||||||
#define M_PI_M2 (M_PI + M_PI)
|
#define M_PI_M2 (M_PI + M_PI)
|
||||||
|
|
||||||
#define DEFAULT_RATE 44100
|
#define DEFAULT_RATE 44100
|
||||||
|
#define DEFAULT_PERIOD 1.0 / DEFAULT_RATE
|
||||||
|
|
||||||
#define DEFAULT_CHANNELS 2
|
#define DEFAULT_CHANNELS 2
|
||||||
#define DEFAULT_VOLUME 0.7
|
#define DEFAULT_VOLUME 0.7
|
||||||
#define DEFAULT_FREQ 200
|
#define DEFAULT_FREQ 500
|
||||||
|
|
||||||
#define DEFAULT_ACCUMULATOR -1
|
#define DEFAULT_ACCUMULATOR -1
|
||||||
|
|
||||||
|
|
@ -18,17 +19,72 @@
|
||||||
struct data {
|
struct data {
|
||||||
struct pw_main_loop *loop;
|
struct pw_main_loop *loop;
|
||||||
struct pw_stream *stream;
|
struct pw_stream *stream;
|
||||||
double accumulator;
|
|
||||||
uint32_t cycle;
|
/*
|
||||||
|
*/
|
||||||
|
double t, tcyc; // global time and cycle time
|
||||||
|
uint32_t frame, cycle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define NEW_DATA (struct data) \
|
||||||
|
{ \
|
||||||
|
.t = 0, \
|
||||||
|
.tcyc = 0, \
|
||||||
|
.frame = 0, \
|
||||||
|
.cycle = 0, \
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int16_t (*snd)(struct data*);
|
||||||
|
|
||||||
|
inline void data_progress(struct data *state) {
|
||||||
|
state->t += DEFAULT_PERIOD / DEFAULT_FREQ;
|
||||||
|
state->tcyc += DEFAULT_PERIOD / DEFAULT_FREQ;
|
||||||
|
if (++state->frame == DEFAULT_FREQ) {
|
||||||
|
state->tcyc -= DEFAULT_PERIOD;
|
||||||
|
state->frame = 0;
|
||||||
|
state->cycle++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t snd_sine(struct data *state) {
|
||||||
|
int16_t val;
|
||||||
|
|
||||||
|
/* sin() gives a value between -1.0 and 1.0, we first apply
|
||||||
|
* the volume and then scale with 32767.0 to get a 16 bits value
|
||||||
|
* between [-32767 32767].
|
||||||
|
* Another common method to convert a double to
|
||||||
|
* 16 bits is to multiple by 32768.0 and then clamp to
|
||||||
|
* [-32768 32767] to get the full 16 bits range. */
|
||||||
|
val = sin(state->tcyc * M_PI_M2 * DEFAULT_FREQ) * 32767.0 * DEFAULT_VOLUME;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
int graph_snd(snd f, struct data *state, double t_max, FILE *fstream) {
|
||||||
|
int16_t val;
|
||||||
|
if (fstream == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
fputs("x, sin(x)\n", fstream);
|
||||||
|
while (state->t < t_max) {
|
||||||
|
val = f(state);
|
||||||
|
fprintf(fstream, "%f, %d\n", state->t, val);
|
||||||
|
data_progress(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fstream);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* [on_process] */
|
/* [on_process] */
|
||||||
static void on_process(void *userdata) {
|
static void on_process(void *userdata) {
|
||||||
struct data *data = userdata;
|
struct data *data = userdata;
|
||||||
struct pw_buffer *b;
|
struct pw_buffer *b;
|
||||||
struct spa_buffer *buf;
|
struct spa_buffer *buf;
|
||||||
int i, c, n_frames, stride;
|
int n_frames, stride;
|
||||||
int16_t *dst, val;
|
int16_t *dst, val;
|
||||||
|
int i, c;
|
||||||
|
|
||||||
if ((b = pw_stream_dequeue_buffer(data->stream)) == NULL) {
|
if ((b = pw_stream_dequeue_buffer(data->stream)) == NULL) {
|
||||||
pw_log_warn("out of buffers: %m");
|
pw_log_warn("out of buffers: %m");
|
||||||
|
|
@ -45,19 +101,7 @@ static void on_process(void *userdata) {
|
||||||
n_frames = SPA_MIN(b->requested, n_frames);
|
n_frames = SPA_MIN(b->requested, n_frames);
|
||||||
|
|
||||||
for (i = 0; i < n_frames; i++) {
|
for (i = 0; i < n_frames; i++) {
|
||||||
// data->accumulator += M_PI_M2 * DEFAULT_FREQ / DEFAULT_RATE; // * 440
|
val = snd_sine(data);
|
||||||
if (data->accumulator++ == DEFAULT_RATE) {
|
|
||||||
data->accumulator = DEFAULT_ACCUMULATOR;
|
|
||||||
data->cycle++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* sin() gives a value between -1.0 and 1.0, we first apply
|
|
||||||
* the volume and then scale with 32767.0 to get a 16 bits value
|
|
||||||
* between [-32767 32767].
|
|
||||||
* Another common method to convert a double to
|
|
||||||
* 16 bits is to multiple by 32768.0 and then clamp to
|
|
||||||
* [-32768 32767] to get the full 16 bits range. */
|
|
||||||
val = sin(data->accumulator * M_PI_M2 * DEFAULT_FREQ / DEFAULT_RATE) * DEFAULT_VOLUME * 32767.0;
|
|
||||||
for (c = 0; c < DEFAULT_CHANNELS; c++)
|
for (c = 0; c < DEFAULT_CHANNELS; c++)
|
||||||
*dst++ = val;
|
*dst++ = val;
|
||||||
}
|
}
|
||||||
|
|
@ -75,16 +119,20 @@ static const struct pw_stream_events stream_events = {
|
||||||
.process = on_process,
|
.process = on_process,
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char **argv) {
|
||||||
struct data data = {
|
struct data data = NEW_DATA;
|
||||||
.accumulator = DEFAULT_ACCUMULATOR,
|
|
||||||
.cycle = 0,
|
|
||||||
};
|
|
||||||
const struct spa_pod *params[1];
|
const struct spa_pod *params[1];
|
||||||
uint8_t buffer[1024];
|
uint8_t buffer[1024];
|
||||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
||||||
|
|
||||||
pw_init(&argc, &argv);
|
// DEBUG: check sine wave is actually a sine wave
|
||||||
|
FILE *fstream = fopen("sine.txt", "w");
|
||||||
|
graph_snd(&snd_sine, &NEW_DATA, DEFAULT_PERIOD, fstream);
|
||||||
|
exit(69);
|
||||||
|
|
||||||
|
int pw_argc = 0;
|
||||||
|
char **pw_argv = NULL;
|
||||||
|
pw_init(&pw_argc, &pw_argv); // pw_init(&argc, &argv);
|
||||||
|
|
||||||
data.loop = pw_main_loop_new(NULL);
|
data.loop = pw_main_loop_new(NULL);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue