2 * This file is part of DisOrder.
3 * Copyright (C) 2009 Richard Kettlewell
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 /** @file lib/uaudio-schedule.c
19 * @brief Scheduler for RTP and command backends
21 * These functions ensure that audio is only written at approximately the rate
22 * it should play at, allowing pause to function properly.
24 * OSS and ALSA we expect to be essentially synchronous (though we could use
25 * this code if they don't play nicely). Core Audio sorts out its own timing
28 * The sequence numbers are intended for RTP's use but it's more convenient to
32 * - we maintain a base time
33 * - we calculate from this how many samples SHOULD have been sent by now
34 * - we compare this with the number of samples sent so far
35 * - we use this to wait until we're ready to send something
36 * - it's up to the caller to send nothing, or send 0s, if it's supposed to
39 * An implication of this is that the caller must still call
40 * uaudio_schedule_sync() when deactivated (paused) and pretend to send 0s.
55 /** @brief Sample timestamp
57 * This is the timestamp that will be used on the next outbound packet.
59 * The timestamp in an RTP packet header is only 32 bits wide. With 44100Hz
60 * stereo, that only gives about half a day before wrapping, which is not
61 * particularly convenient for certain debugging purposes. Therefore the
62 * timestamp is maintained as a 64-bit integer, giving around six million years
63 * before wrapping, and truncated to 32 bits when transmitting.
65 static uint64_t timestamp;
69 * This is the base time that corresponds to a timestamp of 0.
73 /** @brief Synchronize playback operations against real time
74 * @return Sample number
77 uint32_t uaudio_schedule_sync(void) {
78 const unsigned rate = uaudio_rate * uaudio_channels;
81 xgettimeofday(&now, NULL);
82 /* If we're just starting then we might as well send as much as possible
88 /* Calculate how many microseconds ahead of the base time we are */
89 uint64_t us = tvsub_us(now, base);
90 /* Calculate how many samples that is */
91 uint64_t samples = us * rate / 1000000;
94 * We've actually sent 'timestamp' samples so far.
96 * We OUGHT to have sent 'samples' samples so far.
98 * Suppose it's the SECOND call. timestamp will be (say) 716. 'samples'
99 * will be (say) 10 - there's been a bit of scheduling delay. So in that
100 * case we should wait for 716-10=706 samples worth of time before we can
101 * even send one sample.
103 * So we wait that long and send our 716 samples.
105 * On the next call we'll have timestamp=1432 and samples=726, say. So we
106 * wait and send again.
108 * On the next call there's been a bit of a delay. timestamp=2148 but
109 * samples=2200. So we send our 716 samples immediately.
111 * If the delay had been longer we might sent further packets back to back to
114 * Now timestamp=2864 and samples=2210 (say). Now we're back to waiting.
116 if(samples < timestamp) {
117 /* We should delay a bit */
118 int64_t wait_samples = timestamp - samples;
119 int64_t wait_ns = wait_samples * 1000000000 / rate;
121 struct timespec ts[1];
122 ts->tv_sec = wait_ns / 1000000000;
123 ts->tv_nsec = wait_ns % 1000000000;
126 "samples=%8"PRIu64" timestamp=%8"PRIu64" wait=%"PRId64" (%"PRId64"ns)\n",
127 samples, timestamp, wait_samples, wait_ns);
129 while(nanosleep(ts, ts) < 0 && errno == EINTR)
133 fprintf(stderr, "samples=%8"PRIu64" timestamp=%8"PRIu64"\n",
137 /* If samples >= timestamp then it's time, or gone time, to play the
138 * timestamp'th sample. So we return immediately. */
142 /** @brief Report how many samples we actually sent
143 * @param nsamples Number of samples sent
145 void uaudio_schedule_sent(size_t nsamples) {
146 timestamp += nsamples;
149 /** @brief Initialize audio scheduling
151 * Should be called from your API's @c start callback.
153 void uaudio_schedule_init(void) {
154 /* uaudio_schedule_play() will spot this and choose an initial value */