summaryrefslogtreecommitdiff
path: root/dxr3audio-alsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'dxr3audio-alsa.c')
-rw-r--r--dxr3audio-alsa.c58
1 files changed, 55 insertions, 3 deletions
diff --git a/dxr3audio-alsa.c b/dxr3audio-alsa.c
index 0e45afb..a33359d 100644
--- a/dxr3audio-alsa.c
+++ b/dxr3audio-alsa.c
@@ -39,7 +39,7 @@ void cAudioAlsa::openDevice()
string device = "default:CARD=" + cardname;
dsyslog("[dxr3-audio-alsa] opening device %s", device.c_str());
- int err = snd_pcm_open(&handle, device.c_str(), SND_PCM_STREAM_PLAYBACK, 0);
+ int err = snd_pcm_open(&handle, device.c_str(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if (err < 0) {
esyslog("[dxr3-audio-alsa] Playback open error: %s", snd_strerror(err));
@@ -74,7 +74,13 @@ void cAudioAlsa::setup(const SampleContext& ctx)
dsyslog("[dxr3-audio-alsa] changing num of channels to %d (old %d)", ctx.channels, curContext.channels);
snd_pcm_hw_params_t* alsa_hwparams;
+ snd_pcm_sw_params_t* alsa_swparams;
+
snd_pcm_hw_params_alloca(&alsa_hwparams);
+ snd_pcm_sw_params_alloca(&alsa_swparams);
+
+ //
+ // set hardware settings
int err = snd_pcm_hw_params_any(handle, alsa_hwparams);
if (err < 0) {
@@ -100,8 +106,10 @@ void cAudioAlsa::setup(const SampleContext& ctx)
esyslog("[dxr3-audio-alsa] Unable to set channels %d: %s", ctx.channels, snd_strerror(err));
}
+ unsigned int sr = ctx.samplerate;
+
// set samplerate
- err = snd_pcm_hw_params_set_rate_near(handle, alsa_hwparams, (unsigned int *)&ctx.samplerate, NULL);
+ err = snd_pcm_hw_params_set_rate_near(handle, alsa_hwparams, &sr, NULL);
if (err < 0) {
esyslog("[dxr3-audio-alsa] Unable to set samplerate %d: %s", ctx.samplerate, snd_strerror(err));
}
@@ -124,6 +132,51 @@ void cAudioAlsa::setup(const SampleContext& ctx)
esyslog("[dxr3-audio-alsa] Cannot prepare audio interface for use: %s", snd_strerror(err));
}
+ //
+ // set software settings
+
+ err = snd_pcm_sw_params_current(handle, alsa_swparams);
+ if (err < 0) {
+ esyslog("[dxr3-audio-alsa] Cannot get current sw params: %s", snd_strerror(err));
+ }
+
+ static snd_pcm_uframes_t chunk_size = 1024;
+
+ // start playing when one period has been written
+ err = snd_pcm_sw_params_set_start_threshold(handle, alsa_swparams, chunk_size);
+ if (err < 0) {
+ esyslog("[dxr3-audio-alsa] Failed to set chunk_size: %s", snd_strerror(err));
+ }
+
+ snd_pcm_uframes_t boundary;
+#if SND_LIB_VERSION >= 0x000901
+ err = snd_pcm_sw_params_get_boundary(alsa_swparams, &boundary);
+ if (err < 0) {
+ esyslog("[dxr3-audio-alsa] Failed to get boundary: %s", snd_strerror(err));
+ }
+#else
+ boundary = 0x7fffffff;
+#endif
+
+ // disable underrun reporting
+ err = snd_pcm_sw_params_set_stop_threshold(handle, alsa_swparams, boundary);
+ if (err < 0) {
+ esyslog("[dxr3-audio-alsa] Failed to disable underrun reporting: %s", snd_strerror(err));
+ }
+
+#if SND_LIB_VERSION >= 0x000901
+ // play silence when there is an underrun
+ err = snd_pcm_sw_params_set_silence_size(handle, alsa_swparams, boundary);
+ if (err < 0) {
+ esyslog("[dxr3-audio-alsa] Failed to enable silence mode: %s", snd_strerror(err));
+ }
+#endif
+
+ err = snd_pcm_sw_params(handle, alsa_swparams);
+ if (err < 0) {
+ esyslog("[dxr3-audio-alsa] Failed to set sw params: %s", snd_strerror(err));
+ }
+
curContext.channels = ctx.channels;
curContext.samplerate = ctx.samplerate;
@@ -198,4 +251,3 @@ void cAudioAlsa::Xrun()
esyslog("[dxr3-audio-alsa]: read/write error FATAL exiting");
exit(-1);
}
-