summaryrefslogtreecommitdiff
path: root/modules/alsa/alsa_play.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/alsa/alsa_play.c')
-rw-r--r--modules/alsa/alsa_play.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/modules/alsa/alsa_play.c b/modules/alsa/alsa_play.c
index b21ce3d..327acf4 100644
--- a/modules/alsa/alsa_play.c
+++ b/modules/alsa/alsa_play.c
@@ -22,11 +22,13 @@ struct auplay_st {
bool run;
snd_pcm_t *write;
int16_t *sampv;
+ void *xsampv;
size_t sampc;
auplay_write_h *wh;
void *arg;
struct auplay_prm prm;
char *device;
+ enum aufmt aufmt;
};
@@ -45,6 +47,7 @@ static void auplay_destructor(void *arg)
snd_pcm_close(st->write);
mem_deref(st->sampv);
+ mem_deref(st->xsampv);
mem_deref(st->device);
}
@@ -59,14 +62,25 @@ static void *write_thread(void *arg)
while (st->run) {
const int samples = num_frames;
+ void *sampv;
st->wh(st->sampv, st->sampc, st->arg);
- n = snd_pcm_writei(st->write, st->sampv, samples);
+ if (st->aufmt == AUFMT_S16LE) {
+ sampv = st->sampv;
+ }
+ else {
+ sampv = st->xsampv;
+ auconv_from_s16(st->aufmt, st->xsampv,
+ st->sampv, st->sampc);
+ }
+
+ n = snd_pcm_writei(st->write, sampv, samples);
+
if (-EPIPE == n) {
snd_pcm_prepare(st->write);
- n = snd_pcm_writei(st->write, st->sampv, samples);
+ n = snd_pcm_writei(st->write, st->xsampv, samples);
if (n != samples) {
warning("alsa: write error: %s\n",
snd_strerror(n));
@@ -90,6 +104,7 @@ int alsa_play_alloc(struct auplay_st **stp, const struct auplay *ap,
auplay_write_h *wh, void *arg)
{
struct auplay_st *st;
+ snd_pcm_format_t pcmfmt;
int num_frames;
int err;
@@ -111,6 +126,7 @@ int alsa_play_alloc(struct auplay_st **stp, const struct auplay *ap,
st->ap = ap;
st->wh = wh;
st->arg = arg;
+ st->aufmt = alsa_sample_format;
st->sampc = prm->srate * prm->ch * prm->ptime / 1000;
num_frames = st->prm.srate * st->prm.ptime / 1000;
@@ -121,6 +137,15 @@ int alsa_play_alloc(struct auplay_st **stp, const struct auplay *ap,
goto out;
}
+ if (st->aufmt != AUFMT_S16LE) {
+ size_t sz = aufmt_sample_size(st->aufmt) * st->sampc;
+ st->xsampv = mem_alloc(sz, NULL);
+ if (!st->xsampv) {
+ err = ENOMEM;
+ goto out;
+ }
+ }
+
err = snd_pcm_open(&st->write, st->device, SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0) {
warning("alsa: could not open auplay device '%s' (%s)\n",
@@ -128,7 +153,16 @@ int alsa_play_alloc(struct auplay_st **stp, const struct auplay *ap,
goto out;
}
- err = alsa_reset(st->write, st->prm.srate, st->prm.ch, num_frames);
+ pcmfmt = aufmt_to_alsaformat(st->aufmt);
+ if (pcmfmt == SND_PCM_FORMAT_UNKNOWN) {
+ warning("alsa: unknown sample format '%s'\n",
+ aufmt_name(st->aufmt));
+ err = EINVAL;
+ goto out;
+ }
+
+ err = alsa_reset(st->write, st->prm.srate, st->prm.ch, num_frames,
+ pcmfmt);
if (err) {
warning("alsa: could not reset player '%s' (%s)\n",
st->device, snd_strerror(err));