forked from AngryPenguinPL/pipewire
/
7480d095899cd683d028c405b98076127b60a552.patch
120 lines (106 loc) · 3.86 KB
/
7480d095899cd683d028c405b98076127b60a552.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
From 7480d095899cd683d028c405b98076127b60a552 Mon Sep 17 00:00:00 2001
From: Wim Taymans <wtaymans@redhat.com>
Date: Thu, 3 Feb 2022 16:17:38 +0100
Subject: [PATCH] alsa: update test-timer
Remove the bandwidth reduce, we don't do that.
Clamp large errors.
Add htimestamp mode, which seems more stable.
---
spa/plugins/alsa/test-timer.c | 51 ++++++++++++++++++++++++++++-------
1 file changed, 41 insertions(+), 10 deletions(-)
diff --git a/spa/plugins/alsa/test-timer.c b/spa/plugins/alsa/test-timer.c
index caa6b25e2..16d7df105 100644
--- a/spa/plugins/alsa/test-timer.c
+++ b/spa/plugins/alsa/test-timer.c
@@ -45,10 +45,12 @@ struct state {
unsigned int rate;
unsigned int channels;
snd_pcm_uframes_t period;
+ snd_pcm_uframes_t buffer_frames;
snd_pcm_t *hndl;
int timerfd;
+ double max_error;
float accumulator;
uint64_t next_time;
@@ -103,15 +105,36 @@ static int write_period(struct state *state)
static int on_timer_wakeup(struct state *state)
{
- snd_pcm_sframes_t avail, delay;
+ snd_pcm_sframes_t delay;
double error, corr;
-
- /* check the delay in the device */
- CHECK(snd_pcm_avail_delay(state->hndl, &avail, &delay), "delay");
+#if 1
+ snd_pcm_sframes_t avail;
+ CHECK(snd_pcm_avail_delay(state->hndl, &avail, &delay), "delay");
+#else
+ snd_pcm_uframes_t avail;
+ snd_htimestamp_t tstamp;
+ uint64_t then;
+
+ CHECK(snd_pcm_htimestamp(state->hndl, &avail, &tstamp), "htimestamp");
+ delay = state->buffer_frames - avail;
+
+ then = TIMESPEC_TO_NSEC(&tstamp);
+ if (then != 0) {
+ if (then < state->next_time) {
+ delay -= (state->next_time - then) * state->rate / NSEC_PER_SEC;
+ } else {
+ delay += (then - state->next_time) * state->rate / NSEC_PER_SEC;
+ }
+ }
+#endif
/* calculate the error, we want to have exactly 1 period of
* samples remaining in the device when we wakeup. */
error = (double)delay - (double)state->period;
+ if (error > state->max_error)
+ error = state->max_error;
+ else if (error < -state->max_error)
+ error = -state->max_error;
/* update the dll with the error, this gives a rate correction */
corr = spa_dll_update(&state->dll, error);
@@ -124,12 +147,6 @@ static int on_timer_wakeup(struct state *state)
if (state->next_time - state->prev_time > BW_PERIOD) {
state->prev_time = state->next_time;
-
- /* reduce bandwidth and show some stats */
- if (state->dll.bw > SPA_DLL_BW_MIN)
- spa_dll_set_bw(&state->dll, state->dll.bw / 2.0,
- state->period, state->rate);
-
fprintf(stdout, "corr:%f error:%f bw:%f\n",
corr, error, state->dll.bw);
}
@@ -144,6 +161,7 @@ int main(int argc, char *argv[])
struct state state = { 0, };
const char *device = DEFAULT_DEVICE;
snd_pcm_hw_params_t *hparams;
+ snd_pcm_sw_params_t *sparams;
struct timespec now;
CHECK(snd_pcm_open(&state.hndl, device, SND_PCM_STREAM_PLAYBACK, 0), "open %s failed", device);
@@ -165,12 +183,25 @@ int main(int argc, char *argv[])
&state.rate, 0), "set rate");
CHECK(snd_pcm_hw_params(state.hndl, hparams), "hw_params");
+ CHECK(snd_pcm_hw_params_get_buffer_size(hparams, &state.buffer_frames), "get_buffer_size_max");
+
fprintf(stdout, "opened format:%s rate:%u channels:%u\n",
snd_pcm_format_name(SND_PCM_FORMAT_S32_LE),
state.rate, state.channels);
+ snd_pcm_sw_params_alloca(&sparams);
+#if 0
+ CHECK(snd_pcm_sw_params_current(state.hndl, sparams), "sw_params_current");
+ CHECK(snd_pcm_sw_params_set_tstamp_mode(state.hndl, sparams, SND_PCM_TSTAMP_ENABLE),
+ "sw_params_set_tstamp_type");
+ CHECK(snd_pcm_sw_params_set_tstamp_type(state.hndl, sparams, SND_PCM_TSTAMP_TYPE_MONOTONIC),
+ "sw_params_set_tstamp_type");
+ CHECK(snd_pcm_sw_params(state.hndl, sparams), "sw_params");
+#endif
+
spa_dll_init(&state.dll);
spa_dll_set_bw(&state.dll, SPA_DLL_BW_MAX, state.period, state.rate);
+ state.max_error = 256.0;
if ((state.timerfd = timerfd_create(CLOCK_MONOTONIC, 0)) < 0)
perror("timerfd");
--
GitLab