CoolFace
Datasetpublic

karankhatavkar/ak47-acoustic-rul-simulated

AK-47 Acoustic Run-to-Failure (RUL) Simulation Dataset A synthetic Run-to-Failure dataset for Remaining Useful Life (RUL) estimation of an AK-47's recoil spring from gunshot audio. Because real run-to-failure recordings of a wearing firearm are practically impossible to collect, this dataset is generated by a physics-based Digital Twin that takes a small set of real, healthy gunshot recordings and mathematically simulates the acoustic signature of mechanical wear over thousands… See the full description on the dataset page: https://huggingface.co/datasets/karankhatavkar/ak47-acoustic-rul-simulated.

sourceHugging Facemitupdated 4mo agoView on Hugging Face
1likes23downloads
Dataset Card

AK-47 Acoustic Run-to-Failure (RUL) Simulation Dataset

A synthetic Run-to-Failure dataset for Remaining Useful Life (RUL) estimation of an AK-47's recoil spring from gunshot audio. Because real run-to-failure recordings of a wearing firearm are practically impossible to collect, this dataset is generated by a physics-based Digital Twin that takes a small set of real, healthy gunshot recordings and mathematically simulates the acoustic signature of mechanical wear over thousands of rounds.

The core physical assumption: as the recoil spring fatigues and loses its spring constant, the return-to-battery velocity drops, which lengthens the time gap between the muzzle blast ("Bang") and the bolt closing ("Clank"). This cycle time (delta-T) is the wear biomarker, and a sigmoid health curve maps it to a 0–100% health (life remaining) label.


Code & Reproducibility

The full pipeline that generates this dataset — audio preprocessing, the physics-based Digital Twin simulator, and the CWT-scalogram / tabular-feature extraction — is open-sourced at [github.com/karankhatavkar/ak47-acoustic-rul](https://github.com/karankhatavkar/ak47-acoustic-rul).


Repository Structure

.
├── real_recordings/        # Raw, real AK-47 single-shot WAV recordings (the source audio)
├── seed_audio/             # Cleaned & trimmed healthy "seed" clips + ground-truth manifest
│   └── ak47_health_manifest.txt
├── simulated_audio/        # Synthetic run-to-failure WAVs + master log + per-seed graphs
│   ├── S1/ … S71/          # WAVs bucketed by seed (ak_47_S{seed}_P{point}.wav)
│   ├── simulation_master_log.csv
│   └── sim_graphs/
├── cwt_scalograms/         # CWT scalogram images (224×224 PNG) of every simulated clip
│   └── S1/ … S71/          # PNGs bucketed by seed, names mirror the WAVs
└── features/
    └── xgboost_features.csv  # Hand-crafted acoustic features for every simulated clip
Note on the `S{seed}/` sub-folders. The simulated clips are bucketed into one sub-folder per seed (S1, S2, … S71, ~460 files each) inside both simulated_audio/ and cwt_scalograms/. This is required because the Hugging Face Hub caps every directory at 10,000 files, and each of these sets has ~30.6 k clips. The seed id is embedded in every filename (ak_47_S{seed}_P{point}), so a file's bucket is simply S{seed}simulation_master_log.csv stores the bare filename and the bucket is derived from it.

Folder descriptions

Folder / fileContentsCount
real_recordings/The original, unmodified real AK-47 gunshot recordings (44.1 kHz WAV, one shot per file). These are the raw inputs to the whole pipeline.72 WAV
seed_audio/The "seed" clips: each real recording trimmed to a clean 1.0-second window around the gunshot event (see Preprocessing). Files are named seed_1 (N).wav. One ambiguous recording was dropped, so there are 71 (not 72).71 WAV
seed_audio/ak47_health_manifest.txtGround-truth manifest (CSV) for the seeds: Filename, Cycle_Time_ms, Initial_Health_Percent. The measured Bang→Clank cycle time and the initial health each healthy seed maps to.1 file
simulated_audio/S{seed}/The synthetic run-to-failure audio generated by the Digital Twin — each seed's spring is "aged" across its lifetime and rendered as time-stretched WAVs. Files are named ak_47_S{seed_id}_P{point_number}.wav and bucketed into one S{seed}/ sub-folder each.~30.6 k WAV
simulated_audio/simulation_master_log.csvLabels for every simulated clip: seed_file_name, sample_file_name, delta_T_ms, percent_life_remaining. This is the primary label file for the dataset.1 file
simulated_audio/sim_graphs/One PNG per seed (ak_47_S{seed_id}_simulation_graph.png) plotting that seed's simulated degradation trajectory against the ideal health curve and noise envelope.71 PNG
cwt_scalograms/S{seed}/A Continuous Wavelet Transform (CWT) scalogram image for every simulated clip, used as input for 2D-CNN image regression. 224×224 JET-colormapped PNGs named to match the WAVs, bucketed into the same S{seed}/ sub-folders.~30.6 k PNG
features/xgboost_features.csvPre-extracted tabular acoustic features (ZCR, spectral kurtosis, 13 MFCCs) for every simulated clip, joined to the RUL label — ready for gradient-boosting / classical ML.1 file

Source of the Original Audio

The real gunshot recordings in real_recordings/ are sourced from the public [Gunshot Audio Dataset by Emrah Aydemr on Kaggle](https://www.kaggle.com/datasets/emrahaydemr/gunshot-audio-dataset) (the AK-47 class). All synthetic data in this repository is derived from those healthy recordings; no real worn-out / failed firearm audio exists or is used.


How the Dataset Was Built

The dataset is produced by a three-stage pipeline: (1) preprocessing the real audio into clean labelled seeds, (2) simulating run-to-failure trajectories from each seed, and (3) deriving model-ready representations (CWT scalograms and tabular features).

1. Preprocessing (real recordings → labelled seeds)

Applied to every file in real_recordings/ to produce seed_audio/ and the health manifest:

  1. 1.Load each recording at 44.1 kHz mono.
  2. 2.Locate the gunshot event with a pattern-based anchor finder rather than a naive loudest-peak search. It combines normalized RMS energy (sustained power) and onset strength (percussive transients) into a single score (rms_norm × onset_norm), smooths it with a Gaussian filter (~50 ms) to favour a sustained event over a single click, then backtracks from the score peak to the moment the event started (where the score first falls below 10% of its peak).
  3. 3.Crop a fixed window around that anchor — 100 ms before and 900 ms after (a clean ~1.0 s clip) — and save as seed_{original_name}.wav.
  4. 4.Manually drop one ambiguous record (seed_1 (14).wav) that could not be reliably anchored.
  5. 5.Measure the cycle time (delta-T) for each seed from its onset envelope: the Bang is the global onset maximum; the Clank is the strongest onset peak in a 50–150 ms window after the Bang. delta_T = (clank_time − bang_time) in ms. (The seed set averages ≈ 93.9 ms.)
  6. 6.Map cycle time → initial health with the logistic (reverse-sigmoid) degradation model and write ak47_health_manifest.txt:

$$H(t) = \frac{100}{1 + e^{0.19\,(t - 120)}}, \qquad H(t)=0 \text{ for } t \le 40 \text{ or } t > 130$$

2. Data Simulation (Digital Twin run-to-failure)

For each labelled seed (starting from its measured base cycle time T_base), a physics-based simulator generates a full degradation trajectory shot-by-shot. It is built on three coupled models (full spec in the Simulation Parameters table):

  • A. Kinematic wear model — the actual cycle time at shot i is the base time plus an exponential wear trend and a heteroscedastic mechanical jitter (the gun rattles more as it wears):

$$t{final}(i) = T{base} + \underbrace{\alpha\, e^{\beta i}}{\text{wear trend}} + \underbrace{\mathcal{N}\!\big(0,\; \sigma{base} + \gamma i\big)}_{\text{mechanical jitter}}$$

  • B. Ideal health model (ground truth) — the reverse-sigmoid mapping cycle time to health, so the spring holds tension then fails rapidly:

$$H{ideal}(t) = \frac{100}{1 + e^{K\,(t - T0)}}$$

  • C. Dynamic variance model (label noise) — a Gaussian envelope that injects realistic uncertainty into the health label, maximal during the mid-life transition phase and near-zero at the healthy/failed extremes:

$$\sigma{health}(t) = P{noise}\, e^{-\frac{(t - P{time})^2}{2 W^2}}, \qquad H{final} = \mathrm{clip}\!\big(H{ideal} + \mathcal{N}(0, \sigma{health}),\, 0,\, 100\big)$$

The shot loop runs until the wear trend pushes the cycle time past failure (T_base + wear_trend > 145 ms). A fixed random seed (42) makes the whole simulation reproducible.

Audio rendering. For each simulated shot that is kept, the seed waveform is time-stretched with a librosa phase-vocoder at rate T_base / t_target (longer target cycle time → slower playback), which acoustically lengthens the Bang→Clank gap to match the simulated wear. To keep the dataset to a manageable size, every 5th shot is rendered to a WAV (simulated_audio/S{seed_id}/ak_47_S{seed_id}_P{point}.wav); the label of every rendered shot is recorded in simulation_master_log.csv, and a trajectory plot per seed is saved under sim_graphs/.

3. Derived representations

Both derived feature sets are computed from simulated_audio/ using the labels in simulation_master_log.csv.

a. CWT scalograms (`cwt_scalograms/`) — for 2D-CNN image regression:

  • Load at 22.05 kHz; zero-pad or truncate to a fixed 1.5 s.
  • Continuous Wavelet Transform with a complex Morlet wavelet (cmor1.5-1.0) over 128 scales (geomspace(1, 100)).
  • Take the coefficient magnitude → amplitude-to-dB (ref = max) → normalize to 0–255 → vertical flip → resize to 224×224 (cubic) → apply the JET colormap → save as PNG.

b. Tabular acoustic features (`features/xgboost_features.csv`) — for classical ML / XGBoost:

  • Load at 44.1 kHz and extract 15 features per clip:
  • zcr_mean — mean Zero-Crossing Rate (proxy for gas blow-by / turbulence).
  • spectral_kurtosis — kurtosis of the mean STFT spectrum (proxy for mechanical rattle).
  • mfcc_1 … mfcc_13 — means of the first 13 MFCCs (timbre / receiver resonance).
  • Each row is joined with seed_file_name, sample_file_name, delta_T_ms, and the target percent_life_remaining.

Simulation Parameters

CategoryVariableValueDescription
Physics (time)T_baseper-seedStarting cycle time (ms) of the healthy seed (≈ 40 ms = factory new at the curve floor).
ALPHA (α)0.001Wear trend magnitude (base scaler for exponential degradation).
BETA (β)0.005Wear acceleration (steepness of the physical wear curve).
SIGMA_BASE (σ_base)1.0Base mechanical jitter (ms) — natural variance of a new gun.
GAMMA (γ)0.005Jitter growth per shot (rattle increases with wear).
Health curveT0120.0Critical failure point (ms) — the "knee" of the sigmoid.
K0.19Curve steepness — how fast health drops around T0.
VariancePEAK_NOISE10.0Max standard deviation (%) applied to the health label.
PEAK_TIME110.0Cycle time (ms) where label noise is maximal.
NOISE_WIDTH15.0Gaussian width controlling how fast the noise tapers to zero.
SamplingSAVE_EVERY_N_SHOTS5Only every Nth simulated shot is rendered to audio.
SEED_VALUE42RNG seed for full reproducibility.

Expected trajectory behaviour: health stays locked near 100% in the early phase (low variance), spreads into a vertical "cloud" through the mid-life transition (max spread ≈ ±20% at 2σ around 110 ms), then crashes toward 0% past ~120 ms as the noise envelope tightens — confidently labelling failed weapons as near-zero health.


Usage (load_dataset)

All three modalities share one label file (simulation_master_log.csv) and the clips live in S{seed}/ buckets, so the cleanest way to load is to build the dataset from the master log and let 🤗 datasets decode the audio / images lazily. The bucket is derived from the filename:

python
import re
import pandas as pd
from datasets import Dataset, Audio, Image
from huggingface_hub import snapshot_download

repo = snapshot_download("karankhatavkar/ak47-acoustic-rul-simulated", repo_type="dataset")

def bucket(fn):  # 'ak_47_S12_P3.wav' -> 'S12'
    return f"S{re.search(r'_S(\\d+)_', fn).group(1)}"

log = pd.read_csv(f"{repo}/simulated_audio/simulation_master_log.csv")
log["audio"]     = log["sample_file_name"].map(lambda f: f"{repo}/simulated_audio/{bucket(f)}/{f}")
log["scalogram"] = log["sample_file_name"].map(lambda f: f"{repo}/cwt_scalograms/{bucket(f)}/{f[:-4]}.png")

ds = (
    Dataset.from_pandas(log)
    .cast_column("audio", Audio())       # 1D-CNN: raw waveform
    .cast_column("scalogram", Image())   # 2D-CNN: CWT scalogram
)
# target column: percent_life_remaining

# Tabular / XGBoost features (no audio decoding needed):
tab = pd.read_csv(f"{repo}/features/xgboost_features.csv")

Intended Use

  • RUL / prognostics regression — predict percent_life_remaining from audio.
  • Three model families this dataset supports out of the box:
  • Tabular / XGBoost on features/xgboost_features.csv.
  • 2D CNN on cwt_scalograms/ images.
  • 1D CNN on the raw simulated_audio/ waveforms.

Important Caveats

  • This is synthetic data produced by a physics-inspired model; the degradation is simulated, not measured from a real worn firearm. It is intended for prognostics method development and benchmarking, not as ground truth for real-world firearm wear.
  • Time-stretching alters the temporal structure of the seed clip; acoustic features reflect that transformation rather than independently recorded worn-gun audio.

Citation

If you use this dataset, please credit this repository, the code repository, and the original source audio (Gunshot Audio Dataset, Emrah Aydemr, Kaggle).

karankhatavkar/ak47-acoustic-rul-simulated · CoolFace