6#include <alsa/asoundlib.h>
9 if (dst->
cap <= 0)
return CLOD_STREAM_INVALID;
10 if (dst->
len >= dst->
cap)
return CLOD_STREAM_INVALID;
13 int64_t n = snd_pcm_readi((
void*)self->
impl, dst->
ptr + dst->
len, (
size_t)(dst->
cap - dst->
len) /
sizeof(
float));
14 if (n < 0 && n != -EAGAIN) {
15 debug(CLOD_DEBUG,
"Audio read error: %s", snd_strerror((
int)n));
16 n = snd_pcm_recover((
void*)self->
impl, (
int)n, 0);
24 dst->
len += n * (ptrdiff_t)
sizeof(
float);
25 return CLOD_STREAM_OK;
28 if (src->
len < 0)
return CLOD_STREAM_INVALID;
31 int64_t n = snd_pcm_writei((
void*)self->
impl, src->
ptr, (
size_t)(src->
len) /
sizeof(
float));
32 if (n < 0 && n != -EAGAIN) {
33 debug(CLOD_DEBUG,
"Audio write error: %s", snd_strerror((
int)n));
34 n = snd_pcm_recover((
void*)self->
impl, (
int)n, 0);
42 src->
ptr += n * (ptrdiff_t)
sizeof(
float);
43 src->
len -= n * (ptrdiff_t)
sizeof(
float);
44 return CLOD_STREAM_OK;
47 int res = CLOD_STREAM_OK;
49 if ((snd_pcm_t*)(
void*)self->
impl) {
50 snd_pcm_drain((
void*)self->
impl);
51 res = snd_pcm_close((
void*)self->
impl);
52 if (res != 0) debug(CLOD_DEBUG,
"Audio stream close error: %s", snd_strerror(res));
55 return CLOD_STREAM_OK;
58 if (flags & CLOD_AUDIO_IN && flags & CLOD_AUDIO_OUT) {
59 debug(CLOD_DEBUG,
"A single audio stream cannot be both input and output.");
60 return CLOD_STREAM_INVALID;
64 #define check_error(expr) if((res = (expr)) < 0) {\
65 debug(CLOD_DEBUG, "Failed to initialise audio. "#expr" returned %i: %s.", res, snd_strerror(res));\
70 check_error(snd_pcm_open(
73 flags & CLOD_AUDIO_IN ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
77 snd_pcm_hw_params_t *hw_params;
78 snd_pcm_hw_params_alloca(&hw_params);
79 check_error(snd_pcm_hw_params_any(pcm, hw_params));
80 check_error(snd_pcm_hw_params_set_access(pcm, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED));
81 check_error(snd_pcm_hw_params_set_format(pcm, hw_params, SND_PCM_FORMAT_FLOAT));
82 check_error(snd_pcm_hw_params_set_channels(pcm, hw_params, 1));
83 check_error(snd_pcm_hw_params_set_rate(pcm, hw_params, 48000, 0));
85 check_error(snd_pcm_hw_params(pcm, hw_params));
86 check_error(snd_pcm_prepare(pcm));
88 if (flags & CLOD_AUDIO_IN) {
89 stream_out->
impl = (uintptr_t)(
void*)pcm;
90 stream_out->
read = clod_audio_read;
91 stream_out->
write =
nullptr;
92 stream_out->
close = clod_audio_close;
94 stream_out->
impl = (uintptr_t)(
void*)pcm;
95 stream_out->
read =
nullptr;
96 stream_out->
write = clod_audio_write;
97 stream_out->
close = clod_audio_close;
103 if (pcm) snd_pcm_close(pcm);
108 return CLOD_STREAM_INVALID;
int(* write)(clod_stream *self, struct clod_string *src)
int(* read)(clod_stream *self, struct clod_string *dst)
int(* close)(clod_stream *self)