# `TuningFork.Sink.Tcp`
[🔗](https://github.com/jaman/tuning_fork/blob/v0.1.5/tuning_fork/lib/tuning_fork/sink/tcp.ex#L1)

Raw signed 16-bit little-endian PCM over a TCP connection, paced to real time, for any
player that can take it from a socket — `ffplay`, `sox`, `pacat --raw` — on the far
end of an ssh tunnel or across a LAN.

    TuningFork.Stage.start_link(sink: TuningFork.Sink.Tcp, sink_opts: [host: "127.0.0.1", port: 24713])

The connection is made on the first write and remade when it drops, trying again every
`:retry_ms`; until a player listens, samples are dropped at real time. A chunk is sent
and then the sink sleeps until the audio before it has nearly played out, keeping
`:lead_ms` of audio in flight, so a player that reads as fast as it can never runs
seconds ahead. With `:warm_up_ms` set, the first 1024 frames go at once, so the player
opens its device, and for that long after them the audio is pulled at real time but
not sent — for a player that queues whatever arrives while it opens its device and
keeps it as lag. `TuningFork.Listener` needs none of it: it drops such a backlog itself.

## Options

  * `:host` — the player's host. Default `"127.0.0.1"`
  * `:port` — the player's port. Required
  * `:lead_ms` — audio kept in flight ahead of real time. Default `60`
  * `:warm_up_ms` — how long after the first frames the audio is dropped while the
    player opens its device. Default `300`
  * `:retry_ms` — how long to wait after a failed connection before trying again.
    Default `2_000`
  * `:rate`, `:channels` — the PCM format, as the stage passes them

## Playing it

    mix tuning_fork.listen --port 4713
    while :; do ffplay -nodisp -autoexit -fflags nobuffer -analyzeduration 0 -probesize 32 -f s16le -ar 44100 -ch_layout stereo -i "tcp://127.0.0.1:4713?listen"; done
    sox -t raw -r 44100 -e signed -b 16 -c 2 - -d < <(nc -l 4713)

---

*Consult [api-reference.md](api-reference.md) for complete listing*
