bpm-finder-tools 0.1.0

Lightweight Rust utilities and CLI for audio-file BPM analysis, tap tempo, and tempo conversion.
Documentation
  • Coverage
  • 37.21%
    16 out of 43 items documented1 out of 16 items with examples
  • Size
  • Source code size: 52.18 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 2.9 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 27s Average build duration of successful builds.
  • all releases: 27s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • wsgtcyx/bpm-finder-cargo
    1 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • wsgtcyx

bpm-finder-tools

bpm-finder-tools is a lightweight Rust utility package for audio-file BPM analysis, tap tempo analysis, BPM conversion, and practical tempo normalization. It is maintained by BPM Finder, the browser-based tool for fast and privacy-first BPM workflows.

Why this crate exists

Many music and workflow tools only need a few reliable tempo primitives:

  • Detect BPM from supported audio files
  • Estimate BPM from tap intervals
  • Convert BPM into milliseconds per beat or bar
  • Normalize half-time and double-time readings into a practical range

This crate keeps those utilities small, dependency-light, and easy to embed in Rust applications or command-line workflows.

Supported file decoding currently includes WAV, MP3, FLAC, OGG/Vorbis, and common MP4/M4A AAC or ALAC audio files.

Installation

Add the crate to your project:

[dependencies]
bpm-finder-tools = "0.1.0"

Or install the CLI from source:

cargo install bpm-finder-tools

Library usage

Tap tempo

use bpm_finder_tools::tap;

let analysis = tap::analyze_intervals(&[500.0, 480.0, 495.0, 505.0])?;

assert_eq!(analysis.average_interval_ms, 495.0);
assert_eq!(analysis.bpm, 121.212);
assert_eq!(analysis.rounded_bpm, 121);
# Ok::<(), bpm_finder_tools::TapTempoError>(())

Analyze an audio file

use bpm_finder_tools::file;

let analysis = file::analyze_path("fixtures/loop.wav", 70.0, 180.0)?;

println!("Detected BPM: {}", analysis.bpm);
println!("Normalized BPM: {}", analysis.normalized_bpm);
# Ok::<(), bpm_finder_tools::TapTempoError>(())

BPM and milliseconds conversion

use bpm_finder_tools::convert;

let beat_ms = convert::bpm_to_ms_per_beat(128.0)?;
let bar_ms = convert::bpm_to_ms_per_bar(128.0, 4)?;
let bpm = convert::ms_per_bar_to_bpm(1875.0, 4)?;

assert_eq!(beat_ms, 468.75);
assert_eq!(bar_ms, 1875.0);
assert_eq!(bpm, 128.0);
# Ok::<(), bpm_finder_tools::TapTempoError>(())

Normalize into a practical range

use bpm_finder_tools::range;

assert_eq!(range::normalize(72.0, 90.0, 180.0)?, 144.0);
assert_eq!(range::double_time(87.5)?, 175.0);
assert_eq!(range::half_time(174.0)?, 87.0);
assert!(range::is_within(128.0, 90.0, 180.0)?);
# Ok::<(), bpm_finder_tools::TapTempoError>(())

CLI usage

bpm-finder-tools file ./loop.wav
bpm-finder-tools tap 500 480 495 505
bpm-finder-tools ms 128
bpm-finder-tools bpm 468.75
bpm-finder-tools normalize 72 --min 90 --max 180

Example output:

$ bpm-finder-tools file ./loop.wav
File: ./loop.wav
Detected BPM: 120
Rounded BPM: 120
Normalized BPM: 120
Confidence: 0.742
Duration: 8
Sample rate: 44100 Hz
$ bpm-finder-tools tap 500 480 495 505
Tap intervals: 500, 480, 495, 505
Average interval: 495 ms
Exact BPM: 121.212
Rounded BPM: 121

Public API

TapTempoAnalysis

  • average_interval_ms: f64
  • bpm: f64
  • rounded_bpm: u32

AudioFileAnalysis

  • bpm: f64
  • rounded_bpm: u32
  • normalized_bpm: f64
  • confidence: f64
  • duration_seconds: f64
  • analyzed_seconds: f64
  • sample_rate: u32

file

  • analyze_path(path, min_bpm, max_bpm) -> Result<AudioFileAnalysis, TapTempoError>
  • analyze_samples(samples, sample_rate, min_bpm, max_bpm) -> Result<AudioFileAnalysis, TapTempoError>

tap

  • analyze_intervals(intervals_ms: &[f64]) -> Result<TapTempoAnalysis, TapTempoError>
  • bpm_from_intervals(intervals_ms: &[f64]) -> Result<f64, TapTempoError>

convert

  • bpm_to_ms_per_beat(bpm: f64) -> Result<f64, TapTempoError>
  • bpm_to_ms_per_bar(bpm: f64, beats_per_bar: u32) -> Result<f64, TapTempoError>
  • ms_per_beat_to_bpm(milliseconds: f64) -> Result<f64, TapTempoError>
  • ms_per_bar_to_bpm(milliseconds: f64, beats_per_bar: u32) -> Result<f64, TapTempoError>

range

  • normalize(bpm: f64, min: f64, max: f64) -> Result<f64, TapTempoError>
  • is_within(bpm: f64, min: f64, max: f64) -> Result<bool, TapTempoError>
  • half_time(bpm: f64) -> Result<f64, TapTempoError>
  • double_time(bpm: f64) -> Result<f64, TapTempoError>

Development

cargo test
cargo package --list
cargo publish --dry-run

Release notes

Current version: 0.1.0

  • First public release
  • Library API plus CLI
  • Basic audio-file BPM analysis for supported formats

License

MIT