Skip to main content

Utilities

Helper classes for parsing music data files, converting between frame indices and time, and error handling.

SonixParser

Parses pitch, note transcription, and transcription data from text files used in music education.

Methods

MethodInputReturnsDescription
parsePitchStringcontent: StringPitchData?Parse .pitchPP file content
parseNotesStringcontent: StringNotesData?Parse .notes file content
parseTransStringcontent: StringTransData?Parse .trans JSON file content

Parsing Pitch Data

Pitch files (.pitchPP) contain time-pitch pairs:

0.0 440.0
0.01 442.5
0.02 -1.0

Kotlin

val content = File("melody.pitchPP").readText()
val pitchData = SonixParser.parsePitchString(content)
if (pitchData != null) {
for (i in 0 until pitchData.count) {
println("Time: ${pitchData.times[i]}, Pitch: ${pitchData.pitchesHz[i]}")
}
}

Swift

let content = try String(contentsOf: pitchFileURL)
if let pitchData = SonixParser.parsePitchString(content: content) {
print("Found \(pitchData.count) pitch points")
}

Parsing Notes Data

Notes files (.notes) contain tab-separated note transcriptions:

4.899410	5.224489	138.591315	Ṇ
4.980680 7.047256 145.986691 S
val notesData = SonixParser.parseNotesString(content)
if let notesData = SonixParser.parseNotesString(content: content) {
print("Found \(notesData.count) notes")
}

Parsing Transcription Data

Transcription files (.trans) use JSON format with segments:

[{"id": 3, "lyrics": "S... R...", "time_stamp": [3.18, 14.18], "trans": [...]}]
val transData = SonixParser.parseTransString(jsonContent)
if let transData = SonixParser.parseTransString(content: jsonContent) {
print("Found \(transData.segments.count) segments")
}

Data Types

PitchData

PropertyTypeDescription
timesFloatArrayTimestamps in seconds
pitchesHzFloatArrayPitch values in Hz (-1.0 = unvoiced)
countIntNumber of data points

NotesData

PropertyTypeDescription
startTimesFloatArrayNote start times in seconds
endTimesFloatArrayNote end times in seconds
frequenciesFloatArrayNote frequencies in Hz
labelsArray<String>Note labels

TransData

PropertyTypeDescription
segmentsList<TransSegment>Transcription segments
MethodReturnsDescription
toNotesData()NotesDataFlatten all segments' notes into a single NotesData

TransSegment

PropertyTypeDescription
idIntSegment identifier from the JSON
typeString?Raw segment-type string from the JSON type field, deserialized verbatim (e.g. "teacher_vocal", "student_vocal", "commentary"); null when the field is absent. The SDK does not validate or interpret the value.
lyricsStringLyrics for the segment
timeStampList<Double>Two-element segment time bounds (parsed from time_stamp)
transList<TransNote>Per-note transcription within the segment
startTimeDoubleFirst element of timeStamp
endTimeDoubleLast element of timeStamp

TransNote

PropertyTypeDescription
tStartDoubleNote start (seconds; parsed from t_start)
tEndDoubleNote end (seconds; parsed from t_end)
freqHzDoubleFrequency in Hz
labelStringNote label

SonixFrames

Convert between audio frame indices and time values. Useful for aligning analysis results with audio timestamps.

Methods

MethodParametersReturnsDescription
framesToTimeframe: Int, sampleRate: Int, hopLength: IntDoubleFrame index to seconds
timeToFramestime: Double, sampleRate: Int, hopLength: IntIntSeconds to frame index
framesToTimeframes: List<Int>, ...List<Double>Batch frame-to-time
timeToFramestimes: List<Double>, ...List<Int>Batch time-to-frame

Usage

// Convert frame index to time
val timeSeconds = SonixFrames.framesToTime(
frame = 100,
sampleRate = 16000,
hopLength = 160
)

// Convert time to frame index
val frameIndex = SonixFrames.timeToFrames(
time = 1.5,
sampleRate = 16000,
hopLength = 160
)

// Batch conversion
val times = SonixFrames.framesToTime(
frames = listOf(0, 10, 20, 30),
sampleRate = 16000,
hopLength = 160
)

Parameters

ParameterDescriptionTypical Values
sampleRateAudio sample rate in Hz16000, 44100
hopLengthHop length in samples160, 512

SonixError

Error information reported by Sonix APIs via StateFlows. Used instead of throwing exceptions for reactive error handling.

Properties

PropertyTypeDescription
messageStringHuman-readable error description
causeThrowable?Original exception (if available)

Exceptions

SonixException is a typed exception thrown for setup errors that cannot be modeled as state-flow errors (e.g., decoding a corrupt file). SonixKilledException is a typealias for VoxaTraceKilledException and is thrown by factory methods when licensing fails (see Authentication).

Usage

player.error.collect { error ->
error?.let {
println("Error: ${it.message}")
it.cause?.let { cause -> cause.printStackTrace() }
}
}
let task = player.observeError { error in
if let error = error {
print("Error: \(error.message)")
}
}

Next Steps