Implements split voices on Solfa ${S:d}d
This commit is contained in:
parent
84b2094798
commit
a883090d0f
4 changed files with 140 additions and 49 deletions
|
|
@ -1,6 +1,6 @@
|
|||
package mg.dot.feufaro.solfa
|
||||
|
||||
class PNotes (var note: String, private var markers: MutableList<String> = mutableListOf("")) {
|
||||
class PNotes (var note: String, var noteSplit: MutableList<String> = mutableListOf(), private var markers: MutableList<String> = mutableListOf()) {
|
||||
fun addMarker(newMarker: String) {
|
||||
markers.add(newMarker)
|
||||
}
|
||||
|
|
@ -8,7 +8,20 @@ class PNotes (var note: String, private var markers: MutableList<String> = mutab
|
|||
return markers.contains(marker)
|
||||
}
|
||||
fun toNote(): Note {
|
||||
val newNote = Note(note)
|
||||
val validSplits = noteSplit.filter { it.isNotBlank() }
|
||||
|
||||
val finalNoteStr = if (validSplits.isNotEmpty()) {
|
||||
val formattedSplits = if (validSplits.size > 1) {
|
||||
validSplits.joinToString("|")
|
||||
} else {
|
||||
validSplits.joinToString("")
|
||||
}
|
||||
"$note>{$formattedSplits}"
|
||||
} else {
|
||||
note
|
||||
}
|
||||
|
||||
val newNote = Note(finalNoteStr)
|
||||
newNote.setMarkers(markers)
|
||||
return newNote
|
||||
}
|
||||
|
|
@ -16,4 +29,12 @@ class PNotes (var note: String, private var markers: MutableList<String> = mutab
|
|||
fun appendNote(noteSuffix: Char) {
|
||||
note += noteSuffix
|
||||
}
|
||||
fun addSplitNote(splitNote: String) {
|
||||
noteSplit.add(splitNote)
|
||||
}
|
||||
fun appendSplitNote(suffix: Char) {
|
||||
if (noteSplit.isNotEmpty()) {
|
||||
noteSplit[noteSplit.lastIndex] += suffix
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,9 +16,15 @@ class POneVoiceNote {
|
|||
oneVoiceNote.lastOrNull()?.addMarker(marker.toString())
|
||||
}
|
||||
fun addItem(noteString: String = "") {
|
||||
val newNote: PNotes = PNotes(noteString, nextMarkers)
|
||||
val newNote: PNotes = PNotes(note = noteString, noteSplit = mutableListOf(), markers = nextMarkers)
|
||||
oneVoiceNote.add(newNote)
|
||||
nextNote = ""
|
||||
nextMarkers = mutableListOf()
|
||||
}
|
||||
fun appendLastSplitNote(splitNote: String) {
|
||||
oneVoiceNote.lastOrNull()?.addSplitNote(splitNote)
|
||||
}
|
||||
fun appendLastSplitNoteSuffix(suffix: Char) {
|
||||
oneVoiceNote.lastOrNull()?.appendSplitNote(suffix)
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,6 @@ import java.util.prefs.Preferences
|
|||
import kotlin.getValue
|
||||
import kotlin.math.min
|
||||
|
||||
//@todo: split voices (ffpm19/ews22) ${S:mfs} in N4:, idem ffpm-212
|
||||
//@todo: ffpm-164.txt O10:s3:mflswss // alternative notes for stanza 3 only
|
||||
//@todo: ews-47.txt DS/$ + [12][3]
|
||||
//@todo: ffpm-99-2.txt triolet.mid + triolet (m--)--
|
||||
|
|
@ -67,8 +66,16 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
val REGEX_STRIP_DC = Regex("\\$\\{D[^:]*:[^\\}]*\\}")
|
||||
val REGEX_NOTE_TOADD = Regex("([drmfsltz][ia]?|[―])([₄₃₂₁¹²³⁴',]*)>([drmfsltz][ia]?|[―])([₄₃₂₁¹²³⁴',]*)")
|
||||
val REGEX_NOTE_TODROP = Regex("([drmfsltz][ia]?|[―])([₄₃₂₁¹²³⁴',]*)<")
|
||||
val REGEX_NOTE_SPLIT = Regex("\\$\\{[Ss]:([^\\}]+)\\}([drmfsltDRFSTz][,']*)")
|
||||
}
|
||||
|
||||
fun parseNoteSplit(input: String): String {
|
||||
return REGEX_NOTE_SPLIT.replace(input) { matchResult ->
|
||||
val splitValues = matchResult.groupValues[1].chunked(1).joinToString("")
|
||||
val mainNote = matchResult.groupValues[2]
|
||||
"$mainNote<{$splitValues}"
|
||||
}
|
||||
}
|
||||
var nextTIndex: Int = -1
|
||||
var nextNIndex: Int = -1
|
||||
var nextLIndex: Int = -1
|
||||
|
|
@ -1806,11 +1813,19 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
|
||||
private fun preloadN(noteLine: String) {
|
||||
val voiceNumber = noteLine.substring(0, 1).toInt()
|
||||
val parsedNoteLine = parseNoteSplit(noteLine)
|
||||
val templateComments = mutableListOf<String>()
|
||||
val templateStripped = REGEX_TEMPLATE_COMMENT.replace(templateString) { matchResult ->
|
||||
templateComments.add(matchResult.value)
|
||||
"&"
|
||||
}
|
||||
val splitBlocks = mutableListOf<String>()
|
||||
val noteLineWithoutSplits = parsedNoteLine
|
||||
.replace(REGEX_TEMPLATE_COMMENT, "")
|
||||
.replace(Regex("<\\s*\\{[^\\}]*\\}")) { matchResult ->
|
||||
splitBlocks.add(matchResult.value)
|
||||
"§"
|
||||
}
|
||||
fun insertZToCharArray(input: String): CharArray {
|
||||
val delim = "/:!|"
|
||||
val reDelim = "[$delim](?=[$delim])".toRegex()
|
||||
|
|
@ -1818,9 +1833,9 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
return insertedZ.toCharArray()
|
||||
}
|
||||
val templateCharArray = insertZToCharArray(templateStripped)
|
||||
val noteLine = noteLine.replace(REGEX_TEMPLATE_COMMENT, "")
|
||||
val cleanNoteLine = noteLineWithoutSplits.replace(REGEX_TEMPLATE_COMMENT, "")
|
||||
.replace(" ", "")
|
||||
val lineRepeated = REGEX_REPETITION.replace(noteLine.substring(1)) { matchResult ->
|
||||
val lineRepeated = REGEX_REPETITION.replace(cleanNoteLine.substring(1)) { matchResult ->
|
||||
val (charIterated, iteration) = matchResult.destructured
|
||||
val nTimes = iteration.toInt()
|
||||
charIterated.repeat(nTimes)
|
||||
|
|
@ -1830,6 +1845,10 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
var inAnchor = false
|
||||
var anchorNote = ' '
|
||||
lineRepeated.toCharArray().forEach {
|
||||
if (it == '§') {
|
||||
noteChar2 += "§"
|
||||
return@forEach
|
||||
}
|
||||
if (inAnchor) {
|
||||
if (anchor.isEmpty()) {
|
||||
anchorNote = it
|
||||
|
|
@ -1877,16 +1896,34 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
'd', 'r', 'm', 'f', 's', 'l', 't',
|
||||
-> {
|
||||
if (firstInLoop) {
|
||||
val nextChar = if (noteCharIterator.hasNext()) noteCharIterator.next() else 'd'
|
||||
if (nextChar == '§') {
|
||||
result += splitBlocks.removeAt(0)
|
||||
replacement = if (noteCharIterator.hasNext()) noteCharIterator.next() else 'd'
|
||||
} else {
|
||||
replacement = nextChar
|
||||
}
|
||||
firstInLoop = false
|
||||
}
|
||||
if (replacement == '(') {
|
||||
result += replacement
|
||||
val nextChar = if (noteCharIterator.hasNext()) noteCharIterator.next() else 'd'
|
||||
if (nextChar == '§') {
|
||||
result += splitBlocks.removeAt(0)
|
||||
replacement = if (noteCharIterator.hasNext()) noteCharIterator.next() else 'd'
|
||||
} else {
|
||||
replacement = nextChar
|
||||
}
|
||||
}
|
||||
for (repetition in 0 until 6) {
|
||||
result += replacement
|
||||
val nextChar = if (noteCharIterator.hasNext()) noteCharIterator.next() else 'd'
|
||||
if (nextChar == '§') {
|
||||
result += splitBlocks.removeAt(0)
|
||||
replacement = if (noteCharIterator.hasNext()) noteCharIterator.next() else 'd'
|
||||
break
|
||||
}
|
||||
replacement = nextChar
|
||||
if (replacement in setOf(
|
||||
'd', 'r', 'm', 'f', 's', 'l', 't', 'z', '(',
|
||||
'D', 'R', 'M', 'F', 'S', 'L', 'T', '-', 'w', 'Z'
|
||||
|
|
@ -2067,17 +2104,29 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
charIterated.repeat(nTimes)
|
||||
}
|
||||
var commentNumber = -1
|
||||
var inSplit = false
|
||||
val lineChar = lineRepeated.toCharArray()
|
||||
lineChar.forEach {
|
||||
when (it) {
|
||||
'|', ':', '!', '/' -> {
|
||||
if (lastIt == '|' || lastIt == ':' || lastIt == '!' || lastIt == '/') {
|
||||
'|', ':', '!', '/', '&' -> {
|
||||
if (it == '|' && lastIt == '[') {
|
||||
// le séparateur split
|
||||
} else if (lastIt == '|' || lastIt == ':' || lastIt == '!' || lastIt == '/') {
|
||||
} else {
|
||||
midiDuration += nextDuration
|
||||
nextDuration = 60
|
||||
}
|
||||
}
|
||||
|
||||
// blocs de split <[...]
|
||||
'<' -> { }
|
||||
'{' -> {
|
||||
inSplit = true
|
||||
}
|
||||
'}' -> {
|
||||
inSplit = false
|
||||
}
|
||||
|
||||
'.' -> {
|
||||
if (lastIt == ';') {
|
||||
pushMidi()
|
||||
|
|
@ -2106,8 +2155,12 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
}
|
||||
|
||||
'\'', ',' -> {
|
||||
if(!inSplit ){
|
||||
newN.appendLastNote(it)
|
||||
lastNoteString += it
|
||||
} else {
|
||||
newN.appendLastSplitNoteSuffix(it)
|
||||
}
|
||||
}
|
||||
|
||||
'(', '[' -> newN.addNextMarker(it)
|
||||
|
|
@ -2135,6 +2188,9 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
if (it == 'T') {
|
||||
noteString += "a"
|
||||
}
|
||||
if(inSplit) {
|
||||
newN.appendLastSplitNote(noteString)
|
||||
} else {
|
||||
newN.addItem(noteString)
|
||||
when (noteString) {
|
||||
"-" -> {
|
||||
|
|
@ -2153,15 +2209,17 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
lastNoteString = "z"
|
||||
}
|
||||
|
||||
"'", "(", ")", "[", "]", "," -> {}
|
||||
"'", "(", ")", "{", "}", "," -> {}
|
||||
else -> {
|
||||
pushMidi()
|
||||
lastNoteString = noteString
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
'@' -> {
|
||||
if(!inSplit) {
|
||||
if (lastNoteString == "z") {
|
||||
midiDuration += nextDuration
|
||||
nextDuration = 0
|
||||
|
|
@ -2170,6 +2228,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
|||
}
|
||||
lastNoteString = "z"
|
||||
}
|
||||
}
|
||||
|
||||
'i', 'a' ->
|
||||
lastNoteString += it
|
||||
|
|
|
|||
|
|
@ -471,7 +471,12 @@ fun TimeUnitComposable(
|
|||
){
|
||||
val annotatedText = remember(multiLineText, MaterialTheme.colorScheme.primary) {
|
||||
buildAnnotatedString {
|
||||
multiLineText.split(">").mapIndexed { index, text ->
|
||||
val lines = multiLineText.lines()
|
||||
lines.forEachIndexed { lineIndex, line ->
|
||||
if (lineIndex > 0) {
|
||||
append("\n")
|
||||
}
|
||||
line.split(">").mapIndexed { index, text ->
|
||||
if (index % 2 == 0) {
|
||||
append(text)
|
||||
} else {
|
||||
|
|
@ -485,7 +490,7 @@ fun TimeUnitComposable(
|
|||
append(text+" ")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue