Noise in, research evidence out.
A bioacoustic ML pipeline built for the HackSMU VII iMasons "AI & Machine Learning for Nature" challenge. ElephantComm takes noisy field recordings of elephant vocalizations, strips out mechanical interference, isolates individual calls, and classifies them into meaningful categories — giving wildlife researchers clean, structured data from messy real-world audio.
Wildlife researchers deploy recording devices in the field to capture elephant vocalizations. But those recordings are full of noise — airplane engines, electrical hum, wind, and other mechanical interference. Manually sifting through hours of corrupted audio to find usable elephant calls is slow, tedious, and error-prone.
ElephantComm automates this entire workflow. Drop in a noisy recording, get back clean segments, classified calls, and exportable research data.
Top: original elephant audio. Middle: same audio with mechanical noise mixed in. Bottom: recovered signal after spectral subtraction.
The spectrograms below show frequency content over time (0-500 Hz range). Elephant rumbles appear as horizontal bands in the low-frequency region.
| Clean Input | Noisy Input | Denoised Output |
|---|---|---|
![]() |
![]() |
![]() |
| Original 23s African forest elephant recording | Same recording with simulated mechanical interference | Signal recovered by the preprocessing pipeline |
| Noisy Input | Denoised Output |
|---|---|
![]() |
![]() |
| 5-second elephant trumpeting with noise overlay | Clean signal extracted — 6 segments detected |
From a single 23-second recording, the pipeline detected 73 audio segments and classified each one:
Segments are classified into vocalization types based on acoustic features like fundamental frequency, spectral centroid, and duration.
The pipeline processes elephant audio through six stages:
flowchart LR
A["Raw Recording"] --> B["Ingestion"]
B --> C["Preprocessing"]
C --> D["Feature Extraction"]
D --> E["Classification"]
E --> F["Semantic Analysis"]
F --> G["Research Queries"]
style A fill:#e74c3c,color:#fff
style G fill:#2ecc71,color:#fff
Accepts audio in multiple formats with rich metadata.
| Feature | Details |
|---|---|
| Formats | WAV, FLAC, MP3, PCM |
| Metadata | GPS coordinates, device type, capture timestamp |
| Storage | In-memory byte store with UUID-based recording IDs |
| Annotations | Researcher notes, environment descriptions |
service = IngestionService()
recording_id = service.ingest(
source=audio_bytes,
metadata=RecordingMetadata(
gps_latitude=2.3,
gps_longitude=18.6,
device_type="field_recorder",
),
audio_format=AudioFormat.WAV,
sample_rate=16000,
)Uses spectral subtraction to remove mechanical noise while preserving the frequencies that matter most for elephant communication.
| Technique | Purpose |
|---|---|
| Spectral subtraction | Estimates and removes the noise frequency profile from the signal |
| Infrasonic preservation | Protects frequencies below 20 Hz — critical for elephant rumbles humans can't hear |
| Amplitude normalization | Standardizes volume levels across recordings |
| Energy-based segmentation | Splits continuous audio into individual candidate calls |
How spectral subtraction works:
- Compute the Short-Time Fourier Transform (STFT) of both the noisy audio and the noise profile
- Subtract the noise magnitude spectrum from the signal magnitude spectrum
- Reconstruct the cleaned audio via inverse STFT
- Preserve phase information from the original signal
Computes a rich set of acoustic features from each detected segment. Built entirely on numpy/scipy with no heavy dependencies.
| Feature | What It Measures |
|---|---|
| MFCCs (13 coefficients) | Timbral texture — the "color" of the sound |
| Formant tracks | Resonant frequencies and bandwidths — vocal tract shape |
| Spectrogram | Full time-frequency energy distribution |
| Fundamental frequency | The base pitch of the vocalization |
| Spectral centroid | The "center of mass" of the frequency spectrum |
| Spectral bandwidth | How spread out the frequencies are |
| Zero-crossing rate | How often the signal changes sign — correlates with noisiness |
| Energy contour | How loudness changes over the duration of the call |
Categorizes each detected segment into one of 10 elephant vocalization types:
| Category | Frequency Range | Typical Duration | Description |
|---|---|---|---|
| Contact Rumble | ~18 Hz | ~4.5s | Long-distance "I'm here" calls between separated groups |
| Greeting Rumble | ~24 Hz | ~3.0s | Close-range social greetings when elephants reunite |
| Distress Call | ~120 Hz | ~0.8s | High-frequency alarm signals indicating danger |
| Warning Call | ~95 Hz | ~0.9s | Threat alerts broadcast to the group |
| Name Call | ~42 Hz | ~1.8s | Individual-specific vocalizations (elephants call each other by name) |
| Location Reference | ~36 Hz | ~2.2s | Calls associated with specific places |
| Social Bonding | ~28 Hz | ~2.6s | Affiliative interactions that reinforce group cohesion |
| Musth Rumble | ~12 Hz | ~6.0s | Very low-frequency male reproductive calls |
| Maternal Call | ~55 Hz | ~1.6s | Mother-calf communication |
| Unknown | varies | varies | Vocalizations that don't match known patterns |
Two classification modes:
| Mode | How It Works | When To Use |
|---|---|---|
| Heuristic | Compares features against hand-crafted prototypes using scaled Euclidean distance + softmax | No training data available (default) |
| Trained | Nearest-centroid classifier learned from labeled (FeatureVector, CallCategory) pairs |
When you have labeled examples |
Goes beyond individual call classification to detect higher-order communication patterns across sequences of calls:
- Naming events — detects when elephants use individual-specific vocalizations to address or refer to another elephant
- Third-person references — identifies calls about absent individuals (elephants discussing others who aren't present)
- Place references — links vocalizations to geographic locations
- Vowel-like patterns — finds formant structures resembling vowel sounds in the call acoustics
Builds a semantic graph connecting elephants, calls, locations, and events:
graph TD
E1["Elephant A"] -->|CALLER| C1["Call #1 (Name Call)"]
C1 -->|ADDRESSEE| E2["Elephant B"]
C1 -->|LOCATED_AT| L1["Waterhole"]
E2 -->|CALLER| C2["Call #2 (Contact Rumble)"]
C2 -->|RESPONDS_TO| C1
C2 -->|REFERENCES| E3["Elephant C"]
style E1 fill:#3498db,color:#fff
style E2 fill:#3498db,color:#fff
style E3 fill:#3498db,color:#fff
style C1 fill:#e67e22,color:#fff
style C2 fill:#e67e22,color:#fff
style L1 fill:#2ecc71,color:#fff
Provides researchers with tools to explore, filter, and export results:
| Capability | Description |
|---|---|
| Filter by category | Find all distress calls, contact rumbles, etc. |
| Filter by confidence | Only return high-confidence classifications |
| Filter by time range | Focus on specific windows of the recording |
| Communication profiles | Summarize an individual elephant's vocal activity |
| CSV/JSON export | Export results for use in R, Python, Excel, etc. |
| Spectrogram annotation | Overlay classification labels on visual spectrograms |
- Python 3.10+
- pip
# Clone the repository
git clone https://github.com/rv-online/hacksmu.git
cd hacksmu
# Install dependencies
pip install -r requirements.txt
# Optional: install matplotlib for spectrogram visualizations
pip install matplotlib# Step 1: Download real elephant audio samples
python scripts/fetch_demo_audio.py
# Step 2: Run the full pipeline
python scripts/run_hacksmu_demo.py# Short 5-second demo (recommended for quick runs)
python scripts/run_hacksmu_demo.py \
--input demo_assets/audio/elephant_trumpeting.wav \
--output-dir demo_outputs/trumpeting_demo
# Full 23-second African forest elephant clip
python scripts/run_hacksmu_demo.py
# Sponsor challenge dataset
python scripts/run_sponsor_challenge_demo.py \
--sound-file 061220-24_airplane_01.wav \
--output-dir demo_outputs/sponsor_demo| File | Description |
|---|---|
clean_input.wav |
Original elephant audio |
noisy_input.wav |
Audio with synthetic mechanical noise (60 Hz hum, engine rumble, broadband noise) |
denoised_output.wav |
Cleaned audio after spectral subtraction |
summary.json |
Full classification results — segment boundaries, confidence scores, SNR |
clean_spectrogram.png |
Spectrogram of original audio (requires matplotlib) |
noisy_spectrogram.png |
Spectrogram showing noise contamination |
denoised_spectrogram.png |
Spectrogram after pipeline processing |
Here's a snippet from summary.json showing a detected segment:
{
"segment_id": "2af463da-c273-44a6-becc-96246861892b",
"start_time": 20.096,
"end_time": 22.272,
"duration": 2.176,
"fundamental_frequency": 380.95,
"predicted_category": "DISTRESS_CALL",
"confidence": 0.992,
"signal_to_noise_ratio": 15.61
}| Component | Technology |
|---|---|
| Language | Python 3.10+ |
| Audio I/O | scipy.io.wavfile |
| Signal Processing | numpy, scipy (STFT, spectral subtraction, resampling) |
| Feature Extraction | numpy, scipy (MFCCs, formants, spectrograms) |
| Data Models | Pydantic v2 |
| Testing | pytest + Hypothesis (property-based testing) |
| Visualization | matplotlib (optional) |
| CI | GitHub Actions |
hacksmu/
elephant_comm/
ingestion/ # Audio intake and metadata storage
preprocessing/ # Spectral subtraction, normalization, segmentation
feature_extraction/ # MFCCs, formants, spectrograms, acoustic features
classification/ # Heuristic and nearest-centroid classifiers
semantic/ # Communication pattern analysis and graph building
query/ # Research filtering, profiling, and export interface
models/ # Pydantic schemas, enums, and shared type definitions
stores/ # Byte-safe serialization and in-memory persistence
scripts/ # Demo runners and data-fetching utilities
tests/ # Unit tests and property-based tests (Hypothesis)
docs/ # Runbooks, pitch materials, submission checklist
demo_assets/ # Downloaded audio samples (gitignored)
demo_outputs/ # Generated results and spectrograms (gitignored)
# Run the full test suite
python -m pytest -q
# Run with verbose output
python -m pytest -v
# Run a specific module
python -m pytest elephant_comm/classification/test_engine.py226 passing tests including property-based tests via Hypothesis that verify serialization round-trips, classification invariants, and model schema validation.
Demo audio clips are downloaded from the public EarthToolsMaker forest-elephant repository, which describes itself as a collaboration with the Elephant Listening Project and Cornell University. The samples include:
| File | Duration | Description |
|---|---|---|
AfricanForestElephants.wav |
~23s | Forest elephant vocalizations with natural background |
elephant_trumpeting.wav |
~5s | Short trumpeting call — ideal for quick demos |
| Document | Description |
|---|---|
| Demo Runbook | Step-by-step guide for running the live demo |
| Demo Results | Pre-computed results snapshot with key metrics |
| Sponsor Data Notes | How we handled the challenge dataset |
| Hacker Toolkit | Filled-out hackathon template pack |
| Pitch Guide | Presentation framing and talking points |
| Submission Checklist | Final submission verification |
- Sponsor assets stay local-only under
sponsor_assets/ - Generated demo outputs stay local-only under
demo_outputs/ - AI tooling was used during development and is disclosed in the submission
Contributions are welcome. See CONTRIBUTING.md.






