rust · webassembly · ASAM MDF v4 + v3

A fast, reliable reader for ASAM MDF files.

falcon_mdf reads the measurement files recorded by automotive and industrial data loggers — as a Rust crate, through Python bindings, in a desktop viewer, and right here in your browser.

Abstract

Values are decoded exactly as recorded — typed samples, conversion rules and invalidation bits included. A file that cannot be read is reported by name, never decoded incorrectly. On the tracked benchmark corpus it is typically about four times faster than asammdf, the Python reference; the published summary includes the compressed files where the two are at parity.

nothing to install · nothing is uploaded · a sample log is bundled

The browser viewer plotting PWMFiltered, channel3 and dwordCounter from a compressed Vector MF4 file
Figure 1: the playground opening Vector_EmbeddedCompressed.MF4 — 28.1 KB, two groups, eight channels, deflate-compressed.

The playground

The playground is the crate itself, compiled to WebAssembly — the same decoder the Rust build uses. These are real captures of it working on a Vector CANape recording bundled with the site.

Cursor A and cursor B placed on the plot with a region statistics strip above

Cursors, and the stats between them

Click to place cursor A, shift-click for cursor B: the strip above the plot reports min, max, mean and Δt for every plotted channel between them. Between clicks, the readout follows the pointer sample by sample.

  • cursors A / B
  • region stats
  • live readout
open this view in the playground →

Figure 2: the region between the cursors, summarised per channel.

The sample table listing time and PWMFiltered values row by row

Every sample, straight from the file

The table pages through a channel’s raw samples — integer counts stay integers, and a missing value shows as a gap instead of being bridged by interpolation. What the file recorded is what the row shows.

  • raw samples
  • typed values
  • search modes
open this view in the playground →

Figure 3: the sample table paging through PWMFiltered’s raw samples.

An X-Y plot of channel3 against dwordCounter drawn below the time plot

Value against value

Any two plotted channels form an X-Y plot. Y is sampled at X’s own timestamps, so the pair stays accurate even when the channels do not share a master time axis.

  • value vs value
  • resampled on X
  • cursor sync
open this view in the playground →

Figure 4: channel3 against dwordCounter, Y sampled at X’s own timestamps.

Measured against asammdf

Reproducible benchmarks, warm-cache medians, per-file timings committed beside the code — so you can verify the numbers on your own hardware.

3.9×

decoding the reference OBD2 CANedge log — 326,623 samples — against asammdf

4.8×

the same file, whole read: structure to samples, against asammdf’s select()

0

panics, aborts or hangs across 1,200 mutated files — truncations, corrupt links, zeroed fields

76

files in the tracked benchmark corpus, per-file timings committed beside the code

Medians of warm-cache runs, 3–5 each. On some vendor-compressed files performance is at parity with asammdf — the benchmark summary publishes those files too.

What is MDF?

A short primer on the format this whole page reads — what a recording contains, and where the standard is maintained.

MDF, the Measurement Data Format, is the binary file format maintained by ASAM for storing recorded measurement data: signal values sampled over time, saved together with everything needed to interpret them — physical units, conversion rules, master time axes, invalidation bits, comments and attachments. It is the de-facto standard for measurement and calibration systems in automotive development, where data loggers and ECU tools record internal ECU variables and CAN/LIN bus traffic; the same files then serve post-measurement processing, off-line evaluation and long-term archiving. One file holds several channel groups, each with its own time base, so a single recording can carry a 1 kHz engine trace next to slow diagnostic frames. Version 4 recordings use the .mf4 extension; the older version 3 lineage appears as .dat or .mdf.

References: the ASAM MDF standard page, which publishes the specification itself; ASAM’s MDF wiki; and a hands-on introduction to MF4 files.

What it reads

Complete support for the formats your loggers produce, sorted and unsorted. Every claim here is exercised by the test suite.

formats

MDF 4.x (4.0, 4.1, 4.2) and MDF 3.x (2.14, 3.20, 3.30), sorted and unsorted, finished and unfinished files.

compression

Deflate always; zstd and LZ4 behind feature flags. A block whose codec is not compiled in reports itself by name instead of returning wrong bytes.

bus logs

CAN and LIN frames out of bus-logged groups, payloads decoded into physical signals against DBC, ARXML or LDF databases — multiplexing, J1939 matching and VAL_ tables included.

channels

Typed samples — integers stay integers, frame payloads stay bytes. Conversion rules, invalidation bits, array (CA) channels, variable-length data, acquisition sources.

operations

cut, resample, filter, concatenate, stack — and signal algebra that resamples onto the union of two time bases when you write speed + rpm.

export

CSV, Apache Parquet, MATLAB, HDF5, ASC and Arrow.

writing

Mf4Writer builds MF4 files from scratch: typed channels, per-sample validity, optional deflate compression.

Add it to your project

One dependency, no mandatory extras — reading a plain deflate-compressed log pulls in neither a database parser nor a second decompressor. Memory-mapped I/O by default; a buffered backend for files another process may still be writing.

$ cargo add falcon_mdf

quickstart.rs

use falcon_mdf::Mf4File;

let file = Mf4File::open("measurement.mf4")?;

if let Some(channel) = file.find_channel("VehicleSpeed") {
    let signal = file.signal(channel)?;
    let values = signal.values_f64()?;
    println!("{} samples [{}]", values.len(), signal.unit());
}

Documented limitations

Unsupported features are documented with the reason and reported at open time, so nothing fails silently and nothing is decoded incorrectly. You can plan around this list.

Open it right here

The viewer runs live on this page. Open the bundled sample or drop in your own file — decoding happens entirely in your browser, and the file never leaves your machine.

loads the viewer + sample — about 900 KB of WebAssembly, fetched once

runs locally · MDF v4 + v3 · plots, cursors, tables, DBC decoding, two-file compare