Skip to main content

SonixLessonSynthesizer

Synthesize audio lessons from note sequences (e.g. Sa Re Ga in Indian classical practice), each with its own audio recording.

Quick Start​

Kotlin​

val notes = listOf(
LessonNote(
noteName = "Sa",
noteLabel = "S",
noteAudioFilePath = "/path/to/sa.wav",
numBeats = 2,
numSamplesConsonant = 100
),
LessonNote(
noteName = "Re",
noteLabel = "R",
noteAudioFilePath = "/path/to/re.wav",
numBeats = 2,
numSamplesConsonant = 100
)
)

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

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

synth.release()

Swift​

let notes = [
LessonNote(
noteName: "Sa",
noteLabel: "S",
noteAudioFilePath: "/path/to/sa.wav",
numBeats: 2,
numSamplesConsonant: 100
),
LessonNote(
noteName: "Re",
noteLabel: "R",
noteAudioFilePath: "/path/to/re.wav",
numBeats: 2,
numSamplesConsonant: 100
)
]

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

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

synth.release()

Configuration​

Factory Method​

ParameterTypeDefaultDescription
notesList<LessonNote>—Note sequence (required)
beatLengthMsInt—Beat duration in milliseconds (required)

Builder​

For advanced configuration:

Kotlin​

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

Builder Parameters​

MethodTypeDefaultDescription
notesList<LessonNote>—Note sequence (required)
beatLengthMsInt—Beat duration in ms (required)
silenceBeatsstart: Int, end: Int2, 2Silence beats at start/end
sampleRateInt16000Output sample rate in Hz
onError(String) -> Unit—Error callback

Workflow​

The synthesis process has two steps:

1. Load Audio​

Load note 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

LessonNote​

Each note in the sequence is defined by:

PropertyTypeDescription
noteNameStringFull name (e.g., "Sa", "Re")
noteLabelStringShort label (e.g., "S", "R")
noteAudioFilePathStringPath 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​