This file is indexed.

/usr/share/doc/liquidsoap/html/clocks.html is in liquidsoap 1.0.0-4build1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML \
1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
  <meta content="text/html; charset=UTF-8" http-equiv="content-type" />
  <title>Liquidsoap :: Clocks</title>
  <link href="style.css" type="text/css" rel="stylesheet" />
  <link href="homepage.css" type="text/css" rel="stylesheet" />
</head>
<body>
<div id="wrapper">
  <div id="header">
    <div id="logo">
      <h1>Liquidsoap</h1>
      <h2>audio stream generation</h2>
    </div>
  <div>
   <ul id="menu">
     <li id="menu-about">
       <a href="index.html">about</a></li>
     <li id="menu-doc-index">
       <a href="documentation.html">documentation</a></li>
     <li id="menu-doc-api">
       <a href="reference.html">API</a></li>
     <li id="menu-doc-snippets">
       <a href="scripts/index.html">snippets</a></li>
     <li id="menu-developers">
       <a href="http://savonet.rastageeks.org/">developers</a></li>
   </ul>
  </div>
  </div>
  <div id="content"><div>
  <h3>Clocks</h3>
<p>
In the <a href="quick_start.html">quickstart</a> and in the introduction to liquidsoap
<a href="sources.html">sources</a>, we have described a simple world in which sources
communicate with each other, creating and transforming data that
composes multimedia streams.
In this simple view, all sources produce data at the same rate,
animated by a single clock: at every cycle of the clock,
a fixed amount of data is produced.
</p>
<p>
While this simple picture is useful to get a fair idea of what's going on
in liquidsoap, the full picture is more complex: in fact, a streaming
system might involve <em>multiple clocks</em>, or in other words several
time flows.
</p>
<p>
It is only in very particular cases that liquidsoap scripts
need to mention clocks explicitly. Otherwise, you won't even notice
how many clocks are involved in your setup: indeed, liquidsoap can figure
out the clocks by itself, much like it infers types.
Nevertheless, there will sometimes be cases where your script cannot
be assigned clocks in a correct way, in which case liquidsoap will
complain. For that reason, every user should eventually get a minimum
understanding of clocks.
</p>
<p>
In the following, we first describe why we need clocks.
Then we go through the possible errors that any user might encounter
regarding clocks.
Finally, we describe how to explicitly use clocks,
and show a few striking examples of what can be achieved that way.
</p>
<h4>Why multiple clocks</h4>
<p>
The first reason is <b>external</b> to liquidsoap: there is simply
not a unique notion of time in the real world.
Your computer has an internal clock which indicates
a slightly different time than your watch or another computer's clock.
Moreover, when communicating with a remote computer, network
latency causes extra time distortions.
Even within a single computer there are several clocks: notably, each
soundcard has its own clock, which will tick at a slightly different
rate than the main clock of the computer.
Since liquidsoap communicates with soundcards and remote computers,
it has to take those mismatches into account.
</p>
<p>
There are also some reasons that are purely <b>internal</b> to liquidsoap:
in order to produce a stream at a given speed,
a source might need to obtain data from another source at
a different rate. This is obvious for an operator that speeds up or
slows down audio (<code>stretch</code>). But it also holds more subtly
for <code>cross</code>, <code>smart_cross</code> as well as the
derived operators: during the lapse of time where the operator combines
data from an end of track with the beginning of the other other,
the crossing operator needs twice as much stream data. After ten tracks,
with a crossing duration of six seconds, one more minute will have
passed for the source compared to the time of the crossing operator.
</p>
<p>
In order to avoid inconsistencies caused by time differences,
while maintaining a simple and efficient execution model for
its sources, liquidsoap works under the restriction that
one source belongs to a unique clock,
fixed once for all when the source is created.
</p>
<p>
The graph representation of streaming systems can be adapted
into a good representation of what clocks mean.
One simply needs to add boxes representing clocks:
a source can belong to only one box,
and all sources of a box produce streams at the same rate.
For example, 
<code>output.icecast(fallback([crossfade(playlist(...)),jingles]))</code>
yields the following graph:
</p>
<img alt="Graph representation with clocks" src="./images/graph_clocks.png" /><p>
Here, clock_2 was created specifically for the crossfading
operator; the rate of that clock is controlled by that operator,
which can hence accelerate it around track changes without any
risk of inconsistency.
The other clock is simply a wallclock, so that the main stream
is produced following the “real” time rate.
</p>
<h4>Error messages</h4>
<p>
Most of the time you won't have to do anything special about clocks:
operators that have special requirements regarding clocks will do
what's necessary themselves, and liquidsoap will check that everything is 
fine. But if the check fails, you'll need to understand the error,
which is what this section is for.
</p>
<h5>Disjoint clocks</h5>
<p>
On the following example, liquidsoap will issue the fatal error
<code>a source cannot belong to two clocks</code>:
</p>
<pre>
s = playlist("~/media/audio")
output.alsa(s) # perhaps for monitoring
output.icecast(mount="radio.ogg",%vorbis,crossfade(s))
</pre>
<p>
Here, the source <code>s</code> is first assigned the ALSA clock,
because it is tied to an ALSA output.
Then, we attempt to build a <code>crossfade</code> over <code>s</code>.
But this operator requires its source to belong to a dedicated
internal clock (because crossfading requires control over the flow
of the of the source, to accelerate it around track changes).
The error expresses this conflict:
<code>s</code> must belong at the same time to the ALSA clock
and <code>crossfade</code>'s clock.
</p>
<h5>Nested clocks</h5>
<p>
On the following example, liquidsoap will issue the fatal error
<code>cannot unify two nested clocks</code>:
</p>
<pre>
jingles = playlist("jingles.lst")
music = rotate([1,10],[jingles,playlist("remote.lst")])
safe = rotate([1,10],[jingles,single("local.ogg")])
q = fallback([crossfade(music),safe])
</pre>
<p>
Let's see what happened.
The <code>rotate</code> operator, like most operators, operates
within a single clock, which means that <code>jingles</code>
and our two <code>playlist</code> instances must belong to the same clock.
Similarly, <code>music</code> and <code>safe</code> must belong to that
same clock.
When we applied crossfading to <code>music</code>,
the <code>crossfade</code> operator created its own internal clock,
call it <code>cross_clock</code>,
to signify that it needs the ability to accelerate at will the
streaming of <code>music</code>.
So, <code>music</code> is attached to <code>cross_clock</code>,
and all sources built above come along.
Finally, we build the fallback, which requires that all of its
sources belong to the same clock.
In other words, <code>crossfade(music)</code> must belong
to <code>cross_clock</code> just like <code>safe</code>.
The error message simply says that this is forbidden: the internal
clock of our crossfade cannot be its external clock &ndash; otherwise
it would not have exclusive control over its internal flow of time.
</p>
<p>
The same error also occurs on <code>add([crossfade(s),s])</code>,
the simplest example of conflicting time flows, described above.
However, you won't find yourself writing this obviously problematic
piece of code. On the other hand, one would sometimes like to
write things like our first example.
</p>
<p>
The key to the error with our first example is that the same
<code>jingles</code> source is used in combination with <code>music</code>
and <code>safe</code>. As a result, liquidsoap sees a potentially
nasty situation, which indeed could be turned into a real mess
by adding just a little more complexity. To obtain the desired effect
without requiring illegal clock assignments, it suffices to
create two jingle sources, one for each clock:
</p>
<pre>
music = rotate([1,10],[playlist("jingles.lst"),
                       playlist("remote.lst")])
safe  = rotate([1,10],[playlist("jingles.lst"),
                       single("local.ogg")])
q = fallback([crossfade(music),safe])
</pre>
<p>
There is no problem anymore: <code>music</code> belongs to 
<code>crossfade</code>'s internal clock, and <code>crossfade(music)</code>,
<code>safe</code> and the <code>fallback</code> belong to another clock.
</p>
<h4>The clock API</h4>
<p>
There are only a couple of operations dealing explicitly with clocks.
</p>
<p>
The function <code>clock.assign_new(l)</code> creates a new clock
and assigns it to all sources from the list <code>l</code>.
For convenience, we also provide a wrapper, <code>clock(s)</code>
which does the same with a single source instead of a list,
and returns that source.
With both functions, the new clock will follow (the computer's idea of)
real time, unless <code>sync=false</code> is passed, in which case
it will run as fast as possible.
</p>
<p>
The old (pre-1.0.0) setting <code>root.sync</code> is superseded
by <code>clock.assign_new()</code>.
If you want to run an output as fast as your CPU allows,
just attach it to a new clock without synchronization:
</p>
<pre>clock.assign_new(sync=false,[output.file(%vorbis,"audio.ogg",source)])
</pre>
<p>
This will automatically attach the appropriate sources to that clock.
However, you may need to do it for other operators if they are totally
unrelated to the first one.
</p>
<p>
The <code>buffer()</code> operator can be used to communicate between
any two clocks: it takes a source in one clock and builds a source
in another. The trick is that it uses a buffer: if one clock
happens to run too fast or too slow, the buffer may empty or overflow.
</p>
<p>
Finally, <code>get_clock_status</code> provides information on
existing clocks and track their respective times:
it returns a list containing for each clock a pair
<code>(name,time)</code> indicating
the clock id its current time in <em>clock cycles</em> &ndash;
a cycle corresponds to the duration of a frame,
which is given in ticks, displayed on startup in the logs.
The helper function <code>log_clocks</code> built
around <code>get_clock_status</code> can be used to directly
obtain a simple log file, suitable for graphing with gnuplot.
Those functions are useful to debug latency issues.
</p>
<h4>External clocks: decoupling latencies</h4>
<p>
The first reason to explicitly assign clocks is to precisely handle
the various latencies that might occur in your setup.
</p>
<p>
Most input/output operators (ALSA, AO, Jack, OSS, etc)
require their own clocks. Indeed, their processing rate is constrained
by external sound APIs or by the hardware itself.
Sometimes, it is too much of an inconvenience,
in which case one can set <code>clock_safe=false</code> to allow
another clock assignment &ndash;
use at your own risk, as this might create bad latency interferences.
</p>
<p>
Currently, <code>output.icecast</code> does not require to belong
to any particular clock. This allows to stream according to the
soundcard's internal clock, like in most other tools:
in <code>output.icecast(%vorbis,mount="live.ogg",input.alsa())</code>,
the ALSA clock will drive the streaming of the soundcard input via
icecast.
</p>
<p>
Sometimes, the external factors tied to Icecast output cannot be
disregarded: the network may lag. If you stream a soundcard input
to Icecast and the network lags, there will be a glitch in the
soundcard input &ndash; a long enough lag will cause a disconnection,
in which case there won't be anybody to notice the huge glitch.
This might be undesirable, and is certainly disappointing if you
are recording a backup of your precious soundcard input using
<code>output.file</code>: by default it will suffer the same
latencies and glitches, while in theory it could be perfect.
To fix this you can explicitly separate Icecast (high latency,
low quality acceptable) from the backup and soundcard input (low latency,
high quality wanted):
</p>
<pre>
input = input.oss()

clock.assign_new(id="icecast",
  [output.icecast(%mp3,mount="blah",mksafe(buffer(input)))])

output.file(
  %mp3,"record-%Y-%m-%d-%H-%M-%S.mp3",
  input)
</pre>
<p>
Here, the soundcard input and file output end up in the OSS
clock. The icecast output
goes to the explicitly created <code>"icecast"</code> clock,
and a buffer is used to
connect it to the soundcard input. Small network lags will be
absorbed by the buffer. Important lags and possible disconnections
will result in an overflow of the buffer.
In any case, the OSS input and file output won't be affected
by those latencies, and the recording should be perfect.
The Icecast quality is also better with that setup,
since small lags are absorbed by the buffer and do not create
a glitch in the OSS capture, so that Icecast listeners won't
notice the lag at all.
</p>
<p>
Note that explicitly assigning a new clock for the Icecast
output was unnecessary: liquidsoap would have chosen the default
wallclock otherwise. However, it is better practice to force
it manually, to make to obtain the wanted clock assignment.
It is especially important since you might change your script
later, and you want to avoid an unnoticed change of the
clock assignment.
</p>
<h4>Internal clocks: exploiting multiple cores</h4>
<p>
Clocks can also be useful even when external factors are not an issue.
Indeed, several clocks run in several threads, which creates an opportunity
to exploit multiple CPU cores.
The story is a bit complex because OCaml has some limitations on
exploiting multiple cores, but in many situations most of the computing
is done in C code (typically decoding and encoding) so it parallelizes
quite well.
</p>
<p>
Typically, if you run several outputs that do not share much (any) code,
you can put each of them in a separate clock.
For example the following script takes one file and encodes it as MP3
twice. You should run it as <code>liquidsoap EXPR -- FILE</code>
and observe that it fully exploits two cores:
</p>
<pre>
def one()
  clock.assign_new(sync=false,
        [output.file(%mp3,"/dev/null",single(argv(1)))])
end
one()
one()
</pre>
  </div></div>
  <div>
    <div id="footer"> 2003-2011 Savonet team</div>
  </div>
  </div>
</body></html>