Skip to main content

SonixLessonSynthesizer

Synthesize audio lessons from svara (note) sequences for Indian classical music education.

Quick Start

Kotlin

val svaras = listOf(
LessonSvara(
svaraName = "Sa",
svaraLabel = "S",
svaraAudioFilePath = "/path/to/sa.wav",
numBeats = 2,
numSamplesConsonant = 100
),
LessonSvara(
svaraName = "Re",
svaraLabel = "R",
svaraAudioFilePath = "/path/to/re.wav",
numBeats = 2,
numSamplesConsonant = 100
)
)

val synth = SonixLessonSynthesizer.create(
svaras = svaras,
beatLengthMs = 500
)

if (synth.loadAudioSync()) {
val audioData: AudioRawData? = synth.synthesize()
// audioData is ready to play or save
}

synth.release()

Swift

let svaras = [
LessonSvara(
svaraName: "Sa",
svaraLabel: "S",
svaraAudioFilePath: "/path/to/sa.wav",
numBeats: 2,
numSamplesConsonant: 100
),
LessonSvara(
svaraName: "Re",
svaraLabel: "R",
svaraAudioFilePath: "/path/to/re.wav",
numBeats: 2,
numSamplesConsonant: 100
)
]

let synth = SonixLessonSynthesizer.create(
svaras: svaras,
beatLengthMs: 500
)

if await synth.loadAudio() {
if let audioData = synth.synthesize() {
// audioData is ready to play or save
}
}

synth.release()

Configuration

Factory Method

ParameterTypeDefaultDescription
svarasList<LessonSvara>Svara sequence (required)
beatLengthMsIntBeat duration in milliseconds (required)

Builder

For advanced configuration:

Kotlin

val synth = SonixLessonSynthesizer.Builder()
.svaras(svaraList)
.beatLengthMs(500)
.silenceBeats(start = 2, end = 2)
.sampleRate(44100)
.onError { error -> println("Error: $error") }
.build()

Builder Parameters

MethodTypeDefaultDescription
svarasList<LessonSvara>Svara sequence (required)
beatLengthMsIntBeat duration in ms (required)
silenceBeatsstart: Int, end: Int2, 2Silence beats at start/end
sampleRateInt16000Output sample rate in Hz
onError(String) -> UnitError callback

Workflow

The synthesis process has two steps:

1. Load Audio

Load svara audio files into memory:

// Suspending (preferred)
val success = synth.loadAudio()

// Synchronous (blocking)
val success = synth.loadAudioSync()

2. Synthesize

Generate the lesson track:

val audioData: AudioRawData? = synth.synthesize()
if (audioData != null) {
// Play it
val player = SonixPlayer.createFromPcm(
data = audioData.audioData,
sampleRate = audioData.sampleRate,
channels = audioData.numChannels
)
player.play()
}

Observing State

Kotlin (StateFlow)

synth.isLoading.collect { loading ->
progressBar.isVisible = loading
}

synth.isLoaded.collect { loaded ->
synthesizeButton.isEnabled = loaded
}

synth.error.collect { error ->
error?.let { showError(it.message) }
}

Swift (Observers)

let loadingTask = synth.observeIsLoading { loading in
self.isLoading = loading
}

let loadedTask = synth.observeIsLoaded { loaded in
self.isReady = loaded
}

let errorTask = synth.observeError { error in
if let error = error { self.showError(error.message) }
}

Swift (Combine)

synth.isLoadingPublisher
.receive(on: DispatchQueue.main)
.sink { self.isLoading = $0 }
.store(in: &cancellables)

StateFlows

StateFlowTypeDescription
isLoadingStateFlow<Boolean>Whether audio files are being loaded
isLoadedStateFlow<Boolean>Whether ready for synthesis
errorStateFlow<SonixError?>Error state

Properties

PropertyTypeDescription
beatLengthMsIntBeat duration in milliseconds
silenceBeatsStartIntSilence beats at the start
silenceBeatsEndIntSilence beats at the end
sampleRateIntOutput sample rate

LessonSvara

Each svara in the sequence is defined by:

PropertyTypeDescription
svaraNameStringFull name (e.g., "Sa", "Re")
svaraLabelStringShort label (e.g., "S", "R")
svaraAudioFilePathStringPath to audio recording
numBeatsIntDuration in beats
numSamplesConsonantIntConsonant samples for crossfading

Method Summary

MethodReturnsDescription
loadAudio()BooleanLoad audio files (suspend / async)
loadAudioSync()BooleanLoad audio files (blocking)
synthesize()AudioRawData?Generate lesson audio
release()Release resources

Next Steps