/* gcc audiotest.c -o audiotest $(pkg-config libpulse --libs --cflags) */
#include <pulse/pulseaudio.h>
#include <string.h>
float buf[48000]; // Large enough on my system
static void stream_write_callback(pa_stream *s, size_t length, void *userdata) {
pa_stream_write(s, buf, length, NULL, 0, PA_SEEK_RELATIVE);
}
static void stream_read_callback(pa_stream *s, size_t length, void *userdata) {
void const* ptr;
size_t size;
pa_stream_peek(s, &ptr, &size);
memset(buf, 0, sizeof(buf));
memcpy(buf, ptr, size);
pa_stream_drop(s);
}
static void context_state_callback(pa_context* ctx, void* userdata) {
if (pa_context_get_state(ctx) == PA_CONTEXT_READY) {
pa_sample_spec ss = { PA_SAMPLE_FLOAT32LE, 48000, 1 };
pa_buffer_attr ba = { -1, 0, -1, -1, 0 }; // Minimum delay?
pa_stream* stream;
stream = pa_stream_new(ctx, "Recording", &ss, NULL);
pa_stream_set_read_callback(stream, stream_read_callback, NULL);
pa_stream_connect_record(stream, NULL, &ba, PA_STREAM_ADJUST_LATENCY);
stream = pa_stream_new(ctx, "Playback", &ss, NULL);
pa_stream_set_write_callback(stream, stream_write_callback, NULL);
pa_stream_connect_playback(stream, NULL, &ba, PA_STREAM_ADJUST_LATENCY, NULL, NULL);
}
}
int main() {
pa_mainloop* ml = pa_mainloop_new();
pa_mainloop_api* mlapi = pa_mainloop_get_api(ml);
pa_context* ctx = pa_context_new(mlapi, "Audio loopback test");
pa_context_set_state_callback(ctx, context_state_callback, NULL);
pa_context_connect(ctx, NULL, (pa_context_flags_t)0, NULL);
pa_mainloop_run(ml, NULL);
}