dnl To generate the html version, execute dnl m4 web/manual.m4 | grutatxt --toc define(`LOCAL_LINK_NAME', `translit(`$1', `A-Z ', `a-z__')') define(`REMOVE_NEWLINE', `translit(`$1',` ', ` ')') define(`REFERENCE', ./``#''`LOCAL_LINK_NAME($1)' (`REMOVE_NEWLINE($2)')) define(`XREFERENCE', `$1' (`REMOVE_NEWLINE($2)')) define(`EMPH', ``_''`REMOVE_NEWLINE($1)'``_'') Paraslash user manual ===================== This document describes how to install, configure and use the paraslash network audio streaming system. Most chapters start with a chapter overview and conclude with an example section. We try to focus on general concepts and on the interaction of the various pieces of the paraslash package. Hence this user manual is not meant as a replacement for the manual pages that describe all command line options of each paraslash executable. ------------ Introduction ------------ In this chapter we give an REFERENCE(Overview, overview) of the interactions of the two main programs contained in the paraslash package, followed by REFERENCE(The paraslash executables, brief descriptions) of all executables. Overview ~~~~~~~~ The core functionality of the para suite is provided by two main executables, para_server and para_audiod. The former maintains a database of audio files and streams these files to para_audiod which receives and plays the stream. In a typical setting, both para_server and para_audiod act as background daemons whose functionality is controlled by client programs: the para_audioc client controls para_audiod over a local socket while the para_client program connects to para_server over a local or remote networking connection. Typically, these two daemons run on different hosts but a local setup is also possible. A simplified picture of a typical setup is as follows <<
server_host client_host ~~~~~~~~~~~ ~~~~~~~~~~~ +-----------+ audio stream +-----------+ |para_server| -----------------------------> |para_audiod| +-----------+ +-----------+ ^ ^ | | | | connect | | | | | +-----------+ | |para_audioc| | +-----------+ | | | connect +-----------+ +-------------------------------------- |para_client| +-----------+>> The paraslash executables ~~~~~~~~~~~~~~~~~~~~~~~~~ *para_server* para_server streams binary audio data (MP3, ...) over local and/or remote networks. It listens on a TCP port and accepts commands such as play, stop, pause, next from authenticated clients. There are many more commands though, see the man page of para_server for a description of all commands. It supports three built-in network streaming protocols (senders/receivers): HTTP, DCCP, or UDP. This is explained in more detail in the section on REFERENCE(Networking, networking). The built-in audio file selector of paraslash is used to manage your audio files. It maintains statistics on the usage of all available audio files such as last-played time, and the number of times each file was selected. Additional information may be added to the database to allow fine-grained selection based on various properties of the audio file, including information found in (ID3) tags. However, old-fashioned playlists are also supported. It is also possible to store images (album covers) and lyrics in the database and associate these to the corresponding audio files. The section on the REFERENCE(The audio file selector, audio file selector) discusses this topic. *para_client* The client program to connect to para_server. paraslash commands are sent to para_server and the response is dumped to STDOUT. This can be used by any scripting language to produce user interfaces with little programming effort. All connections between para_server and para_client are encrypted with a symmetric RC4 session key. For each user of paraslash you must create a public/secret RSA key pair for authentication. If para_client is started without non-option arguments, an interactive session (shell) is started. Command history and command completion are supported through libreadline. *para_audiod* The local daemon that collects information from para_server. It runs on the client side and connects to para_server. As soon as para_server announces the availability of an audio stream, para_audiod starts an appropriate receiver, any number of filters and a paraslash writer to play the stream. Moreover, para_audiod listens on a local socket and sends status information about para_server and para_audiod to local clients on request. Access via this local socket may be restricted by using Unix socket credentials, if available. *para_audioc* The client program which talks to para_audiod. Used to control para_audiod, to receive status info, or to grab the stream at any point of the decoding process. Like para_client, para_audioc supports interactive sessions on systems with libreadline. *para_recv* A command line HTTP/DCCP/UDP stream grabber. The http mode is compatible with arbitrary HTTP streaming sources (e.g. icecast). In addition to the three network streaming modes, para_recv can also operate in local (afh) mode. In this mode it writes the content of an audio file on the local file system in complete chunks to stdout, optionally 'just in time'. This allows to cut an audio file without first decoding it, and it enables third-party software which is unaware of the particular audio format to send complete frames in real time. *para_filter* A filter program that reads from STDIN and writes to STDOUT. Like para_recv, this is an atomic building block which can be used to assemble higher-level audio receiving facilities. It combines several different functionalities in one tool: decoders for multiple audio formats and a number of processing filters, among these a normalizer for audio volume. *para_afh* A small stand-alone program that prints tech info about the given audio file to STDOUT. It can be instructed to print a "chunk table", an array of offsets within the audio file. *para_write* A modular audio stream writer. It supports a simple file writer output plug-in and optional WAV/raw players for ALSA (Linux) and for coreaudio (Mac OS). para_write can also be used as a stand-alone WAV or raw audio player. *para_play* A command line audio player. *para_gui* Curses-based gui that presents status information obtained in a curses window. Appearance can be customized via themes. para_gui provides key-bindings for the most common server commands and new key-bindings can be added easily. *para_fade* An alarm clock and volume-fader for OSS and ALSA. ----------- Quick start ----------- This chapter lists the REFERENCE(Requirements, necessary software) that must be installed to compile the paraslash package, describes how to REFERENCE(Installation, compile and install) the paraslash source code and the steps that have to be performed in order to REFERENCE(Quick start, set up) a typical server and client. Requirements ~~~~~~~~~~~~ For the impatient: git clone git://git.tuebingen.mpg.de/osl cd osl && make && sudo make install && sudo ldconfig sudo apt-get install autoconf libssl-dev help2man gengetopt \ libmad0-dev libid3tag0-dev libasound2-dev libvorbis-dev \ libfaad-dev libspeex-dev libFLAC-dev libsamplerate-dev \ libasound2-dev libao-dev libreadline-dev libncurses-dev Detailed description: In any case you'll need - XREFERENCE(http://systemlinux.org/~maan/osl/, libosl). The _object storage layer_ library is used by para_server. To clone the source code repository, execute git clone git://git.tuebingen.mpg.de/osl - XREFERENCE(ftp://ftp.gnu.org/pub/gnu/gcc, gcc) or XREFERENCE(http://clang.llvm.org, clang). All gcc versions >= 3.3 are currently supported. Clang version 1.1 or newer should work as well. - XREFERENCE(ftp://ftp.gnu.org/pub/gnu/make, gnu make) is also shipped with the disto. On BSD systems the gnu make executable is often called gmake. - XREFERENCE(ftp://ftp.gnu.org/pub/gnu/bash, bash). Some scripts which run during compilation require the EMPH(Bourne again shell). It is most likely already installed. - XREFERENCE(http://www.openssl.org/, openssl) or XREFERENCE(ftp://ftp.gnupg.org/gcrypt/libgcrypt/, libgcrypt). At least one of these two libraries is needed as the backend for cryptographic routines on both the server and the client side. Both openssl and libgcrypt are usually shipped with the distro, but you might have to install the development package (libssl-dev or libgcrypt-dev on debian systems) as well. - XREFERENCE(ftp://ftp.gnu.org/pub/gnu/gengetopt/, gengetopt) is needed to generate the C code for the command line parsers of all paraslash executables. - XREFERENCE(ftp://ftp.gnu.org/pub/gnu/help2man, help2man) is used to create the man pages. Optional: - XREFERENCE(http://www.underbit.com/products/mad/, libmad). To compile in MP3 support for paraslash, the development package must be installed. It is called libmad0-dev on debian-based systems. Note that libmad is not necessary on the server side, i.e. for sending MP3 files. - XREFERENCE(http://www.underbit.com/products/mad/, libid3tag). For version-2 ID3 tag support, you'll need the libid3tag development package libid3tag0-dev. Without libid3tag, only version one tags are recognized. - XREFERENCE(http://www.xiph.org/downloads/, ogg vorbis). For ogg vorbis streams you'll need libogg, libvorbis, libvorbisfile. The corresponding Debian packages are called libogg-dev and libvorbis-dev. - XREFERENCE(http://www.audiocoding.com/, libfaad). For aac files (m4a) you'll need libfaad (libfaad-dev). - XREFERENCE(http://www.speex.org/, speex). In order to stream or decode speex files, libspeex (libspeex-dev) is required. - XREFERENCE(http://flac.sourceforge.net/, flac). To stream or decode files encoded with the _Free Lossless Audio Codec_, libFLAC (libFLAC-dev) must be installed. - XREFERENCE(http://www.mega-nerd.com/SRC/index.html, libsamplerate). The resample filter will only be compiled if this library is installed. Debian package: libsamplerate-dev. - XREFERENCE(ftp://ftp.alsa-project.org/pub/lib/, alsa-lib). On Linux, you'll need to have ALSA's development package libasound2-dev installed. - XREFERENCE(http://downloads.xiph.org/releases/ao/, libao). Needed to build the ao writer (ESD, PulseAudio,...). Debian package: libao-dev. - XREFERENCE(ftp://ftp.gnu.org/pub/gnu/ncurses, curses). Needed for para_gui. Debian package: libncurses-dev. - XREFERENCE(http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html, GNU Readline). If this library (libreadline-dev) is installed, para_client, para_audioc and para_play support interactive sessions. Installation ~~~~~~~~~~~~ First make sure all non-optional packages listed in the section on REFERENCE(Requirements, required software) are installed on your system. You don't need everything listed there. In particular, MP3, OGG/Vorbis, OGG/Speex and AAC support are all optional. The configure script will detect what is installed on your system and will only try to build those executables that can be built with your setup. Note that no special decoder library (not even the MP3 decoding library libmad) is needed for para_server if you only want to stream MP3 or WMA files. Also, it's fine to use para_server on a box without sound card. Next, install the paraslash package on all machines, you'd like this software to run on. If you compile from a released tarball, execute (./configure && make) > /dev/null When compiling from git or from snapshots downloaded via gitweb, the above command will not work because the configure script is not included in the git repository. In this case the following command should be used instead: ./autogen.sh This runs autoconf to generate the configure script, then runs it as above. Therefore you'll need autoconf for this to work. There should be no errors but probably some warnings about missing packages which usually implies that not all audio formats will be supported. If headers or libs are installed at unusual locations you might need to tell the configure script where to find them. Try ./configure --help to see a list of options. If the paraslash package was compiled successfully, execute (optionally) make test to run the paraslash test suite. If all tests pass, execute as root make install to install executables under /usr/local/bin and the man pages under /usr/local/man. Configuration ~~~~~~~~~~~~~ *Step 1*: Create a paraslash user In order to control para_server at runtime you must create a paraslash user. As authentication is based on the RSA crypto system you'll have to create an RSA key pair. If you already have a user and an RSA key pair, you may skip this step. In this section we'll assume a typical setup: You would like to run para_server on some host called server_host as user foo, and you want to connect to para_server from another machine called client_host as user bar. As foo@server_host, create ~/.paraslash/server.users by typing the following commands: user=bar target=~/.paraslash/server.users key=~/.paraslash/id_rsa.pub.$user perms=AFS_READ,AFS_WRITE,VSS_READ,VSS_WRITE mkdir -p ~/.paraslash echo "user $user $key $perms" >> $target Next, change to the "bar" account on client_host and generate the key pair with the commands ssh-keygen -t rsa -b 2048 # hit enter twice to create a key with no passphrase This generates the two files id_rsa and id_rsa.pub in ~/.ssh. Note that paraslash can also read keys generated by the "openssl genrsa" command. However, since keys created with ssh-keygen can also be used for ssh, this method is recommended. Note that para_server refuses to use a key if it is shorter than 2048 bits. In particular, the RSA keys of paraslash 0.3.x will not work with version 0.4.x. Moreover, para_client refuses to use a (private) key which is world-readable. para_server only needs to know the public key of the key pair just created. Copy this public key to server_host: src=~/.ssh/id_rsa.pub dest=.paraslash/id_rsa.pub.$LOGNAME scp $src foo@server_host:$dest Finally, tell para_client to connect to server_host: conf=~/.paraslash/client.conf echo 'hostname server_host' > $conf *Step 2*: Start para_server Before starting the server make sure you have write permissions to the directory /var/paraslash that has been created during installation: sudo chown $LOGNAME /var/paraslash Alternatively, use the --afs-socket Option to specify a different location for the AFS command socket. For this first try, we'll use the info loglevel to make the output of para_server more verbose. para_server -l info Now you can use para_client to connect to the server and issue commands. Open a new shell as bar@client_host and try para_client help para_client si to retrieve the list of available commands and some server info. Don't proceed if this doesn't work. *Step 3*: Create and populate the database An empty database is created with para_client init This initializes a couple of empty tables under ~/.paraslash/afs_database-0.4. You normally don't need to look at these tables, but it's good to know that you can start from scratch with rm -rf ~/.paraslash/afs_database-0.4 in case something went wrong. Next, you need to add some audio files to that database so that para_server knows about them. Choose an absolute path to a directory containing some audio files and add them to the audio file table: para_client add /my/mp3/dir This might take a while, so it is a good idea to start with a directory containing not too many files. Note that the table only contains data about the audio files found, not the files themselves. You may print the list of all known audio files with para_client ls *Step 4*: Configure para_audiod para_audiod needs to create a "well-known" socket for the clients to connect to. The default path for this socket is /var/paraslash/audiod_socket.$HOSTNAME In order to make this directory writable for para_audiod, execute as bar@client_host sudo chown $LOGNAME /var/paraslash We will also have to tell para_audiod that it should receive the audio stream from server_host via http: para_audiod -l info -r '.:http -i server_host' You should now be able to listen to the audio stream once para_server starts streaming. To activate streaming, execute para_client play Since no playlist has been specified yet, the "dummy" mode which selects all known audio files is activated automatically. See the section on the REFERENCE(The audio file selector, audio file selector) for how to use playlists and moods to specify which files should be streamed in which order. *Troubleshooting* It did not work? To find out why, try to receive, decode and play the stream manually using para_recv, para_filter and para_write as follows. For simplicity we assume that you're running Linux/ALSA and that only MP3 files have been added to the database. para_recv -r 'http -i server_host' > file.mp3 # (interrupt with CTRL+C after a few seconds) ls -l file.mp3 # should not be empty para_filter -f mp3dec -f wav < file.mp3 > file.wav ls -l file.wav # should be much bigger than file.mp3 para_write -w alsa < file.wav Double check what is logged by para_server and use the --loglevel option of para_recv, para_filter and para_write to increase verbosity. --------------- User management --------------- para_server uses a challenge-response mechanism to authenticate requests from incoming connections, similar to ssh's public key authentication method. Authenticated connections are encrypted using the RC4 stream cipher. In this chapter we briefly describe RSA and RC4 and sketch the REFERENCE(Client-server authentication, authentication handshake) between para_client and para_server. User management is discussed in the section on REFERENCE(The user_list file, the user_list file). These sections are all about communication between the client and the server. Connecting para_audiod is a different matter and is described in a REFERENCE(Connecting para_audiod, separate section). RSA and RC4 ~~~~~~~~~~~ RSA is an asymmetric block cipher which is used in many applications, including ssh and gpg. An RSA key consists in fact of two keys, called the public key and the private key. A message can be encrypted with either key and only the counterpart of that key can decrypt the message. While RSA can be used for both signing and encrypting a message, paraslash uses RSA only for the latter purpose. The RSA public key encryption and signatures algorithms are defined in detail in RFC 2437. RC4 is a stream cipher, i.e. the input is XORed with a pseudo-random key stream to produce the output. Decryption uses the same function calls as encryption. While RC4 supports variable key lengths, paraslash uses a fixed length of 256 bits, which is considered a strong encryption by today's standards. Since the same key must never be used twice, a different, randomly-generated key is used for every new connection. Client-server authentication ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The authentication handshake between para_client and para_server goes as follows: - para_client connects to para_server and sends an authentication request for a user. It does so by connecting to TCP port 2990 of the server host. This port is called the para_server _control port_. - para_server accepts the connection and forks a child process which handles the incoming request. The parent process keeps listening on the control port while the child process (also called para_server below) continues as follows. - para_server loads the RSA public key of that user, fills a fixed-length buffer with random bytes, encrypts that buffer using the public key and sends the encrypted buffer to the client. The first part of the buffer is the challenge which is used for authentication while the second part is the RC4 session key. - para_client receives the encrypted buffer and decrypts it with the user's private key, thereby obtaining the challenge buffer and the session key. It sends the SHA1 hash value of the challenge back to para_server and stores the session key for further use. - para_server also computes the SHA1 hash of the challenge and compares it against what was sent back by the client. - If the two hashes do not match, the authentication has failed and para_server closes the connection. - Otherwise the user is considered authenticated and the client is allowed to proceed by sending a command to be executed. From this point on the communication is encrypted using the RC4 stream cipher with the session key known to both peers. paraslash relies on the quality of the pseudo-random bytes provided by the crypto library (openssl or libgcrypt), on the security of the implementation of the RSA and RC4 crypto routines and on the infeasibility to invert the SHA1 function. Neither para_server or para_client create RSA keys on their own. This has to be done once for each user as sketched in REFERENCE(Quick start, Quick start) and discussed in more detail REFERENCE(The user_list file, below). The user_list file ~~~~~~~~~~~~~~~~~~ At startup para_server reads the user list file which contains one line per user. The default location of the user list file may be changed with the --user-list option. There should be at least one user in this file. Each user must have an RSA key pair. The public part of the key is needed by para_server while the private key is needed by para_client. Each line of the user list file must be of the form user
server_host client_host ~~~~~~~~~~~ ~~~~~~~~~~~ +-----------+ connect +-----------+ |para_server|<------------------------------ |para_client| +-----------+ +-----------+ | ^ | fork +---+ | +----------> |AFS| | | +---+ | | ^ | | | | | | connect (cookie) | | | | | | | | fork +-----+ inherited connection | +---------->|child|<--------------------------+ +-----+>> Note that the child process is not a child of the afs process, so communication of these two processes has to happen via local sockets. In order to avoid abuse of the local socket by unrelated processes, a magic cookie is created once at server startup time just before the server process forks off the AFS process. This cookie is known to the server, AFS and the child, but not to unrelated processes. There are two different kinds of commands: First there are commands that cause the server to respond with some answer such as the list of all audio files. All but the addblob commands (addimg, addlyr, addpl, addmood) are of this kind. The addblob commands add contents to the database, so they need to transfer data the other way round, from the client to the server. There is no knowledge about the server commands built into para_client, so it does not know about addblob commands. Instead, it inspects the first data package sent by the server for a magic string. If this string was found, it sends STDIN to the server, otherwise it dumps data from the server to STDOUT. Streaming protocols ~~~~~~~~~~~~~~~~~~~ A network (audio) stream usually consists of one streaming source, the _sender_, and one or more _receivers_ which read data over the network from the streaming source. Senders are thus part of para_server while receivers are part of para_audiod. Moreover, there is the stand-alone tool para_recv which can be used to manually download a stream, either from para_server or from a web-based audio streaming service. The following three streaming protocols are supported by paraslash: - HTTP. Recommended for public streams that can be played by any player like mpg123, xmms, itunes, winamp, etc. The HTTP sender is supported on all operating systems and all platforms. - DCCP. Recommended for LAN streaming. DCCP is currently available only for Linux. - UDP. Recommended for multicast LAN streaming. See the Appendix on REFERENCE(Network protocols, network protocols) for brief descriptions of the various protocols relevant for network audio streaming with paraslash. It is possible to activate more than one sender simultaneously. Senders can be controlled at run time and via config file and command line options. Note that audio connections are _not_ encrypted. Transport or Internet layer encryption should be used if encrypted data connections are needed. Since DCCP and TCP are both connection-oriented protocols, connection establishment/teardown and access control are very similar between these two streaming protocols. UDP is the most lightweight option, since in contrast to TCP/DCCP it is connectionless. It is also the only protocol supporting IP multicast. The HTTP and the DCCP sender listen on a (TCP/DCCP) port waiting for clients to connect and establish a connection via some protocol-defined handshake mechanism. Both senders maintain two linked lists each: The list of all clients which are currently connected, and the list of access control entries which determines who is allowed to connect. IP-based access control may be configured through config file and command line options and via the "allow" and "deny" sender subcommands. Upon receiving a GET request from the client, the HTTP sender sends back a status line and a message. The body of this message is the audio stream. This is common practice and is supported by many popular clients which can thus be used to play a stream offered by para_server. For DCCP things are a bit simpler: No messages are exchanged between the receiver and sender. The client simply connects and the sender starts to stream. DCCP is an experimental protocol which offers a number of new features not available for TCP. Both ends can negotiate these features using a built-in negotiation mechanism. In contrast to TCP/HTTP, DCCP is datagram-based (no retransmissions) and thus should not be used over lossy media (e.g. WiFi networks). One useful feature offered by DCCP is access to a variety of different congestion-control mechanisms called CCIDs. Two different CCIDs are available per default on Linux: - _CCID 2_. A Congestion Control mechanism similar to that of TCP. The sender maintains a congestion window and halves this window in response to congestion. - _CCID-3_. Designed to be fair when competing for bandwidth. It has lower variation of throughput over time compared with TCP, which makes it suitable for streaming media. Unlike the HTTP and DCCP senders, the UDP sender maintains only a single list, the _target list_. This list describes the set of clients to which the stream is sent. There is no list for access control and no "allow" and "deny" commands for the UDP sender. Instead, the "add" and "delete" commands can be used to modify the target list. Since both UDP and DCCP offer an unreliable datagram-based transport, additional measures are necessary to guard against disruptions over networks that are lossy or which may be subject to interference (as is for instance the case with WiFi). Paraslash uses FEC (Forward Error Correction) to guard against packet losses and reordering. The stream is FEC-encoded before it is sent through the UDP socket and must be decoded accordingly on the receiver side. The packet size and the amount of redundancy introduced by FEC can be configured via the FEC parameters which are dictated by server and may also be configured through the "sender" command. The FEC parameters are encoded in the header of each network packet, so no configuration is necessary on the receiver side. See the section on REFERENCE(Forward error correction, FEC) below. Streams with headers and headerless streams ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For OGG/Vorbis, OGG/Speex and wma streams, some of the information needed to decode the stream is only contained in the audio file header of the container format but not in each data chunk. Clients must be able to obtain this information in case streaming starts in the middle of the file or if para_audiod is started while para_server is already sending a stream. This is accomplished in different ways, depending on the streaming protocol. For connection-oriented streams (HTTP, DCCP) the audio file header is sent prior to audio file data. This technique however does not work for the connectionless UDP transport. Hence the audio file header is periodically being embedded into the UDP audio data stream. By default, the header is resent after five seconds. The receiver has to wait until the next header arrives before it can start decoding the stream. Examples ~~~~~~~~ The sender command of para_server allows to (de-)activate senders and to change the access permissions senders at runtime. The "si" (server info) command is used to list the streaming options of the currently running server as well as the various sender access lists. -> Show client/target/access lists: para_client si -> Obtain general help for the sender command: para_client help sender -> Get help for a specific sender (contains further examples): s=http # or dccp or udp para_client sender $s help By default para_server activates both the HTTP and th DCCP sender on startup. This can be changed via command line options or para_server's config file. -> List config file options for senders: para_server -h All senders share the "on" and "off" commands, so senders may be activated and deactivated independently of each other. -> Switch off the http sender: para_client sender http off -> Receive a DCCP stream using CCID2 and write the output into a file: host=foo.org; ccid=2; filename=bar para_recv --receiver "dccp --host $host --ccid $ccid" > $filename Note the quotes around the arguments for the dccp receiver. Each receiver has its own set of command line options and its own command line parser, so arguments for the dccp receiver must be protected from being interpreted by para_recv. -> Start UDP multicast, using the default multicast address: para_client sender udp add 224.0.1.38 -> Receive FEC-encoded multicast stream and write the output into a file: filename=foo para_recv -r udp > $filename -> Add an UDP unicast for a client to the target list of the UDP sender: t=client.foo.org para_client sender udp add $t -> Receive this (FEC-encoded) unicast stream: filename=foo para_recv -r 'udp -i 0.0.0.0' > $filename -> Create a minimal config for para_audiod for HTTP streams: c=$HOME/.paraslash/audiod.conf.min; s=server.foo.com echo receiver \".:http -i $s\" > $c para_audiod --config $c ------- Filters ------- A paraslash filter is a module which transforms an input stream into an output stream. Filters are included in the para_audiod executable and in the stand-alone tool para_filter which usually contains the same modules. While para_filter reads its input stream from STDIN and writes the output to STDOUT, the filter modules of para_audiod are always connected to a receiver which produces the input stream and a writer which absorbs the output stream. Some filters depend on a specific library being installed and are not compiled in if this library was not found at compile time. To see the list of supported filters, run para_filter and para_audiod with the --help option. The output looks similar to the following: Available filters: compress wav amp fecdec wmadec prebuffer oggdec aacdec mp3dec Out of these filter modules, a chain of filters can be constructed, much in the way Unix pipes can be chained, and analogous to the use of modules in gstreamer: The output of the first filter becomes the input of the second filter. There is no limitation on the number of filters and the same filter may occur more than once. Like receivers, each filter has its own command line options which must be quoted to protect them from the command line options of the driving application (para_audiod or para_filter). Example: para_filter -f 'mp3dec --ignore-crc' -f 'compress --damp 1' For para_audiod, each audio format has its own set of filters. The name of the audio format for which the filter should be applied can be used as the prefix for the filter option. Example: para_audiod -f 'mp3:prebuffer --duration 300' The "mp3" prefix above is actually interpreted as a POSIX extended regular expression. Therefore para_audiod -f '.:prebuffer --duration 300' activates the prebuffer filter for all supported audio formats (because "." matches all audio formats) while para_audiod -f 'wma|ogg:prebuffer --duration 300' activates it only for wma and ogg streams. Decoders ~~~~~~~~ For each supported audio format there is a corresponding filter which decodes audio data in this format to 16 bit PCM data which can be directly sent to the sound device or any other software that operates on undecoded PCM data (visualizers, equalizers etc.). Such filters are called _decoders_ in general, and xxxdec is the name of the paraslash decoder for the audio format xxx. For example, the mp3 decoder filter is called mp3dec. Note that the output of the decoder is about 10 times larger than its input. This means that filters that operate on the decoded audio stream have to deal with much more data than filters that transform the audio stream before it is fed to the decoder. Paraslash relies on external libraries for most decoders, so these libraries must be installed for the decoder to be included in the para_filter and para_audiod executables. The oggdec filter depends on the libogg and libvorbis libraries for example. Forward error correction ~~~~~~~~~~~~~~~~~~~~~~~~ As already mentioned REFERENCE(Streaming protocols, earlier), paraslash uses forward error correction (FEC) for the unreliable UDP and DCCP transports. FEC is a technique which was invented already in 1960 by Reed and Solomon and which is widely used for the parity calculations of storage devices (RAID arrays). It is based on the algebraic concept of finite fields, today called Galois fields, in honour of the mathematician Galois (1811-1832). The FEC implementation of paraslash is based on code by Luigi Rizzo. Although the details require a sound knowledge of the underlying mathematics, the basic idea is not hard to understand: For positive integers k and n with k < n it is possible to compute for any k given data bytes d_1, ..., d_k the corresponding r := n -k parity bytes p_1, ..., p_r such that all data bytes can be reconstructed from *any* k bytes of the set {d_1, ..., d_k, p_1, ..., p_r}. FEC-encoding for unreliable network transports boils down to slicing the audio stream into groups of k suitably sized pieces called _slices_ and computing the r corresponding parity slices. This step is performed in para_server which then sends both the data and the parity slices over the unreliable network connection. If the client was able to receive at least k of the n = k + r slices, it can reconstruct (FEC-decode) the original audio stream. From these observations it is clear that there are three different FEC parameters: The slice size, the number of data slices k, and the total number of slices n. It is crucial to choose the slice size such that no fragmentation of network packets takes place because FEC only guards against losses and reordering but fails if slices are received partially. FEC decoding in paralash is performed through the fecdec filter which usually is the first filter (there can be other filters before fecdec if these do not alter the audio stream). Volume adjustment (amp and compress) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The amp and the compress filter both adjust the volume of the audio stream. These filters operate on uncompressed audio samples. Hence they are usually placed directly after the decoding filter. Each sample is multiplied with a scaling factor (>= 1) which makes amp and compress quite expensive in terms of computing power. *amp* The amp filter amplifies the audio stream by a fixed scaling factor that must be known in advance. For para_audiod this factor is derived from the amplification field of the audio file's entry in the audio file table while para_filter uses the value given at the command line. The optimal scaling factor F for an audio file is the largest real number F >= 1 such that after multiplication with F all samples still fit into the sample interval [-32768, 32767]. One can use para_filter in combination with the sox utility to compute F: para_filter -f mp3dec -f wav < file.mp3 | sox -t wav - -e stat -v The amplification value V which is stored in the audio file table, however, is an integer between 0 and 255 which is connected to F through the formula V = (F - 1) * 64. To store V in the audio file table, the command para_client -- touch -a=V file.mp3 is used. The reader is encouraged to write a script that performs these computations :) *compress* Unlike the amplification filter, the compress filter adjusts the volume of the audio stream dynamically without prior knowledge about the peak value. It maintains the maximal volume of the last n samples of the audio stream and computes a suitable amplification factor based on that value and the various configuration options. It tries to chose this factor such that the adjusted volume meets the desired target level. Note that it makes sense to combine amp and compress. Misc filters (wav and prebuffer) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ These filters are rather simple and do not modify the audio stream at all. The wav filter is only useful with para_filter and in connection with a decoder. It asks the decoder for the number of channels and the sample rate of the stream and adds a Microsoft wave header containing this information at the beginning. This allows to write wav files rather than raw PCM files (which do not contain any information about the number of channels and the sample rate). The prebuffer filter simply delays the output until the given time has passed (starting from the time the first byte was available in its input queue) or until the given amount of data has accumulated. It is mainly useful for para_audiod if the standard parameters result in buffer underruns. Both filters require almost no additional computing time, even when operating on uncompressed audio streams, since data buffers are simply "pushed down" rather than copied. Examples ~~~~~~~~ -> Decode an mp3 file to wav format: para_filter -f mp3dec -f wav < file.mp3 > file.wav -> Amplify a raw audio file by a factor of 1.5: para_filter -f amp --amp 32 < foo.raw > bar.raw ------ Output ------ Once an audio stream has been received and decoded to PCM format, it can be sent to a sound device for playback. This part is performed by paraslash _writers_ which are described in this chapter. Writers ~~~~~~~ A paraslash writer acts as a data sink that consumes but does not produce audio data. Paraslash writers operate on the client side and are contained in para_audiod and in the stand-alone tool para_write. The para_write program reads uncompressed audio data from STDIN. If this data starts with a wav header, sample rate, sample format and channel count are read from the header. Otherwise CD audio (44.1KHz 16 bit little endian, stereo) is assumed but this can be overridden by command line options. para_audiod, on the other hand, obtains the sample rate and the number of channels from the decoder. Like receivers and filters, each writer has an individual set of command line options, and for para_audiod writers can be configured per audio format separately. It is possible to activate more than one writer for the same stream simultaneously. OS-dependent APIs ~~~~~~~~~~~~~~~~~ Unfortunately, the various flavours of Unix on which paraslash runs on have different APIs for opening a sound device and starting playback. Hence for each such API there is a paraslash writer that can play the audio stream via this API. *ALSA*. The _Advanced Linux Sound Architecture_ is only available on Linux systems. Although there are several mid-layer APIs in use by the various Linux distributions (ESD, Jack, PulseAudio), paraslash currently supports only the low-level ALSA API which is not supposed to be change. ALSA is very feature-rich, in particular it supports software mixing via its DMIX plugin. ALSA is the default writer on Linux systems. *OSS*. The _Open Sound System_ is the only API on *BSD Unixes and is also available on Linux systems, usually provided by ALSA as an emulation for backwards compatibility. This API is rather simple but also limited. For example only one application can open the device at any time. The OSS writer is activated by default on BSD Systems. *OSX*. Mac OS X has yet another API called CoreAudio. The OSX writer for this API is only compiled in on such systems and is of course the default there. *FILE*. The file writer allows to capture the audio stream and write the PCM data to a file on the file system rather than playing it through a sound device. It is supported on all platforms and is always compiled in. *AO*. _Libao_ is a cross-platform audio library which supports a wide variety of platforms including PulseAudio (gnome), ESD (Enlightened Sound Daemon), AIX, Solaris and IRIX. The ao writer plays audio through an output plugin of libao. Examples ~~~~~~~~ -> Use the OSS writer to play a wav file: para_write --writer oss < file.wav -> Enable ALSA software mixing for mp3 streams para_audiod --writer 'mp3:alsa -d plug:swmix' --- Gui --- para_gui executes an arbitrary command which is supposed to print status information to STDOUT. It then displays this information in a curses window. By default the command para_audioc -- stat -p is executed, but this can be customized via the --stat-cmd option. In particular it possible to use para_client -- stat -p to make para_gui work on systems on which para_audiod is not running. Key bindings ~~~~~~~~~~~~ It is possible to bind keys to arbitrary commands via custom key-bindings. Besides the internal keys which can not be changed (help, quit, loglevel, version...), the following flavours of key-bindings are supported: - external: Shutdown curses before launching the given command. Useful for starting other ncurses programs from within para_gui, e.g. aumix or dialog scripts. Or, use the mbox output format to write a mailbox containing one mail for each (admissible) file the audio file selector knows about. Then start mutt from within para_gui to browse your collection! - display: Launch the command and display its stdout in para_gui's bottom window. - para: Like display, but start "para_client