diff options
Diffstat (limited to 'modules/alsa/alsa_src.c')
-rw-r--r-- | modules/alsa/alsa_src.c | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/modules/alsa/alsa_src.c b/modules/alsa/alsa_src.c index 0f611ea..6688f9d 100644 --- a/modules/alsa/alsa_src.c +++ b/modules/alsa/alsa_src.c @@ -22,11 +22,13 @@ struct ausrc_st { bool run; snd_pcm_t *read; int16_t *sampv; + void *xsampv; size_t sampc; ausrc_read_h *rh; void *arg; struct ausrc_prm prm; char *device; + enum aufmt aufmt; }; @@ -45,6 +47,7 @@ static void ausrc_destructor(void *arg) snd_pcm_close(st->read); mem_deref(st->sampv); + mem_deref(st->xsampv); mem_deref(st->device); } @@ -66,7 +69,15 @@ static void *read_thread(void *arg) } while (st->run) { - err = snd_pcm_readi(st->read, st->sampv, num_frames); + size_t sampc; + void *sampv; + + if (st->aufmt == AUFMT_S16LE) + sampv = st->sampv; + else + sampv = st->xsampv; + + err = snd_pcm_readi(st->read, sampv, num_frames); if (err == -EPIPE) { snd_pcm_prepare(st->read); continue; @@ -75,7 +86,14 @@ static void *read_thread(void *arg) continue; } - st->rh(st->sampv, err * st->prm.ch, st->arg); + sampc = err * st->prm.ch; + + if (st->aufmt != AUFMT_S16LE) { + auconv_to_s16(st->sampv, st->aufmt, + st->xsampv, sampc); + } + + st->rh(st->sampv, sampc, st->arg); } out: @@ -89,6 +107,7 @@ int alsa_src_alloc(struct ausrc_st **stp, const struct ausrc *as, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; + snd_pcm_format_t pcmfmt; int num_frames; int err; (void)ctx; @@ -112,6 +131,7 @@ int alsa_src_alloc(struct ausrc_st **stp, const struct ausrc *as, st->as = as; st->rh = rh; 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; @@ -122,6 +142,15 @@ int alsa_src_alloc(struct ausrc_st **stp, const struct ausrc *as, 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->read, st->device, SND_PCM_STREAM_CAPTURE, 0); if (err < 0) { warning("alsa: could not open ausrc device '%s' (%s)\n", @@ -129,7 +158,16 @@ int alsa_src_alloc(struct ausrc_st **stp, const struct ausrc *as, goto out; } - err = alsa_reset(st->read, 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->read, st->prm.srate, st->prm.ch, num_frames, + pcmfmt); if (err) { warning("alsa: could not reset source '%s' (%s)\n", st->device, snd_strerror(err)); |