This file provides guidance to AI coding assistants when working with code in this repository.
Olaf (Overly Lightweight Acoustic Fingerprinting) is an acoustic fingerprinting system designed to run efficiently on embedded platforms, traditional computers, and in web browsers via WebAssembly. The project extracts audio fingerprints and stores/matches them against a database for content-based audio search.
- Portable C11: Core implementation in C11 for embedded compatibility
- Memory efficiency: Designed for 32-bit ARM platforms (ESP32, Teensy, Arduino)
- Multi-target: Supports embedded (memory DB), desktop (LMDB), and web (WASM)
- Patent awareness: Implementation is primarily for learning; be aware of US7627477 B2 and US6990453
The project uses two build systems:
make # Build default version with LMDB
make install # Install to /usr/local/bin
make mem # Build memory-only version (for embedded/testing)
make web # Build WebAssembly version (requires emcc)
make lib # Build shared library (libolaf.so) for Python wrapper
make test # Build and run unit tests
make clean # Clean build artifactszig build # Build CLI version with LMDB
zig build -Dcore=true # Build core C library only
zig build -Doptimize=ReleaseSmall # Optimized build
zig build run -- [args] # Build and run with arguments
zig build install-system # Install to system location
zig build -Dtarget=x86_64-windows-gnu # Cross-compile for Windows
zig build -Dtarget=wasm32-wasi-musl # Build for WebAssemblyWhen modifying build logic: The Zig build is the modern approach and should be preferred for new features.
Audio Input → Reader → Stream Processor → EP Extractor → FP Extractor → DB Writer/Matcher
↓
FFT (PFFFT)
↓
Max Filter (Peak Detection)
↓
Event Points
↓
Fingerprints
- Reader (
olaf_reader_stream.c): Streams audio data in blocks (default 1024 samples @ 16kHz) - Stream Processor (
olaf_stream_processor.c): Coordinates FFT and processing pipeline - FFT (
pffft.c): Fast Fourier Transform to convert to frequency domain - EP Extractor (
olaf_ep_extractor.c): Extracts Event Points from spectral peaks using perceptual max filtering (olaf_max_filter_perceptual_van_herk.c) - FP Extractor (
olaf_fp_extractor.c): Combines 2-3 Event Points into fingerprint hashes with time/frequency deltas - Writers/Matcher: Store fingerprints or find temporal alignment matches against database
Three implementations exist depending on target platform:
-
LMDB (
olaf_db.c): B+-tree key-value store for desktop (production)- Uses Lightning Memory-Mapped Database for persistent storage
- Supports multiple concurrent readers, single writer
- Stores fingerprint hashes as keys with (audio_id, timestamp) as values
-
Memory (
olaf_db_mem.c): In-memory array for embedded/testing- Fingerprints stored in static arrays or header files
- No persistent storage, loaded at compile time or initialization
- Used for ESP32 and similar microcontrollers with limited resources
-
WASM (
olaf_wasm.c): Similar to memory version, runs in browsers- Compiled with Emscripten (
make web) or Zig - Integrates with Web Audio API for microphone/file input
- Fingerprints pre-compiled into WASM module
- Compiled with Emscripten (
The CLI is implemented in Zig (cli/olaf_cli.zig) and wraps the C core via olaf_cli_bridge.c:
- Command structure: Modular commands in
cli/olaf_cli_commands/ - Each command exports
CommandInfostruct andexecutefunction - Configuration: JSON-based (
olaf_config.json), checked in home dir first - Audio handling: Supports ffmpeg-based decoding in utilities
- Threading:
olaf_cli_threading.zigprovides parallel processing for store/query/cache operations
Located in python-wrapper/, provides high-level Python API using CFFI:
Setup:
make lib # Build libolaf.so
pip install -r python-wrapper/requirements.txt
python python-wrapper/setup.py # Build CFFI wrapper
export LD_LIBRARY_PATH=$(pwd)/bin # Set library pathCommands:
STORE: Index audio file or numpy arrayQUERY: Find matches, returns dictionary with match detailsEXTRACT_EVENT_POINTS: Returns time/frequency pairs (debugging)EXTRACT_FINGERPRINTS: Returns fingerprint hashes with metadataEXTRACT_MAGNITUDES: Returns magnitude spectrum (visualization)
Accepts filenames or numpy arrays (mono audio @ 16kHz sample rate).
Compile-time config (src/olaf_config.c/.h): Algorithm parameters that affect fingerprint compatibility
- Audio parameters: sample rate (16kHz), block size (1024), step size (128)
- Event point extraction: filter sizes, minimum magnitude thresholds, max EPs per block
- Fingerprint generation: time/frequency distance ranges, number of EPs per FP (2-3)
- Matching parameters: search range, minimum match counts, temporal alignment thresholds
- Important: Changes to these make existing databases incompatible with new queries
- Multiple preset configs:
olaf_config_default(),olaf_config_esp_32(),olaf_config_mem(),olaf_config_test()
Runtime config (Zig CLI): Operational settings in olaf_config.json
- Database/cache paths (default:
~/.olaf/db/,~/.olaf/cache/) - Thread counts for parallel processing
- Audio file extensions allowlist
- Query fragmentation settings
- File checked in order: executable dir,
~/.olaf/olaf_config.json - Use
olaf configcommand to view current configuration
zig build test # Run all Zig unit testsThe Zig test suite (tests/olaf_tests.zig) includes:
- Unit tests: Testing C core components (config, deque, reader)
- Functional tests: CLI command testing (skeletons provided)
- Integration tests: End-to-end pipeline testing (skeletons provided)
- Benchmark tests: Performance testing (skeletons provided)
Tests automatically skip when dependencies (ffmpeg, test files) are unavailable.
make test # Build C unit tests
./bin/olaf_tests # Run C unit testsLegacy C tests in tests/olaf_tests.c test deque, max filter, and reader components.
# Recognition benchmark (indexes a fraction, queries random cuts; requires
# ffmpeg/ffprobe, optionally SoX for distortions). The test dataset is
# downloaded automatically by `zig build test`.
python3 eval/olaf_recognition_benchmark.py /folder/with/music
# Benchmark indexing and query throughput (requires only olaf + ffmpeg)
python3 eval/olaf_benchmark/olaf_benchmark.py /folder/with/musicA small tail of Ruby remains in eval/ and still requires a Ruby interpreter:
# Olaf vs Panako timing comparison (requires panako installed)
ruby eval/olaf_vs_panako.rb /folder/with/music
# Query memory profiler (requires `make mem` build + macOS /usr/bin/time -l)
ruby eval/olaf_memory_use.rb /folder/with/musicCSV result-line utilities (sort/filter/merge/check) have been ported to Python:
cat result_output.csv | python3 eval/olaf_result_utils.py sort- Create new file in
cli/olaf_cli_commands/olaf_cli_cmd_[name].zig - Export
CommandInfostruct with name, description, help, and needs_audio_files - Implement
execute(allocator: std.mem.Allocator, args: *types.Args) !void - Register in
cli/olaf_cli.zigcommands array
- Always rebuild completely:
make clean && makeorzig build - Algorithm changes in
src/may require database re-indexing - Test both desktop (LMDB) and memory versions if changing core processing
- Update configuration in
olaf_config.cif adding new parameters
For ESP32/embedded targets:
- Build memory version:
make mem - Generate header file index:
olaf to_raw audio.mp3 bin/olaf_mem store olaf_audio_audio.raw "identifier" > fingerprints.h
- Include header in ESP32 project
Zig makes cross-compilation trivial:
- Windows:
zig build -Dtarget=x86_64-windows-gnu -Doptimize=ReleaseSmall - Linux:
zig build -Dtarget=x86_64-linux-gnu - macOS ARM:
zig build -Dtarget=aarch64-macos.11.0.0-none - macOS x86:
zig build -Dtarget=x86_64-macos-gnu - WebAssembly:
zig build -Dtarget=wasm32-wasi-musl
Traditional make + emscripten for web: make web
Build and run in Docker container (Alpine Linux based):
docker build -t olaf:1.0 .
docker run -v $HOME/.olaf/docker_dbs:/root/.olaf -v $PWD:/root/audio olaf:1.0 olaf store audio.mp3
# Or with docker compose
docker compose run olaf olaf store dataset/ref/*
docker compose run olaf olaf query dataset/queries/*The C code uses OOP-inspired patterns:
- Structs with constructor/destructor:
olaf_*_new()/olaf_*_destroy() - Function pointers for polymorphism (see database interface)
- Opaque pointers in headers, implementation in .c files
- C core: Manual malloc/free, caller responsible for cleanup
- Zig CLI: Arena allocators, GPA with defer statements
- Always pair
_new()with_destroy()calls
- Core C library is single-threaded (embedded compatibility)
- Zig CLI implements multi-threading for query/store commands
- Use
--threads nflag for parallel processing on desktop
Core Algorithm:
src/olaf_config.c/h: Algorithm configuration and presetssrc/olaf_runner.c/h: Main execution coordinatorsrc/olaf_stream_processor.c/h: Audio processing pipeline coordinationsrc/olaf_ep_extractor.c/h: Event point extraction from spectral peakssrc/olaf_fp_extractor.c/h: Fingerprint generation logicsrc/olaf_fp_matcher.c/h: Temporal alignment matching algorithm
Database Implementations:
src/olaf_db.c/h: LMDB database for desktopsrc/olaf_db_mem.c: Memory database for embeddedsrc/mdb.c,src/midl.c: LMDB implementation (embedded)
CLI and Wrappers:
cli/olaf_cli.zig: Main CLI entry pointcli/olaf_cli_bridge.c/h: C bridge for Zig CLIpython-wrapper/olaf.py: Python CFFI wrapperpython-wrapper/setup.py: CFFI build script
Build System:
build.zig: Zig build configuration (preferred for new features)Makefile: Traditional build system
- LMDB: Embedded in
src/mdb.c,src/midl.c(OpenLDAP Public License) - PFFFT: Fast FFT library in
src/pffft.c(BSD license) - Hash table/queue: Simon Howard's c-algorithms in
src/hash-table.c,src/queue.c(ISC license) - ffmpeg: External tool for audio decode/resample (not linked, invoked as subprocess)
- Python 3: For evaluation/benchmark scripts (stdlib only, desktop only)
- Ruby: Only for the remaining un-ported eval scripts (
olaf_vs_panako.rb,olaf_memory_use.rb); being phased out - Emscripten: For WebAssembly builds (
make web) - libsamplerate-js: Audio resampling for browser version (MIT/BSD license)
Be aware of patents US7627477 B2 and US6990453 covering acoustic fingerprinting techniques. Olaf's primary purpose is educational and as a learning platform. Consult intellectual property specialists before production use in regions where these patents apply.