TesseraRangeSession

Guided vocal range detection session with observable state.

What is a Range Session?

A stateful, phase-driven workflow for detecting a singer's comfortable vocal range: countdown → detect low → transition → detect high → complete. Emits VocalRangeState via state (a StateFlow) so UI can track progress, current pitch, stability, and the final result.

Supports auto-flow (automatic phase progression) and manual control (caller drives transitions via startPhase / advancePhase).

When to Use

ScenarioUse ThisWhy
Interactive "find your range" flow in the appYesGuided phases + observable state
Batch range estimation from a recordingNoUse TesseraRange.computeVocalRange
Multi-metric analysis (breath + agility + range)NoUse Tessera.analyze or TesseraSession

Quick Start

Kotlin

val session = TesseraRangeSession.create(
detectorConfig = PitchDetectorConfig.BALANCED
)

// Observe state
session.state.collect { state -> updateUI(state) }

// Start auto-flow and feed audio
session.start()
recorder.audioBuffers.collect { buffer ->
session.addAudio(buffer.samples, sampleRate = 16000)
}

// Lock a detected note, or cancel
session.confirmNote()
session.release()

Swift

let session = TesseraRangeSession.create(
detectorConfig: PitchDetectorConfig.Builder().algorithm(.yin).enableProcessing().build()
)

// Observe state via AsyncSequence
for await state in session.state {
updateUI(state)
}

session.start()
for await buffer in recorder.audioBuffers {
session.addAudio(samples: buffer.samples, sampleRate: Int32(hwRate))
}

session.confirmNote()
session.release()

Common Pitfalls

  1. start() is for auto-flow only: If config.autoFlow = false, call startPhase / advancePhase instead — start() throws.

  2. Audio is only processed during detection phases: Samples sent outside DETECTING_LOW / DETECTING_HIGH (i.e., during IDLE, COUNTDOWN, TRANSITION, COMPLETE, or CANCELLED) are silently ignored.

  3. Call release() when done: Holds native detector resources.

  4. confirmNote() locks the current best: It's a user-confirmation action, not an auto-trigger. Returns false if no stable note yet.

See also

For batch (non-interactive) range estimation

For multi-metric batch analysis

The observable state type

The final result with natural shruti

Session configuration (auto-flow, countdown, etc.)

Types

Link copied to clipboard
object Companion

Properties

Link copied to clipboard
val state: StateFlow<VocalRangeState>

Functions

Link copied to clipboard
fun addAudio(samples: FloatArray, sampleRate: Int = 16000)

Add raw audio samples. Resamples to 16kHz internally if needed.

Link copied to clipboard
fun addPitch(time: Float, pitchHz: Float, confidence: Float)

Add a pre-extracted pitch point. Skips internal pitch detection.

Link copied to clipboard
Link copied to clipboard
fun cancel()
Link copied to clipboard
fun complete()
Link copied to clipboard
Link copied to clipboard

Get statistics about accumulated range data.

Link copied to clipboard
fun release()
Link copied to clipboard
fun reset()
Link copied to clipboard
fun start()
Link copied to clipboard