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 (svara names)

TransData

PropertyTypeDescription
segmentsList<TransSegment>Transcription segments

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)

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