{"id":13575447,"url":"https://github.com/JorenSix/Olaf","last_synced_at":"2025-04-04T22:31:08.587Z","repository":{"id":40764235,"uuid":"289562557","full_name":"JorenSix/Olaf","owner":"JorenSix","description":"Olaf: Overly Lightweight Acoustic Fingerprinting is a portable acoustic fingerprinting system.","archived":false,"fork":false,"pushed_at":"2024-05-16T08:44:13.000Z","size":5859,"stargazers_count":343,"open_issues_count":8,"forks_count":33,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-03-29T20:05:44.452Z","etag":null,"topics":["acoustic-fingerprinting","audio-fingerprinting","esp32","music-information-retrieval","wasm"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JorenSix.png","metadata":{"files":{"readme":"README.textile","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-08-22T20:32:13.000Z","updated_at":"2025-03-27T13:34:46.000Z","dependencies_parsed_at":"2024-05-16T09:55:53.566Z","dependency_job_id":null,"html_url":"https://github.com/JorenSix/Olaf","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JorenSix%2FOlaf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JorenSix%2FOlaf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JorenSix%2FOlaf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JorenSix%2FOlaf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JorenSix","download_url":"https://codeload.github.com/JorenSix/Olaf/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247260468,"owners_count":20910008,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["acoustic-fingerprinting","audio-fingerprinting","esp32","music-information-retrieval","wasm"],"created_at":"2024-08-01T15:01:01.153Z","updated_at":"2025-04-04T22:31:03.576Z","avatar_url":"https://github.com/JorenSix.png","language":"C","funding_links":[],"categories":["C"],"sub_categories":[],"readme":"!https://github.com/JorenSix/Olaf/actions/workflows/make.yml/badge.svg(Olaf build and test status)!  !https://joss.theoj.org/papers/f5b4572fd51939c2ab8363e561bdb2b7/status.svg!:https://joss.theoj.org/papers/f5b4572fd51939c2ab8363e561bdb2b7\n\nh1. OLAF -  Overly Lightweight Acoustic Fingerprinting\n\nOlaf is a C application or library for content-based audio search. Olaf is able to extract fingerprints from an audio stream, and either store those fingerprints in a database, or find a match between extracted fingerprints and stored fingerprints. Olaf does this efficiently in order to be used on **embedded platforms**, traditional computers or in web browsers via WASM. \n\nPlease be aware of the patents US7627477 B2 and US6990453 and perhaps others. They describe techniques used in algorithms implemented within Olaf. These patents limit the use of Olaf under various conditions and for several regions. Please make sure to consult your intellectual property rights specialist if you are in doubt about these restrictions. If these restrictions apply, please __respect the patent holders rights__. The main aim of Olaf is to serve as a learning platform on efficient (embedded) acoustic fingerprinting algorithms.\n\nh2(#overview). Overview\n\n#  \"Why Olaf?\":#why\n#  \"Olaf on traditional computers\":#start_trad\n## \"Compilation and installation\":#compilation\n## \"Compilation with Zig\":#zig\n## \"Olaf on Windows\":#docker\n## \"Olaf on Docker\":#docker\n#  \"Olaf in the browser\":#browser\n#  \"Embedded Olaf\":#emb\n#  \"Olaf Usage\":#usage\n## \"Store fingerprints\":#store\n## \"Query fingerprints\":#query\n## \"Delete fingerprints\":#delete\n## \"Deduplicate a collection\":#dedup\n## \"Database stats\":#stats\n## \"Cache fingerprints and store cached fingerprints\":#cache\n#  \"Configuring Olaf\":#config\n#  \"Testing, evaluating and benchmarking Olaf\":#teb\n## \"Testing Olaf\":#test\n## \"Evaluating Olaf\":#eval\n## \"Benchmarking Olaf\":#benchmark\n#  \"Contribute to Olaf\":#contrib\n#  \"Olaf documentation\":#docs\n#  \"Limitations of Olaf\":#lims\n#  \"Further Reading\":#reading\n#  \"Credits\":#credits\n\nh2(#why). Why Olaf?\n\nWith respect to other audio search systems, Olaf stands out for three reasons:\n\n* Olaf runs on embedded devices. \n* Olaf is fast on traditional computers. \n* Olaf runs in the browsers. \n\nThere seem to be no lightweight acoustic fingerprinting libraries that are straightforward to run on embedded platforms. On embedded platforms memory and computational resources are severely limited. Olaf is written in portable C with these restrictions in mind. Olaf mainly targets 32-bit ARM devices such as some Teensy's, some Arduino's and the ESP32. Other modern __embedded platforms__ with similar specifications and should work as well.\n\nOlaf, being written in portable C, also targets __traditional computers__. There, the efficiency of Olaf makes it run fast. On embedded devices reference fingerprints are stored in memory. On traditional computers fingerprints are stored in a high-performance key-value-store: LMDB. LMDB offers an a B+-tree based persistent storage ideal for small keys and values with low storage overhead.\n\nOlaf works in __the browser__. Via Emscripten Olaf can be compiled to \"WASM\":https://en.wikipedia.org/wiki/WebAssembly. This makes it relatively straightforward to combine the capabilities of the \"Web Audio API\":https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API and Olaf to create browser based audio fingerprinting applications.\n\n!./docs/olaf_in_browser.png(Olaf in the browser)!\nOlaf running in a browser\n\nOlaf was featured on \"hackaday\":https://hackaday.com/2020/08/30/olaf-lets-an-esp32-listen-to-the-music/. There is also a small discussion about Olaf on \"Hacker News\":https://news.ycombinator.com/item?id=24292817.\n\n\nh2(#start_trad). Olaf on traditional computers\n\nTo use Olaf @ffmpeg@ and @ruby@ need to be installed on your system. While the core of Olaf is in pure c, a Ruby script provides an easy to use interface to its capabilities. The Ruby script converts audio (with @ffmpeg@), parses command line arguments and reports results in a readable format.\n\nTo install ffmpeg and ruby on a Debian like system: @apt-get install ffmpeg ruby@. On macOS ruby is available by default and @ffmpeg@ can be installed with \"homebrew\":https://brew.sh/ by calling @brew install ffmpeg@.\n\n\nh3(#compilation). Compilation and installation\n\nTo compile the version with a key value store for traditional computers use the following. By default the makefile uses @gcc@ set to the C11 standard. Other compilers compliant with the C11 standard work equally well. Make sure @gcc@ is installed correctly or modify the Makefile for your compiler of choice. Compilation and installation:\n\n\u003cpre\u003e\n#sudo apt-get install ffmpeg ruby\ngit clone https://github.com/JorenSix/Olaf\ncd Olaf\nmake\nsudo make install\n\u003c/pre\u003e\n\nBy default, a directory named @.olaf@ is created in the current user home directory. The command line script is installed to @/usr/local/olaf@, which is assumed to be on the user's path.\n\nh3(#zig). Compilation with Zig\n\nAlternatively you can build Olaf with \"zig\":https://ziglang.org/. Zig is a programming language which also ships with a c compiler. In this project Zig is employed as an easy to use cross-compiler. \n\nA @zig.build@ file is provided. Just call \"zig build\" to compile for your platform. On an M1 mac it gives the following:\n\n\u003cpre\u003e\nzig build\nfile zig-out/bin/olaf_c # Mach-O 64-bit executable arm64\n\u003c/pre\u003e\n\nThe power of Zig is, however, more obvious when an other target is provided. For a list of platforms, please consult the output of @zig targets@. To build a windows executable run the following commands.\n\n\u003cpre\u003e\nzig build -Dtarget=x86_64-windows-gnu -Drelease-small\nfile zig-out/bin/olaf_c.exe # PE32+ executable (console) x86-64, for MS Windows\n\u003c/pre\u003e\n\nZig also supports WebAssembly as a target platform as an alternative to Emscripten. The @zig.build@ file includes a conditional to build the memory db for WASM. To get a WASM binary call the following:\n\n\u003cpre\u003e\nzig build -Dtarget=wasm32-wasi-musl -Drelease-small\nfile zig-out/bin/olaf_c.wasm #WebAssembly (wasm) binary module version 0x1 (MVP)\n\u003c/pre\u003e\n\nh3(#win). Olaf on Windows\n\nOlaf has been designed with a UNIX like environment in mind but also works on Windows.  A pre-built windows executable can be found in the @pre-built@ folder. There is additional \"documentation for running Olaf on Windows\":pre-built/README.textile.\n\nh3(#docker). Olaf on Docker\n\nOlaf can be containerized with \"Docker\":https://www.docker.com/. The provided Dockerfile is based on \"Alpine linux\":https://www.alpinelinux.org/ and installs only the needed requirements. A way to build the container and run Olaf:\n\n\u003cpre\u003e\ndocker build -t olaf:1.0 .\nwget \"https://filesamples.com/samples/audio/mp3/sample3.mp3\"\ndocker run -v $HOME/.olaf/docker_dbs:/root/.olaf -v $PWD:/root/audio olaf:1.0 olaf store sample3.mp3\ndocker run -v $HOME/.olaf/docker_dbs:/root/.olaf -v $PWD:/root/audio olaf:1.0 olaf stats\n\u003c/pre\u003e\n\nIn this case the @$HOME/.olaf/docker_dbs@ is mapped to @/root/.olaf@ in the container to store the database. The audio enters the system via a mapping of @$PWD@ to @/root/audio@ in the container, which is also the work directory in the container. So relative paths with respect to @$PWD@ of the host can be resolved in the container, absolute paths can not.\n\n\nh2(#browser). Olaf in the browser\n\n\nTo compile Olaf to WASM the @emcc@ compiler from Emcripten is used. Make sure \"Emscripten is correctly installed\":https://emscripten.org/docs/getting_started/downloads.html and run the following:\n\n\u003cpre\u003e\nmake web\n\npython3 -m http.server --directory wasm #start a web browser\nopen \"http://localhost:8000/spectrogram.html\" #open the url in standard browser\n\u003c/pre\u003e\n\nNote that the web version does not use a key value store but a list of hashes stored in a header-file. See below for more info.\n\n\nh2(#emb). Embedded Olaf\n\nOlaf is has been tested on the ESP32 microcontroller. Other, similar microcontroller might work as well. The embedded version does not use a key value store but a list of hashes stored in a @.h@ header file. This header file is the fingerprint index. \n\nThe 'index' or header file can be created on a computer to contain fingerprints extracted from audio. To create this header file do the following:\n\n\u003cpre\u003e\nmake mem\nolaf to_raw your_audio_file.mp3\nbin/olaf_mem store olaf_audio_your_audio_file.raw \"arandomidentifier\" \u003e your_header_file.h\n\u003c/pre\u003e\n\nTo test and debug this header file, use the @mem@ version of Olaf on your computer. The ESP32 version is basically the same as the @mem@ version, only the audio comes from microphone input and not from a file.\n\n\nh2(#usage). Olaf Usage \n\nOn traditional computers, Olaf provides a _command line interface_ it can be called using @olaf sub-application [argument...]@. For each task Olaf has to perform, there is a sub-application. There are sub-applications to store fingerprints, to query audio fragments,... . A typical interaction with Olaf could look like this:\n\n!./docs/olaf_interaction.svg(Olaf interaction)!\n\nIn a more copy-paste friendly way the following demonstrates example use of Olaf. In the example, first a dataset is downloaded then all audio files in a folder are indexed. Then statistics about the index are printed. Finally a folder is deduplicated: the duplicates material in a folder are identified and the duplicate is removed. \n\n\u003cpre\u003e\ngit clone https://github.com/JorenSix/Olaf\ncd Olaf\nmake \u0026\u0026 make install\nruby eval/download_dataset.rb\n\n#store all audio in a folder and execute a query\nolaf store dataset/ref\nolaf query dataset/queries/1051039_34s-54s.mp3\n\n#print statistics of the index:\nolaf stats\n\n#Deduplication of a folder with duplicate material\nffmpeg -i dataset/ref/173050.mp3 dataset/ref/173050_dup.ogg\nolaf dedup dataset/ref\n\n#delete the duplicate from the index:\nolaf delete dataset/ref/173050_dup.ogg\nrm  dataset/ref/173050_dup.ogg\n\u003c/pre\u003e\n\n\nh3(#store). Store fingerprints\n\nThe store command extracts fingerprints from an audio file and stores them in a reference database. The incoming audio is decoded and resampled using @ffmpeg@. @ffmpeg@ needs to be installed on your system and available on the path. \n\n\u003cpre\u003e\nolaf store audio_item...\n\u003c/pre\u003e\n\nThe @audio_item@ can be:\n# An audio file: @olaf store audio.mp3@, if the audio file contains multiple channels they are mixed to a mono.\n# A video file. The __first audio stream__ is extracted from the video container and used as input: @olaf store video.mkv@\n# A folder name: Olaf attempts to __recursively__ find all audio files within the folder. It does this with a limited allowlist of known audio file name extensions. @olaf store /home/user/Music@\n# A text file: The text file should contain a list of file names. The following commands recursively finds all mp3 within the current directory and subsequently stores them in the reference database.\n \n\u003cpre\u003e\nfind . -name \"*.mp3\" \u003e list.txt\nolaf store list.txt\n\u003c/pre\u003e\n\nInternally each audio stream is given an identifier using a one time \"Jenkins Hash\":https://en.wikipedia.org/wiki/Jenkins_hash_function function. This identifier is returned when a match is found. A list connecting these identifiers to file names is also stored automatically.\n\nh3(#query). Query fingerprints\n\nThe query command extracts fingerprints and matches them with the database:\n\n\u003cpre\u003e\nolaf query [–-threads n] [–-fragmented] [--no-identity-match] query.opus\n\u003c/pre\u003e\n\nThe query command has several options.\n\n__--threads n__  tells Olaf to use multiple threads to query the index. This can significantly speed up matching if multiple cores are available on your system.\n\n__--fragmented__  this splits query file into steps of x seconds. When working in steps of 5 seconds, then the first five seconds are matched with the reference database and matches are reported. Subsequently it goes on with the next 5 seconds and so forth. This is practical if an unsegmented audio file needs to be matched with the reference database. \n\n__--no-identity-match__ If the query is present in the index it obviously matches itself. This option prevents identity matches to be reported. This is useful for deduplication.\n\nTo query audio coming from the microphone there is the @olaf microphone@ command.  It uses ffmpeg to access the default microphone. See \"the @ffmpeg@ input devices docs for your platform:\" http://www.ffmpeg.org/ffmpeg-devices.html#Input-Devices\n\n\u003cpre\u003effmpeg -f avfoundation -list_devices true -i \"\"\u003c/pre\u003e\n\u003cpre\u003effmpeg -f avfoundation -i \"none:default\" -ac 1 -ar 16000 -f f32le -acodec pcm_f32le pipe:1 | olaf query \u003c/pre\u003e\n\n\nh3(#delete). Delete fingerprints\n\nDeletion of fingerprints is similar to adding prints:\n\n\u003cpre\u003eolaf delete item.mp3\u003c/pre\u003e\n\nNote that it is currently unclear what the performance implications are when adding and removing many items to the db. In other words: how balanced the B+ tree remains with many leaves removed. To make sure the tree remains balanced it is always an option to clear the database and re-index the audio:\n\n\u003cpre\u003eolaf clear\u003c/pre\u003e\n\nThe clear command deletes the database and optionally clears the folder with cached fingerprints. It requests permission before deleting. To force deletion the @-f@ flag can be used: @olaf clear -f@.\n\nh3(#dedup). Deduplicate a collection\n\nThis command finds duplicate audio content in a folder. First each audio file is stored in the reference database. Next each file is used as a query and matched with the reference database. The file should, evidently, match itself but self-matches are ignored, leaving only duplicates.\n\nA duplicate means that audio from the original is found in another file. The start and stop times of the found fragment are reported. If the match reports a start of nearly zero and a duration similar to the duration of the original audio file then a 'full duplicate' is found: it is almost certainly the same exact track. If only a couple of seconds are reported it means that only a couple of seconds of the original audio are found in the duplicate.\n\n\u003cpre\u003e\n\tolaf dedup [–-threads n] [–-fragmented] field_recordings/archive\n\u003c/pre\u003e\n\n__--threads n__  tells Olaf to use multiple threads to query the index. This can significantly speed up matching if multiple cores are available on your system.\n\n__--fragmented__  this tells Olaf to split the query file into steps of x seconds during matching. When working in steps of 5 seconds, then the first five seconds are matched with the reference database and matches are reported. Subsequently it goes on with the next 5 seconds and so forth. This is practical for partial matches with the reference database.\n\nh3(#stats). Database stats\n\nTo get statistics on the database use @stats@. It prints information on the b-tree structure backing the storage.\n\n\u003cpre\u003e\nolaf stats\n\u003c/pre\u003e\n\nh3(#cache). Cache fingerprints and store cached fingerprints\n\nCaching prints can be practical to speed up indexing. Olaf is single threaded mainly for use on embedded platforms. Additionally, the data storage of Olaf only allows one write thread (multiple readers are allowed). However, on more powerful computing machinery it might be of interest to use multiple cores to extract fingerprints. This can speed up indexing significantly. \n\nThe way around this is to cache fingerprints to a file with all available cores - or multiple machines - and later store all prints in the index.\n\n\u003cpre\u003e\nolaf cache [--threads n] *.mp3\nolaf store_cached\n\u003c/pre\u003e\n\nNote that for multi-threading to work, the @threach@ ruby gem is required. Install this with @gem install threach@. Also a default is the storage place for cached items: @~/.olaf/cache@. These default can be changed in the @/usr/local/bin/olaf@ ruby file. The configuration can be found at the top.\n\nh2(#config). Configuring Olaf\n\nOlaf has a number of configuration parameters. Currently these are done during compile time in the @olaf_config.c@ file. This is to avoid changing configuration at runtime which could result in an index being not compatible with fingerprints extracted from a query (with different configuration parameters).\n\nThe configuration includes the amount of fingerprints extracted, the location of the data directory, configuration related to matching, ... Each configuration setting has a small description. There is a default configuration for @mem@, @web@ and @default@ cases which slightly differ.\n\nThe olaf.rb Ruby script also contains a few settings related to how audio is decoded, where data is expected, the number of threads which can be used,... To change these settings, edit the script itself (typically located at @/usr/local/bin/olaf@. Changes to configuration there are immediately applied.\n\nh2(#teb). Testing, Evaluating and Benchmarking Olaf\n\nThe tests check __whether Olaf works__. The evaluation verifies __how well__ Olaf works. The benchmark checks __how fast__ Olaf works and how it deals with scalability.\n\n\"More details on testing, evaluating and benchmarking Olaf\":./eval can be found in the separate page. There information on memory use can be found together with a comparison against Panako.\n\nh3(#test). Testing Olaf\n\nThe first thing this checks is whether Olaf compiles correctly. Afterwards, a small dataset is indexed and some queries are fired. The result of the queries is evaluated for correctness. Also the memory version of Olaf is checked. To run this yourself, with Ruby, @ffmpeg@ and @ffprobe@ installed:\n\n\u003cpre\u003e\ngit clone https://github.com/JorenSix/Olaf\ncd Olaf\nmake \u0026\u0026 make install\nruby eval/olaf_functional_tests.rb\n\u003c/pre\u003e\n\nLess interesting are the unit tests, these are mainly of interest for developing Olaf. The unit test can be compiled with `make test` and ran with `./bin/olaf_tests`.\n\nh3(#eval). Evaluating Olaf\n\n In the @eval@ folder there is an evaluation script which takes a folder as input and stores and evaluates queries with several modifications. \"SoX\":https://sox.sourceforge.net/ needs to be available on the system for this to work.\n\n\u003cpre\u003e\nruby eval/olaf_evaluation.rb /folder/with/music\n\u003c/pre\u003e\n\nh3(#benchmark). Benchmarking Olaf\n\nWith the script a folder of audio files is stored and it is registered how long it takes to store 64, 128, 256, 512,... files. If run with the \"FMA full\":https://github.com/mdeff/fma dataset a total of more than 200 days of audio are stored at a rate of just under 2000 times real-time with a 96 CPU-core system. An interpretation of the graph is that indexing remains linear on larger datasets. At every doubling of the database the \"query performance\":./eval/olaf_benchmark/olaf_benchmark_query.svg is also checked. Run the benchmark yourself:\n\n\u003cpre\u003e\nruby eval/olaf_benchmark/olaf_benchmark.rb /folder/with/music\n\u003c/pre\u003e\n\n!./eval/olaf_benchmark/olaf_benchmark.svg(Olaf indexing)!\n\n\nh2(#contrib). Contribute to Olaf\n\nThere are several ways to contribute to Olaf. The first is to use Olaf and report issues or feature requests using the Github Issue tracker. Bug reports are greatly appreciated, but keep in mind the note below on responsiveness.\n\nAnother way to contribute is to dive into the code, fork and improve Olaf yourself. Merge requests with additional documentation, bug fixes or new features will be handled and end up in the main branch if correctness, maintainability and simplicity are kept in check. However, keep in mind the note below:\n\nMy time to spend on Olaf is limited and goes in activity bursts. If an issue is raised it might take a couple of months before I am able to spend time on it during the next burst of activity. A period of relative silence does not mean your feedback / pull request is not greatly valued!\n\nh2(#docs). Olaf documentation\n\nThe \"documentation of Olaf\":https://jorensix.github.io/Olaf is generated with \"doxygen\":http://doxygen.nl and can be consulted on github via the gh-pages branch. \n\nh2(#lims). Limitations of Olaf\n\n* \u003cdel\u003eCurrently a complete audio file is read in memory in order to process it. While the algorithm allows streaming, the current implementation does not allow to store incoming streams.\u003c/del\u003e Now you can choose whether to compile in the single or stream reader: choose either @olaf_reader_single.c@ or @olaf_reader_stream.c@, which is a bit slower. \n* Only one write process: LMDB limits the number of processes that can write to the key-value store to a single process. Attempting to write to the key-value store while an other write-process is busy should put the process automatically in a wait state untile the write lock is released (by the other process). Reading can be done frome multiple processes at the same time. \n* Audio decoding is done externally. The core of Olaf does fingerprinting. ffmpeg or similar audio decoding software is required to decode and resample various audio formats.\n* \u003cdel\u003eRemoving items from the reference database is currently not supported. The underlying database does support deletion of items so it should be relatively easy to add this functionality.\u003c/del\u003e\n* Performance implications when removing many items from the database are currently unclear. In other words: how balanced does the B+tree remain when removing many leaves.\n* Olaf is single threaded. The main reasons are simplicity and limitations of embedded platforms. The single threaded design keeps the code simple. On embedded platforms with single core CPU's multithreading makes no sense. \nOn traditional computers there might be a performance gain by implementing multi-threading. However, the time spent on decoding audio and storing fingerprints is much larger than analysis/extraction so the gain might be limited. As an work-around multiple processes can be used simultaniously to query the database.\n* The limitation of the number of tracks that can be indexed and queried on a single computer is not known. Olaf has been used to index and query the \"fma_full dataset\":https://github.com/mdeff/fma. This dataset contains 100 000 tracks totaling more than 340 days of audio. The dataset, around 800GB of mp3s, were indexed in a 15GB database and query speed remained at a respectable 80 times realtime: it only takes a single second to query 80 seconds of audio. With the datastructure having logaritmic complexity the limit of the number of songs per pc might be a couple of times higher.   \n\nh2(#reading). Further Reading\n\nSome relevant reading material about (landmark based) acoustic fingerprinting. The order gives an idea of relevance to the Olaf project. \n\n# Wang, Avery L. __An Industrial-Strength Audio Search Algorithm__ (2003)\n# Six, Joren and Leman, Marc \"__Panako - A Scalable Acoustic Fingerprinting System Handling Time-Scale and Pitch Modification__\":http://www.terasoft.com.tw/conf/ismir2014/proceedings/T048_122_Paper.pdf (2014)\n# Cano, Pedro and Batlle, Eloi and Kalker, Ton and Haitsma, Jaap __A Review of Audio Fingerprinting__ (2005)\n# Arzt, Andreas and Bock, Sebastian and Widmer, Gerhard __Fast Identification of Piece and Score Position via Symbolic Fingerprinting__ (2012)\n# Fenet, Sebastien and Richard, Gael and Grenier, Yves __A Scalable Audio Fingerprint Method with Robustness to Pitch-Shifting__ (2011)\n# Ellis, Dan and Whitman, Brian and Porter, Alastair __Echoprint - An Open Music Identification Service__ (2011)\n# Sonnleitner, Reinhard  and Widmer, Gerhard __Quad-based Audio Fingerprinting Robust To Time And Frequency Scaling__ (2014)\n# Sonnleitner, Reinhard  and Widmer, Gerhard \"__Robust Quad-Based Audio Fingerprinting__\":http://dx.doi.org/10.1109/TASLP.2015.2509248 (2015)\n\nThe programming style of Olaf attempts to use an OOP inspired way to organize code and divide responsibilities and interfaces.  For more information see on this style consult this document about \"OOP in C\":https://www.state-machine.com/doc/AN_OOP_in_C.pdf. Also of interest is the \"Modern C book by Jens Gustedt\":https://modernc.gforge.inria.fr/.\n\nh2(#credits). Credits\n\n* \"PFFFT\":https://bitbucket.org/jpommier/pffft/src/default/  a pretty fast FFT library. BSD license\n* \"LMDB\":https://symas.com/lmdb/ \"Lightning Memory-Mapped Database\":https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database, a fast key value store with a permissive software license (the OpenLDAP Public License) by Howard Chu.\n* \"Hash table\":https://github.com/fragglet/c-algorithms and dequeue by Simon Howard, ISC lisence\n* \"libsamplerate-js\":https://github.com/aolsenjazz/libsamplerate-js the browser based version of Olaf uses a WASM build of an audio resampling library \"SRC\":http://www.mega-nerd.com/SRC/ which is BSD licensed. @libsamplerate-js@ is MIT licensed.\n\nOlaf by Joren Six at IPEM, Ghent University.\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJorenSix%2FOlaf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FJorenSix%2FOlaf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJorenSix%2FOlaf/lists"}