Skip to content

Commit

Permalink
Add indian notation systems (carnatic and hindustani)
Browse files Browse the repository at this point in the history
  • Loading branch information
thetwom committed Mar 2, 2023
1 parent fd014e8 commit eece2dc
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ class PreferenceResources(
val notationType = when(notation) {
"international" -> NotationType.International
"solfege" -> NotationType.Solfege
"carnatic" -> NotationType.Carnatic
"hindustani" -> NotationType.Hindustani
else -> NotationType.Standard
}
val sharpFlatPreference = if (preferFlat)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ data class MusicalNote(val base: BaseNote, val modifier: NoteModifier, val octav
}

/** Return a note, where enharmonic and base represenation are exchanged. */
fun switchEnharmonic(): MusicalNote {
if (enharmonicBase == BaseNote.None)
fun switchEnharmonic(switchAlsoForBaseNone: Boolean = false): MusicalNote {
if (enharmonicBase == BaseNote.None && !switchAlsoForBaseNone)
return this
return MusicalNote(base = enharmonicBase, modifier = enharmonicModifier, octave = octave,
octaveOffset = enharmonicOctaveOffset,
Expand Down
88 changes: 49 additions & 39 deletions app/src/main/java/de/moekadu/tuner/temperaments/NoteNamePrinter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -198,75 +198,85 @@ class NoteNamePrinter(
}

private fun resolveNoteProperties(note: MusicalNote): ResolvedNoteProperties {
// check if there is a direct note name capturing base and modifier
return if (preferEnharmonic(note)) {
resolveNotePropertiesWithoutEnharmonicCheck(note.switchEnharmonic(switchAlsoForBaseNone = true))
} else {
resolveNotePropertiesWithoutEnharmonicCheck(note)
}
}

private fun resolveNotePropertiesWithoutEnharmonicCheck(note: MusicalNote): ResolvedNoteProperties {
// check if we can directly resolve the note
val stem = NoteNameStem.fromMusicalNote(note)
val noteNameOriginal = noteResourceIds[stem]?.let{ context.getString(it) }
if (noteNameOriginal != null && noteNameOriginal != "" && noteNameOriginal != "-") {
val noteName = noteResourceIds[stem]?.let { context.getString(it) }
if (noteName != null && noteName != "" && noteName != "-") {
return ResolvedNoteProperties(
baseName = noteNameOriginal,
baseName = noteName,
modifier = NoteModifier.None,
octave = if (note.octave == Int.MAX_VALUE) Int.MAX_VALUE else note.octave + note.octaveOffset
)
}

// check if there is a direct note name of the enharmonic capturing base and modifier
val noteEnharmonic = note.switchEnharmonic()
// check if we can directly resolve the enharmonic
val noteEnharmonic = note.switchEnharmonic(switchAlsoForBaseNone = true)
val stemEnharmonic = NoteNameStem.fromMusicalNote(noteEnharmonic)
val noteNameEnharmonic = noteResourceIds[stemEnharmonic]?.let{ context.getString(it) }
if (noteNameEnharmonic != null && noteNameEnharmonic !="" && noteNameEnharmonic != "-") {
val noteNameEnharmonic = noteResourceIds[stemEnharmonic]?.let { context.getString(it) }

if (noteNameEnharmonic != null && noteNameEnharmonic != "" && noteNameEnharmonic != "-") {
return ResolvedNoteProperties(
baseName = noteNameEnharmonic,
modifier = NoteModifier.None,
octave = if (note.octave == Int.MAX_VALUE) Int.MAX_VALUE else note.octave + note.octaveOffset
octave = if (note.octave == Int.MAX_VALUE) Int.MAX_VALUE else noteEnharmonic.octave + noteEnharmonic.octaveOffset
)
}

// construct note name based on base note and modifier -> either for enharmonic, or directly
if (preferEnharmonic(note)) {
val stemEnharmonicBase = NoteNameStem(
noteEnharmonic.base, NoteModifier.None, BaseNote.None, NoteModifier.None
)
val noteNameEnharmonicBase =
noteResourceIds[stemEnharmonicBase]?.let { context.getString(it) }
if (noteNameEnharmonicBase != null && noteNameEnharmonicBase != "" && noteNameEnharmonicBase != "-") {
return ResolvedNoteProperties(
baseName = noteNameEnharmonicBase,
modifier = noteEnharmonic.modifier,
octave = if (noteEnharmonic.octave == Int.MAX_VALUE) Int.MAX_VALUE else noteEnharmonic.octave + noteEnharmonic.octaveOffset
)
}
} else {
val stemBase = NoteNameStem(
note.base, NoteModifier.None, BaseNote.None, NoteModifier.None
// try to resolve note by base name + modifier
val stemBase = NoteNameStem(
note.base, NoteModifier.None, BaseNote.None, NoteModifier.None
)
val noteNameBase = noteResourceIds[stemBase]?.let { context.getString(it) }
if (noteNameBase != null && noteNameBase != "" && noteNameBase != "-") {
return ResolvedNoteProperties(
baseName = noteNameBase,
modifier = note.modifier,
octave = if (note.octave == Int.MAX_VALUE) Int.MAX_VALUE else note.octave + note.octaveOffset
)
val noteNameBase =
noteResourceIds[stemBase]?.let { context.getString(it) }
if (noteNameBase != null && noteNameBase != "" && noteNameBase != "-") {
return ResolvedNoteProperties(
baseName = noteNameBase,
modifier = note.modifier,
octave = if (note.octave == Int.MAX_VALUE) Int.MAX_VALUE else note.octave + note.octaveOffset
)
}
}

// note able to resolve note name, print a X
// try to resolve note by enharmonic base name + modifier
val stemEnharmonicBase = NoteNameStem(
noteEnharmonic.base, NoteModifier.None, BaseNote.None, NoteModifier.None
)
val noteNameEnharmonicBase = noteResourceIds[stemEnharmonicBase]?.let { context.getString(it) }
if (noteNameEnharmonicBase != null && noteNameEnharmonicBase != "" && noteNameEnharmonicBase != "-") {
return ResolvedNoteProperties(
baseName = noteNameEnharmonicBase,
modifier = noteEnharmonic.modifier,
octave = if (note.octave == Int.MAX_VALUE) Int.MAX_VALUE else noteEnharmonic.octave + noteEnharmonic.octaveOffset
)
}
return ResolvedNoteProperties("X", NoteModifier.None, note.octave)
}

private fun preferEnharmonic(note: MusicalNote): Boolean {
if (note.enharmonicBase == BaseNote.None)
return false
return sharpFlatPreference == SharpFlatPreference.Flat

return when (sharpFlatPreference) {
SharpFlatPreference.None -> {
false
}
SharpFlatPreference.Sharp -> {
note.enharmonicModifier.flatSharpIndex() > note.modifier.flatSharpIndex()
if (note.enharmonicModifier.flatSharpIndex() == note.modifier.flatSharpIndex())
false
else
note.enharmonicModifier.flatSharpIndex() > note.modifier.flatSharpIndex()
}
SharpFlatPreference.Flat -> {
note.enharmonicModifier.flatSharpIndex() < note.modifier.flatSharpIndex()
if (note.enharmonicModifier.flatSharpIndex() == note.modifier.flatSharpIndex())
true
else
note.enharmonicModifier.flatSharpIndex() < note.modifier.flatSharpIndex()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import de.moekadu.tuner.R
enum class NotationType {
Standard,
International,
Solfege
Solfege,
Carnatic,
Hindustani
}

// if more special note names are needed, (like ashparp_bflat -> B in German), this can easily
Expand Down Expand Up @@ -43,20 +45,43 @@ private val noteInternationalResourceIds = mapOf(
NoteNameStem(BaseNote.B) to R.string.b_note_international,
)

//private val noteCarnaticResourceIds = mapOf(
// NoteNameStem(BaseNote.C) to R.string.c_carnatic,
// NoteNameStem(BaseNote.C, NoteModifier.Sharp, BaseNote.D, NoteModifier.Flat) to R.string.csharp_dflat_carnatic,
// NoteNameStem(BaseNote.D) to R.string.d_carnatic,
// NoteNameStem(BaseNote.D, NoteModifier.Sharp, BaseNote.E, NoteModifier.Flat) to R.string.dsharp_eflat_carnatic,
// NoteNameStem(BaseNote.E) to R.string.e_carnatic,
// NoteNameStem(BaseNote.F) to R.string.f_carnatic,
// NoteNameStem(BaseNote.F, NoteModifier.Sharp, BaseNote.G, NoteModifier.Flat) to R.string.fsharp_gflat_carnatic,
// NoteNameStem(BaseNote.G) to R.string.g_carnatic,
// NoteNameStem(BaseNote.G, NoteModifier.Sharp, BaseNote.A, NoteModifier.Flat) to R.string.gsharp_aflat_carnatic,
// NoteNameStem(BaseNote.A) to R.string.a_carnatic,
// NoteNameStem(BaseNote.A, NoteModifier.Sharp, BaseNote.B, NoteModifier.Flat) to R.string.asharp_bflat_carnatic,
// NoteNameStem(BaseNote.B) to R.string.b_carnatic,
//)
private val noteCarnaticResourceIds = mapOf(
NoteNameStem(BaseNote.C) to R.string.sa_carnatic,
NoteNameStem(BaseNote.C, NoteModifier.Sharp, BaseNote.D, NoteModifier.Flat) to R.string.ri1_carnatic,
NoteNameStem(BaseNote.D) to R.string.ri2_carnatic,
NoteNameStem(BaseNote.None, enharmonicBaseNote = BaseNote.D) to R.string.ga1_carnatic,
NoteNameStem(BaseNote.D, NoteModifier.Sharp, BaseNote.E, NoteModifier.Flat) to R.string.ri3_carnatic,
NoteNameStem(BaseNote.E, NoteModifier.Flat, BaseNote.D, NoteModifier.Sharp) to R.string.ga2_carnatic,
NoteNameStem(BaseNote.E) to R.string.ga3_carnatic,
NoteNameStem(BaseNote.F) to R.string.ma1_carnatic,
NoteNameStem(BaseNote.F, NoteModifier.Sharp, BaseNote.G, NoteModifier.Flat) to R.string.ma2_carnatic,
NoteNameStem(BaseNote.G) to R.string.pa_carnatic,
NoteNameStem(BaseNote.G, NoteModifier.Sharp, BaseNote.A, NoteModifier.Flat) to R.string.dha1_carnatic,
NoteNameStem(BaseNote.A) to R.string.ni1_carnatic,
NoteNameStem(BaseNote.None, enharmonicBaseNote = BaseNote.A) to R.string.dha2_carnatic,
NoteNameStem(BaseNote.A, NoteModifier.Sharp, BaseNote.B, NoteModifier.Flat) to R.string.ni2_carnatic,
NoteNameStem(BaseNote.B, NoteModifier.Flat, BaseNote.A, NoteModifier.Sharp) to R.string.dha3_carnatic,
NoteNameStem(BaseNote.B) to R.string.ni3_carnatic,
)

private val noteHindustaniResourceIds = mapOf(
NoteNameStem(BaseNote.C) to R.string.sa_hindustani,
NoteNameStem(BaseNote.C, NoteModifier.Sharp, BaseNote.D, NoteModifier.Flat) to R.string.re1_hindustani,
NoteNameStem(BaseNote.D) to R.string.re2_hindustani,
NoteNameStem(BaseNote.None, enharmonicBaseNote = BaseNote.D) to R.string.ga1_hindustani,
NoteNameStem(BaseNote.D, NoteModifier.Sharp, BaseNote.E, NoteModifier.Flat) to R.string.re3_hindustani,
NoteNameStem(BaseNote.E, NoteModifier.Flat, BaseNote.D, NoteModifier.Sharp) to R.string.ga2_hindustani,
NoteNameStem(BaseNote.E) to R.string.ga3_hindustani,
NoteNameStem(BaseNote.F) to R.string.ma1_hindustani,
NoteNameStem(BaseNote.F, NoteModifier.Sharp, BaseNote.G, NoteModifier.Flat) to R.string.ma2_hindustani,
NoteNameStem(BaseNote.G) to R.string.pa_hindustani,
NoteNameStem(BaseNote.G, NoteModifier.Sharp, BaseNote.A, NoteModifier.Flat) to R.string.dha1_hindustani,
NoteNameStem(BaseNote.A) to R.string.ni1_hindustani,
NoteNameStem(BaseNote.None, enharmonicBaseNote = BaseNote.A) to R.string.dha2_hindustani,
NoteNameStem(BaseNote.A, NoteModifier.Sharp, BaseNote.B, NoteModifier.Flat) to R.string.ni2_hindustani,
NoteNameStem(BaseNote.B, NoteModifier.Flat, BaseNote.A, NoteModifier.Sharp) to R.string.dha3_hindustani,
NoteNameStem(BaseNote.B) to R.string.ni3_hindustani,
)

fun createNoteNamePrinter(
context: Context,
Expand All @@ -81,5 +106,17 @@ fun createNoteNamePrinter(
NoteNamePrinter.MaxNoteNameWidth.MultipleLetters
)
}
NotationType.Carnatic -> {
NoteNamePrinter(
context, sharpFlatPreference, noteCarnaticResourceIds,
NoteNamePrinter.MaxNoteNameWidth.MultipleLetters
)
}
NotationType.Hindustani -> {
NoteNamePrinter(
context, sharpFlatPreference, noteHindustaniResourceIds,
NoteNamePrinter.MaxNoteNameWidth.MultipleLetters
)
}
}
}
4 changes: 4 additions & 0 deletions app/src/main/res/values/arrays.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,15 @@
<item>"standard"</item>
<item>"solfege"</item>
<item>"international"</item>
<item>"carnatic"</item>
<item>"hindustani"</item>
</string-array>

<string-array name="notation_names">
<item>@string/notation_standard</item>
<item>@string/notation_solfege</item>
<item>@string/notation_international</item>
<item>@string/notation_carnatic</item>
<item>@string/notation_hindustani</item>
</string-array>
</resources>
34 changes: 34 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -252,4 +252,38 @@
<string name="no_capture_duration">Disable capturing</string>
<string name="capture_in_scientific_mode">Capture in scientific mode</string>
<string name="solfege_notation">Solfège notation</string>
<string name="sa_carnatic">Sa</string>
<string name="ri1_carnatic">Ri₁</string>
<string name="ri2_carnatic">Ri₂</string>
<string name="ga1_carnatic">Ga₁</string>
<string name="ga2_carnatic">Ga₂</string>
<string name="ri3_carnatic">Ri₃</string>
<string name="ga3_carnatic">Ga₃</string>
<string name="ma1_carnatic">Ma₁</string>
<string name="ma2_carnatic">Ma₂</string>
<string name="pa_carnatic">Pa</string>
<string name="dha1_carnatic">Dha₁</string>
<string name="dha2_carnatic">Dha₂</string>
<string name="ni1_carnatic">Ni₁</string>
<string name="ni2_carnatic">Ni₂</string>
<string name="dha3_carnatic">Dha₃</string>
<string name="ni3_carnatic">Ni₃</string>
<string name="notation_carnatic">Carnatic</string>
<string name="sa_hindustani">Sa</string>
<string name="re1_hindustani">Re₁</string>
<string name="re2_hindustani">Re₂</string>
<string name="ga1_hindustani">Ga₁</string>
<string name="ga2_hindustani">Ga₂</string>
<string name="re3_hindustani">Re₃</string>
<string name="ga3_hindustani">Ga₃</string>
<string name="ma1_hindustani">Ma₁</string>
<string name="ma2_hindustani">Ma₂</string>
<string name="pa_hindustani">Pa</string>
<string name="dha1_hindustani">Dha₁</string>
<string name="dha2_hindustani">Dha₂</string>
<string name="ni1_hindustani">Ni₁</string>
<string name="ni2_hindustani">Ni₂</string>
<string name="dha3_hindustani">Dha₃</string>
<string name="ni3_hindustani">Ni₃</string>
<string name="notation_hindustani">Hindustani</string>
</resources>

0 comments on commit eece2dc

Please # to comment.