summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2023-04-25 14:33:46 +0200
committerJaroslav Kysela <perex@perex.cz>2023-05-03 13:56:19 +0200
commitdd9cb31a90594e19f7a3ad53dc1a6344ddf78f7e (patch)
tree22609a6d422a16427585750633acce5ffb29085d
parent2115cdb4dc314d66e92a9e04413bcedc543da007 (diff)
downloadalsa-lib-dd9cb31a90594e19f7a3ad53dc1a6344ddf78f7e.tar.gz
pcm: hw: add drain_silence configuration keyword
# Add silence in drain (-1 = auto /default/, 0 = off, > 0 milliseconds) [drain_silence INT] Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r--src/pcm/pcm_hw.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c
index d6bc7ee0..6d7b2d48 100644
--- a/src/pcm/pcm_hw.c
+++ b/src/pcm/pcm_hw.c
@@ -111,6 +111,7 @@ typedef struct {
int max;
} rates;
int channels;
+ int drain_silence;
/* for chmap */
unsigned int chmap_caps;
snd_pcm_chmap_query_t **chmap_override;
@@ -738,8 +739,16 @@ static int snd_pcm_hw_drain(snd_pcm_t *pcm)
if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
goto __skip_silence;
- /* compute end silence size, align to period size + extra time */
+ if (hw->drain_silence == 0)
+ goto __skip_silence;
snd_pcm_sw_params_current_no_lock(pcm, &sw_params);
+ if (hw->drain_silence > 0) {
+ silence_size = (pcm->rate * hw->drain_silence) / 1000;
+ if (silence_size > pcm->buffer_size)
+ silence_size = pcm->buffer_size;
+ goto __manual_silence;
+ }
+ /* compute end silence size, align to period size + extra time */
if ((pcm->boundary % pcm->period_size) == 0) {
silence_size = pcm->period_size - (*pcm->appl.ptr % pcm->period_size);
if (silence_size == pcm->period_size)
@@ -752,6 +761,7 @@ static int snd_pcm_hw_drain(snd_pcm_t *pcm)
silence_size = pcm->period_size;
}
silence_size += pcm->rate / 10; /* 1/10th of second */
+__manual_silence:
if (sw_params.silence_size < silence_size) {
/* fill the silence soon as possible (in the bellow ioctl
* or the next period wake up)
@@ -1818,6 +1828,7 @@ pcm.name {
[rate INT] # Restrict only to the given rate
or [rate [INT INT]] # Restrict only to the given rate range (min max)
[chmap MAP] # Override channel maps; MAP is a string array
+ [drain_silence INT] # Add silence in drain (-1 = auto /default/, 0 = off, > 0 milliseconds)
}
\endcode
@@ -1850,7 +1861,7 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name,
long card = -1, device = 0, subdevice = -1;
const char *str;
int err, sync_ptr_ioctl = 0;
- int min_rate = 0, max_rate = 0, channels = 0;
+ int min_rate = 0, max_rate = 0, channels = 0, drain_silence = -1;
snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN;
snd_config_t *n;
int nonblock = 1; /* non-block per default */
@@ -1991,6 +2002,16 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name,
}
continue;
}
+ if (strcmp(id, "drain_silence") == 0) {
+ long val;
+ err = snd_config_get_integer(n, &val);
+ if (err < 0) {
+ SNDERR("Invalid type for %s", id);
+ goto fail;
+ }
+ drain_silence = val;
+ continue;
+ }
SNDERR("Unknown field %s", id);
err = -EINVAL;
goto fail;
@@ -2033,6 +2054,7 @@ int _snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name,
}
if (chmap)
hw->chmap_override = chmap;
+ hw->drain_silence = drain_silence;
return 0;