/** * @file alsa.c ALSA sound driver * * Copyright (C) 2010 Creytiv.com */ #define _POSIX_SOURCE 1 #include #include #include #include #include #include #include #include #include "alsa.h" /** * @defgroup alsa alsa * * Advanced Linux Sound Architecture (ALSA) audio driver module * * * References: * * http://www.alsa-project.org/main/index.php/Main_Page */ char alsa_dev[64] = "default"; static struct ausrc *ausrc; static struct auplay *auplay; int alsa_reset(snd_pcm_t *pcm, uint32_t srate, uint32_t ch, uint32_t num_frames) { snd_pcm_hw_params_t *hw_params = NULL; const snd_pcm_format_t pcmfmt = SND_PCM_FORMAT_S16; snd_pcm_uframes_t period = num_frames, bufsize = num_frames * 4; int err; err = snd_pcm_hw_params_malloc(&hw_params); if (err < 0) { warning("alsa: cannot allocate hw params (%s)\n", snd_strerror(err)); goto out; } err = snd_pcm_hw_params_any(pcm, hw_params); if (err < 0) { warning("alsa: cannot initialize hw params (%s)\n", snd_strerror(err)); goto out; } err = snd_pcm_hw_params_set_access(pcm, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { warning("alsa: cannot set access type (%s)\n", snd_strerror(err)); goto out; } err = snd_pcm_hw_params_set_format(pcm, hw_params, pcmfmt); if (err < 0) { warning("alsa: cannot set sample format %d (%s)\n", pcmfmt, snd_strerror(err)); goto out; } err = snd_pcm_hw_params_set_rate(pcm, hw_params, srate, 0); if (err < 0) { warning("alsa: cannot set sample rate to %u Hz (%s)\n", srate, snd_strerror(err)); goto out; } err = snd_pcm_hw_params_set_channels(pcm, hw_params, ch); if (err < 0) { warning("alsa: cannot set channel count to %d (%s)\n", ch, snd_strerror(err)); goto out; } err = snd_pcm_hw_params_set_period_size_near(pcm, hw_params, &period, 0); if (err < 0) { warning("alsa: cannot set period size to %d (%s)\n", period, snd_strerror(err)); } err = snd_pcm_hw_params_set_buffer_size_near(pcm, hw_params, &bufsize); if (err < 0) { warning("alsa: cannot set buffer size to %d (%s)\n", bufsize, snd_strerror(err)); } err = snd_pcm_hw_params(pcm, hw_params); if (err < 0) { warning("alsa: cannot set parameters (%s)\n", snd_strerror(err)); goto out; } err = snd_pcm_prepare(pcm); if (err < 0) { warning("alsa: cannot prepare audio interface for use (%s)\n", snd_strerror(err)); goto out; } err = 0; out: snd_pcm_hw_params_free(hw_params); if (err) { warning("alsa: init failed: err=%d\n", err); } return err; } static int alsa_init(void) { int err; err = ausrc_register(&ausrc, "alsa", alsa_src_alloc); err |= auplay_register(&auplay, "alsa", alsa_play_alloc); return err; } static int alsa_close(void) { ausrc = mem_deref(ausrc); auplay = mem_deref(auplay); return 0; } const struct mod_export DECL_EXPORTS(alsa) = { "alsa", "sound", alsa_init, alsa_close };