Skip to content
This repository

Folve - seamlessly convolving audio file fuse filesystem

branch: master
Octocat-spinner-32 demo-filters o Add simple echo example. September 23, 2012
Octocat-spinner-32 COPYING o legalese: add COPYING, provide "Appropriate Legal Notices" and September 23, 2012
Octocat-spinner-32 INSTALL.md o now really switch to PREFIX September 30, 2012
Octocat-spinner-32 Makefile o Move SndFileHandler as ConvolveFileHandler out of folve-filesystem.cc October 12, 2012
Octocat-spinner-32 README.md o Write PID file. October 25, 2012
Octocat-spinner-32 buffer-thread.cc o Reduce lock contention. October 13, 2012
Octocat-spinner-32 buffer-thread.h o add missing include for off_t October 14, 2012
Octocat-spinner-32 conversion-buffer.cc o Allow to have a different amount of input vs. output channels. November 18, 2012
Octocat-spinner-32 conversion-buffer.h o Allow to have a different amount of input vs. output channels. November 18, 2012
Octocat-spinner-32 convolve-file-handler.cc o Fix channel availability test. November 19, 2012
Octocat-spinner-32 convolve-file-handler.h o Allow to have a different amount of input vs. output channels. November 18, 2012
Octocat-spinner-32 file-handler-cache.cc o Only have one pre-buffer thread to only use at most one more core October 08, 2012
Octocat-spinner-32 file-handler-cache.h o Only have one pre-buffer thread to only use at most one more core October 08, 2012
Octocat-spinner-32 file-handler.h o add include for off_t October 14, 2012
Octocat-spinner-32 folve-filesystem.cc o add include for off_t October 14, 2012
Octocat-spinner-32 folve-filesystem.h o add include for off_t October 14, 2012
Octocat-spinner-32 folve-main.cc o don't trip if PID file cannot be written. October 25, 2012
Octocat-spinner-32 pass-through-handler.cc o file size better represented with off_t than size_t December 09, 2012
Octocat-spinner-32 pass-through-handler.h o file size better represented with off_t than size_t December 09, 2012
Octocat-spinner-32 processor-pool.cc o Fix channel availability test. November 19, 2012
Octocat-spinner-32 processor-pool.h o Remove TODO: pass out detailed error msg when failing to October 06, 2012
Octocat-spinner-32 sound-processor.cc o Fix channel availability test. November 19, 2012
Octocat-spinner-32 sound-processor.h o Allow to have a different amount of input vs. output channels. November 18, 2012
Octocat-spinner-32 status-server.cc o Write timestamp of last access with -D October 13, 2012
Octocat-spinner-32 status-server.h Provide html status as well as /folve-status.html October 06, 2012
Octocat-spinner-32 util.cc o more include missing. October 14, 2012
Octocat-spinner-32 util.h o Only have one pre-buffer thread to only use at most one more core October 08, 2012
Octocat-spinner-32 zita-audiofile.cc o .. September 14, 2012
Octocat-spinner-32 zita-audiofile.h o add basic zita filter. September 09, 2012
Octocat-spinner-32 zita-config.cc o legalese: add COPYING, provide "Appropriate Legal Notices" and September 23, 2012
Octocat-spinner-32 zita-config.h o Fix channel availability test. November 19, 2012
Octocat-spinner-32 zita-fconfig.cc o legalese: add COPYING, provide "Appropriate Legal Notices" and September 23, 2012
Octocat-spinner-32 zita-sstring.cc o add basic zita filter. September 09, 2012
Octocat-spinner-32 zita-sstring.h o add basic zita filter. September 09, 2012
README.md

Folve - FUSE convolve

Folve is a FUSE filesystem that convolves audio files on-the-fly.

Overview

The Folve FUSE filesystem takes a path to a directory of FLAC files, and provides these files at a mount point. Other file formats than FLAC should work as well, but not all are working well for streaming yet (and before you ask: MP3 is not supported. Use Ogg/Vorbis as it is patent free and provides better quality than MP3).

When a FLAC file is accessed through the mount point, Folve automatically convolves its original counterpart on-the-fly with a Finite Impulse Response (FIR) filter. The FIR filter is based on the jconvolver convolution engine.

Folve can use the same filter configuration files that jconvolver uses. Folve requires a naming scheme, described later, for these files.

In essence, Folve provides a filesystem that convolves files as a media server or application reads them; many media servers or applications do not provide an independent convolve option, but they all can read files.

Filesystem accesses are optimized for streaming. If files are read sequentially, we only need to convolve whatever is requested, which minimizes CPU use if you do not need the full file. Simply playing a file in real-time will use very little CPU (on my notebook ~3% on one core). So this should work as well on low-CPU machines (like NAS servers; have not tried that yet).

Because input and output files are compressed, we cannot predict what the relationship between file-offset and sample-number is; so skipping forward requires to convolve everything up to the point (the convolver is pretty fast though, so you'll hardly notice).

While indexing, some media servers try to skip to the end of the file (do not know why, to check if the end is there ?), so there is code that detects this case so that we do not end up convolving whole files just for this. Also, some media servers continually watch the file size while playing, so we adapt predictions of the final filesize depending on the observed compression ratio.

The files are decoded with libsndfile, convolved, and re-encoded with libsndfile. Libsndfile is very flexible in reading/writing all kinds of audio files, but the support for rich header tags is limited. To not loose information from the FLAC headers when indexing Folve-served files with a media server, Folve extracts and serves the headers from the original files before continuing with the convolved audio stream.

Folve has been tested with some players and media servers (and works around bugs in these). Still, this is the first version made public, so expect rough edges. Please report observations with particular media servers or provide patches through github https://github.com/hzeller/folve.

This project is notably based on

Compiling on Ubuntu (tested on 11.10 and 12.04)

This requires the latest versions of some development libraries.

sudo apt-get install libsndfile-dev libflac-dev libzita-convolver-dev \
                     libfuse-dev libmicrohttpd-dev
make
sudo make install

For hints on how to compile on older systems see INSTALL.md.

(TODO: debian package)

Let's test it!

Folve requires at least two parameters: the directory where your original FLAC files reside and the mount point of this filesystem.

Also, do be useful, you need to supply the directory that contains filter directories with the -C <config-dir> option. Very useful is the -p <port> that starts a HTTP status server. Let's use some example filters from this distribution; if you are in the Folve source directory, you find the directory demo-filters/ that contains subdirectories with filters. If we pass this directory to folve, folve will search in this directory for named filters:

mkdir /tmp/test-mount
./folve -C demo-filters -p 17322 -f \
        /path/to/your/directory/with/flacs /tmp/test-mount

Now you can access the fileystem under that mount point; it has the same structure as your original directory.

mplayer /tmp/test-mount/foo.flac

Folve provides a HTTP status page; have a look at

http://localhost:17322/

(or whatever port you chose with the -p 17322 option) There you can switch the filter; after you changed it in the UI, re-open the same FLAC file with your media player: you'll hear the difference.

To terminate this instance of folve, you can just press CTRL-C as we've run it in the foreground (the -f option did this). In real life, you'd run it as daemon (without -f option), so then you can stop the daemon and unmount the directory with the fusermount command:

fusermount -u /tmp/test-mount

Filter Configuration

With the -C option, you give folve a directory in which it looks for subdirectories with named filter configurations.

Filters are WAV files containing an impulse response (IR). This is used by jconvolver's convolution engine to create a Finite Impulse Response (FIR) filter and process your audio.

Text configuration files refer to these WAV files and add parameters such as filter gain and channel mapping. These configuration files are read by Folve. See the samples in the demo-filters/ directory. The README.CONFIG in the jconvolver project describes the details of the configuration format.

Since the filter is dependent on the sampling rate, we need to choose the right filter depending on the input file we see. This is why you give Folve a whole configuration directory: it can contain multipe files depending on sample rate.

The files in the configuration directory need to follow a naming scheme to be found by Folve. Their naming is:

filter-<samplerate>-<channels>-<bits>.conf   OR
filter-<samplerate>-<channels>.conf          OR
filter-<samplerate>.conf

So if you have FLAC files with 44.1kHz, 16 bits and 2 channel stero, you need a filter configuration named one of these (in matching sequence):

/filter/dir/filter-44100-2-16.conf            OR
/filter/dir/filter-44100-2.conf               OR
/filter/dir/filter-44100.conf

The files are searched from the most specific to the least specific type.

The Folve filesystem will determine the samplerate/bits/channels and attempt to find the right filter in the filter directory. If there is a filter, the output is filtered on-the-fly, otherwise the original file is returned.

(I am looking for filter construction tools on Linux; if you know some, please let me know.)

General usage:

usage: folve [options] <original-dir> <mount-point-dir>
Options: (in sequence of usefulness)
  -C <cfg-dir> : Convolver base configuration directory.
                 Sub-directories name the different filters.
                 Select on the HTTP status page.
  -p <port>    : Port to run the HTTP status server on.
  -r <refresh> : Seconds between refresh of status page;
                 Default is 10 seconds; switch off with -1.
  -g           : Gapless convolving alphabetically adjacent files.
  -b <KibiByte>: Predictive pre-buffer by given KiB (64...16384).
  -O <factor>  : Oversize: Multiply orig. file sizes with this. Default 1.25.
  -o <mnt-opt> : other generic mount parameters passed to FUSE.
  -P <pid-file>: Write PID to this file.
  -D           : Moderate volume Folve debug messages to syslog,
                 and some more detailed configuration info in UI
  -f           : Operate in foreground; useful for debugging.
  -d           : High volume FUSE debug log. Implies -f.
  -R <file>    : Debug readdir() & stat() calls. Output to file.

If you're listening to classical music, opera or live-recordings, then you certainly want to switch on gapless convolving with -g. If a file ends with not enough samples to fill the FIR filter input, the gap is bridged by including the first samples of the alphabetically next file in that directory -- and the result is split between these two files.

Misc

To manually switch the configuration from the command line, you can use wget or curl, whatever you prefer:

wget -q -O/dev/null http://localhost:17322/settings?f=highpass
curl http://localhost:17322/settings?f=SantaLucia

The parameter given to f= is the name of the subdirectory in your base configuration directory. An empty string is no filter, i.e. 'pass through'. (And no, there is no security built-in. If you want people from messing with the configuration of your Folve-daemon, do not use -p <port> :)).

Something went wrong with that request. Please try again.