Calibra Vocal Range
Streaming vocal range analyzer for determining a singer's pitch range.
What is Vocal Range?
Vocal range is the span between a singer's lowest and highest notes. This analyzer detects the range using pedagogically-valid criteria based on ASHA 2018 guidelines and voice science research.
Use it for:
Onboarding: Determine user's comfortable singing range
Song selection: Match songs to user's range
Progress tracking: See if range expands over time
Key transposition: Calculate optimal key for user
When to Use
| Scenario | Use This? | Why |
|---|---|---|
| Find singer's range | Yes | Core use case |
| Guided range finding | Yes | getStableNote() for step-by-step |
| Real-time pitch display | No | Use CalibraPitch |
| Score singing | No | Use CalibraLiveEval |
Quick Start
Kotlin
val analyzer = CalibraVocalRange.create()
// Feed audio from recorder
recorder.audioBuffers.collect { buffer ->
analyzer.addAudio(buffer.toFloatArray())
}
// Get detected range
val range = analyzer.getRange()
if (range != null) {
println("Range: ${range.lower.noteLabel} to ${range.upper.noteLabel}")
println("Octaves: ${range.octaves}")
}
analyzer.release()Swift
let analyzer = CalibraVocalRange.create()
// Feed audio from recorder
for await buffer in recorder.audioBuffersStream() {
analyzer.addAudio(samples: buffer.toFloatArray())
}
// Get detected range
if let range = analyzer.getRange() {
print("Range: \(range.lower.noteLabel) to \(range.upper.noteLabel)")
print("Octaves: \(range.octaves)")
}
analyzer.release()Guided Range Detection
For step-by-step range finding (e.g., "sing your lowest note"):
Kotlin
val analyzer = CalibraVocalRange.create()
// Phase 1: Detect lowest note
showPrompt("Sing your lowest comfortable note")
// ... user sings, feed audio via addAudio() ...
val lowestNote = analyzer.getStableNote()
analyzer.reset() // Reset for next phase
// Phase 2: Detect highest note
showPrompt("Sing your highest comfortable note")
// ... user sings, feed audio via addAudio() ...
val highestNote = analyzer.getStableNote()
// Calculate range
val rangeOctaves = (highestNote.pitch.midiNote - lowestNote.pitch.midiNote) / 12f
analyzer.release()Detection Criteria (ASHA 2018)
The analyzer uses these criteria for pedagogical validity:
Minimum 1 second sustained pitch for note inclusion
Confidence threshold of 0.5 minimum
Stability: pitch deviation < 1 semitone within 50ms
Percentile-based range extraction (5th-95th percentile)
Platform Notes
iOS
Audio is typically 48kHz from microphone; internal resampling handles this
Uses YIN algorithm for pitch detection (no external dependencies)
Android
Audio varies by device (44.1kHz, 48kHz, 16kHz)
Uses YIN algorithm for pitch detection (pure Kotlin)
Common Pitfalls
Forgetting to release: Call
analyzer.release()to free resourcesNot resetting between phases: Call
reset()when starting new detectionNot enough sustained notes: User must hold notes for 1+ second
Background noise: High noise can trigger false detections
See also
For the result structure
For customizing detection parameters
For general pitch detection
Functions
Add audio samples for analysis.
Get lower limit from accumulated data (5th percentile of stable pitches).
Get complete range analysis.
Get the stable note detected so far.
Get statistics about accumulated data.
Get upper limit from accumulated data (95th percentile of stable pitches).