Skip to content

sdercolin/harmoloid-core-kt

Repository files navigation

HARMOLOID Core

Maven Central

Core library for HARMOLOID built in Kotlin Multiplatform.

What is HARMOLOID?

HARMOLOID is an application for generating simple chorus based on projects of singing voice synthesizers.

The current version 2.x of the application is built as a web application in Kotlin/JS.

The core library

This project is a Kotlin implementation of the core algorithm of HARMOLOID. It can be applied on any MIDI-like formats with external IO modules.

Basic features

  • Tonality analysis (auto: with detection of modulation)
  • Tonality analysis (semi-auto: for single tonality)
  • Note shift based on tonality and harmonic type
  • Parameter configuration

Getting Started

This library targets jvm, js, and native. Basically you can use it in any Kotlin Gradle project or Java Gradle project.

Kotlin DSL:

repositories {
    mavenCentral()
}

dependencies {
    implementation("com.sdercolin.harmoloid:harmoloid-core:1.2")
}

Groovy DSL:

repositories {
    mavenCentral()
}

dependencies {
    implementation "com.sdercolin.harmoloid:harmoloid-core:1.2"
}

Basic usages

Initialization

You have to implement IO modules to handle data tranformation between the original structure and HARMOLOID structure.

// Extract content from the MIDI-like data
val tracks = Track.build(index, name, notes, timeSignatures)

// Initialize core object
val core = Core(tracks)

Configuration (optional)

You can configure all the parameters used. See Config.kt for details.

val config = Config(
    keyShiftForUpperThirdHarmony = Config.keyShiftForUpperThirdHarmonyStandard,
    keyShiftForLowerThirdHarmony = Config.keyShiftForLowerThirdHarmonyStandard
)

// Pass config to constructor
val core = Core(tracks, config)

// Or reload config later
core.reloadConfig(config)

Setup tonality

Tracks have to be marked with tonality before harmony generation.

val track = core.getTrack(trackIndex)
val bar = track.bars

// Method 1: auto
when (val result = core.setPassagesAuto(trackIndex)) {
    is TrackTonalityAnalysisResult.Success -> {
        val passageResults = result.passageResults
        // Notify results
    }
    is TrackTonalityAnalysisResult.Failure -> {
        // Notify error
    }
}

// Method 2: semi-auto, have to construct passages by yourself
val passages = listOf(
    Passage(index = 0, bars = bars.subList(0, 20)),
    Passage(index = 1, bars = bars.subList(21, bars.size))
)
when (val result = core.setPassagesSemiAuto(trackIndex, passages)) {
    is TrackTonalityAnalysisResult.Success -> {
        val passageResults = result.passageResults
        // Notify results
    }
    is TrackTonalityAnalysisResult.Failure -> {
        // Notify error
    }
}

// Method 3: manual, have to construct passages with tonalities by yourself 
val passages = listOf(
    Passage(index = 0, bars = bars.subList(0, 20), tonality = Tonality.C),
    Passage(index = 1, bars = bars.subList(21, bars.size), tonality = Tonality.D)
)
core.savePassages(trackIndex, passages)

// Check if track is setup
if (!core.getTrack(trackIndex).isTonalityMarked) {
    // Tonality is not fully analysed or set, check result given by Method 1 or Method 2
    // and do Method 3 again
}

Generate chorus tracks

// Save harmonic settings
core.saveHarmonicTypes(trackIndex, setOf(HarmonicType.UpperThird, HarmonicType.LowerThird))

// Get note shifts
core.getAllChorusTracks(trackIndex).forEach { (harmony, noteShifts) ->
    // Do your output work with the note shifts
    // The following code is an example with a pseudo NoteElement model
    val shiftedNoteElements = noteElements.mapNotNull { noteElement ->
        val keyDelta = noteShifts.find { it.noteIndex == noteElement }?.keyDelta
        if (keyDelta == null) {
            // delete the note
            null
        } else {
            noteElement.copy(key = noteElement.key + keyDelta)
        }
    }
}

License

Apache License, Version 2.0

About

Core library for HARMOLOID

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages