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
|
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) {
|
fun addMarker(newMarker: String) {
|
||||||
markers.add(newMarker)
|
markers.add(newMarker)
|
||||||
}
|
}
|
||||||
|
|
@ -8,7 +8,20 @@ class PNotes (var note: String, private var markers: MutableList<String> = mutab
|
||||||
return markers.contains(marker)
|
return markers.contains(marker)
|
||||||
}
|
}
|
||||||
fun toNote(): Note {
|
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)
|
newNote.setMarkers(markers)
|
||||||
return newNote
|
return newNote
|
||||||
}
|
}
|
||||||
|
|
@ -16,4 +29,12 @@ class PNotes (var note: String, private var markers: MutableList<String> = mutab
|
||||||
fun appendNote(noteSuffix: Char) {
|
fun appendNote(noteSuffix: Char) {
|
||||||
note += noteSuffix
|
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())
|
oneVoiceNote.lastOrNull()?.addMarker(marker.toString())
|
||||||
}
|
}
|
||||||
fun addItem(noteString: String = "") {
|
fun addItem(noteString: String = "") {
|
||||||
val newNote: PNotes = PNotes(noteString, nextMarkers)
|
val newNote: PNotes = PNotes(note = noteString, noteSplit = mutableListOf(), markers = nextMarkers)
|
||||||
oneVoiceNote.add(newNote)
|
oneVoiceNote.add(newNote)
|
||||||
nextNote = ""
|
nextNote = ""
|
||||||
nextMarkers = mutableListOf()
|
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.getValue
|
||||||
import kotlin.math.min
|
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: ffpm-164.txt O10:s3:mflswss // alternative notes for stanza 3 only
|
||||||
//@todo: ews-47.txt DS/$ + [12][3]
|
//@todo: ews-47.txt DS/$ + [12][3]
|
||||||
//@todo: ffpm-99-2.txt triolet.mid + triolet (m--)--
|
//@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_STRIP_DC = Regex("\\$\\{D[^:]*:[^\\}]*\\}")
|
||||||
val REGEX_NOTE_TOADD = Regex("([drmfsltz][ia]?|[―])([₄₃₂₁¹²³⁴',]*)>([drmfsltz][ia]?|[―])([₄₃₂₁¹²³⁴',]*)")
|
val REGEX_NOTE_TOADD = Regex("([drmfsltz][ia]?|[―])([₄₃₂₁¹²³⁴',]*)>([drmfsltz][ia]?|[―])([₄₃₂₁¹²³⁴',]*)")
|
||||||
val REGEX_NOTE_TODROP = Regex("([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 nextTIndex: Int = -1
|
||||||
var nextNIndex: Int = -1
|
var nextNIndex: Int = -1
|
||||||
var nextLIndex: Int = -1
|
var nextLIndex: Int = -1
|
||||||
|
|
@ -1806,11 +1813,19 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
|
|
||||||
private fun preloadN(noteLine: String) {
|
private fun preloadN(noteLine: String) {
|
||||||
val voiceNumber = noteLine.substring(0, 1).toInt()
|
val voiceNumber = noteLine.substring(0, 1).toInt()
|
||||||
|
val parsedNoteLine = parseNoteSplit(noteLine)
|
||||||
val templateComments = mutableListOf<String>()
|
val templateComments = mutableListOf<String>()
|
||||||
val templateStripped = REGEX_TEMPLATE_COMMENT.replace(templateString) { matchResult ->
|
val templateStripped = REGEX_TEMPLATE_COMMENT.replace(templateString) { matchResult ->
|
||||||
templateComments.add(matchResult.value)
|
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 {
|
fun insertZToCharArray(input: String): CharArray {
|
||||||
val delim = "/:!|"
|
val delim = "/:!|"
|
||||||
val reDelim = "[$delim](?=[$delim])".toRegex()
|
val reDelim = "[$delim](?=[$delim])".toRegex()
|
||||||
|
|
@ -1818,9 +1833,9 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
return insertedZ.toCharArray()
|
return insertedZ.toCharArray()
|
||||||
}
|
}
|
||||||
val templateCharArray = insertZToCharArray(templateStripped)
|
val templateCharArray = insertZToCharArray(templateStripped)
|
||||||
val noteLine = noteLine.replace(REGEX_TEMPLATE_COMMENT, "")
|
val cleanNoteLine = noteLineWithoutSplits.replace(REGEX_TEMPLATE_COMMENT, "")
|
||||||
.replace(" ", "")
|
.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 (charIterated, iteration) = matchResult.destructured
|
||||||
val nTimes = iteration.toInt()
|
val nTimes = iteration.toInt()
|
||||||
charIterated.repeat(nTimes)
|
charIterated.repeat(nTimes)
|
||||||
|
|
@ -1830,6 +1845,10 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
var inAnchor = false
|
var inAnchor = false
|
||||||
var anchorNote = ' '
|
var anchorNote = ' '
|
||||||
lineRepeated.toCharArray().forEach {
|
lineRepeated.toCharArray().forEach {
|
||||||
|
if (it == '§') {
|
||||||
|
noteChar2 += "§"
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
if (inAnchor) {
|
if (inAnchor) {
|
||||||
if (anchor.isEmpty()) {
|
if (anchor.isEmpty()) {
|
||||||
anchorNote = it
|
anchorNote = it
|
||||||
|
|
@ -1877,16 +1896,34 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
'd', 'r', 'm', 'f', 's', 'l', 't',
|
'd', 'r', 'm', 'f', 's', 'l', 't',
|
||||||
-> {
|
-> {
|
||||||
if (firstInLoop) {
|
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'
|
replacement = if (noteCharIterator.hasNext()) noteCharIterator.next() else 'd'
|
||||||
|
} else {
|
||||||
|
replacement = nextChar
|
||||||
|
}
|
||||||
firstInLoop = false
|
firstInLoop = false
|
||||||
}
|
}
|
||||||
if (replacement == '(') {
|
if (replacement == '(') {
|
||||||
result += 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'
|
replacement = if (noteCharIterator.hasNext()) noteCharIterator.next() else 'd'
|
||||||
|
} else {
|
||||||
|
replacement = nextChar
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (repetition in 0 until 6) {
|
for (repetition in 0 until 6) {
|
||||||
result += 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'
|
replacement = if (noteCharIterator.hasNext()) noteCharIterator.next() else 'd'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
replacement = nextChar
|
||||||
if (replacement in setOf(
|
if (replacement in setOf(
|
||||||
'd', 'r', 'm', 'f', 's', 'l', 't', 'z', '(',
|
'd', 'r', 'm', 'f', 's', 'l', 't', 'z', '(',
|
||||||
'D', 'R', 'M', 'F', 'S', 'L', 'T', '-', 'w', '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)
|
charIterated.repeat(nTimes)
|
||||||
}
|
}
|
||||||
var commentNumber = -1
|
var commentNumber = -1
|
||||||
|
var inSplit = false
|
||||||
val lineChar = lineRepeated.toCharArray()
|
val lineChar = lineRepeated.toCharArray()
|
||||||
lineChar.forEach {
|
lineChar.forEach {
|
||||||
when (it) {
|
when (it) {
|
||||||
'|', ':', '!', '/' -> {
|
'|', ':', '!', '/', '&' -> {
|
||||||
if (lastIt == '|' || lastIt == ':' || lastIt == '!' || lastIt == '/') {
|
if (it == '|' && lastIt == '[') {
|
||||||
|
// le séparateur split
|
||||||
|
} else if (lastIt == '|' || lastIt == ':' || lastIt == '!' || lastIt == '/') {
|
||||||
} else {
|
} else {
|
||||||
midiDuration += nextDuration
|
midiDuration += nextDuration
|
||||||
nextDuration = 60
|
nextDuration = 60
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// blocs de split <[...]
|
||||||
|
'<' -> { }
|
||||||
|
'{' -> {
|
||||||
|
inSplit = true
|
||||||
|
}
|
||||||
|
'}' -> {
|
||||||
|
inSplit = false
|
||||||
|
}
|
||||||
|
|
||||||
'.' -> {
|
'.' -> {
|
||||||
if (lastIt == ';') {
|
if (lastIt == ';') {
|
||||||
pushMidi()
|
pushMidi()
|
||||||
|
|
@ -2106,8 +2155,12 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
'\'', ',' -> {
|
'\'', ',' -> {
|
||||||
|
if(!inSplit ){
|
||||||
newN.appendLastNote(it)
|
newN.appendLastNote(it)
|
||||||
lastNoteString += it
|
lastNoteString += it
|
||||||
|
} else {
|
||||||
|
newN.appendLastSplitNoteSuffix(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
'(', '[' -> newN.addNextMarker(it)
|
'(', '[' -> newN.addNextMarker(it)
|
||||||
|
|
@ -2135,6 +2188,9 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
if (it == 'T') {
|
if (it == 'T') {
|
||||||
noteString += "a"
|
noteString += "a"
|
||||||
}
|
}
|
||||||
|
if(inSplit) {
|
||||||
|
newN.appendLastSplitNote(noteString)
|
||||||
|
} else {
|
||||||
newN.addItem(noteString)
|
newN.addItem(noteString)
|
||||||
when (noteString) {
|
when (noteString) {
|
||||||
"-" -> {
|
"-" -> {
|
||||||
|
|
@ -2153,15 +2209,17 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
lastNoteString = "z"
|
lastNoteString = "z"
|
||||||
}
|
}
|
||||||
|
|
||||||
"'", "(", ")", "[", "]", "," -> {}
|
"'", "(", ")", "{", "}", "," -> {}
|
||||||
else -> {
|
else -> {
|
||||||
pushMidi()
|
pushMidi()
|
||||||
lastNoteString = noteString
|
lastNoteString = noteString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
'@' -> {
|
'@' -> {
|
||||||
|
if(!inSplit) {
|
||||||
if (lastNoteString == "z") {
|
if (lastNoteString == "z") {
|
||||||
midiDuration += nextDuration
|
midiDuration += nextDuration
|
||||||
nextDuration = 0
|
nextDuration = 0
|
||||||
|
|
@ -2170,6 +2228,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
}
|
}
|
||||||
lastNoteString = "z"
|
lastNoteString = "z"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
'i', 'a' ->
|
'i', 'a' ->
|
||||||
lastNoteString += it
|
lastNoteString += it
|
||||||
|
|
|
||||||
|
|
@ -471,8 +471,13 @@ fun TimeUnitComposable(
|
||||||
){
|
){
|
||||||
val annotatedText = remember(multiLineText, MaterialTheme.colorScheme.primary) {
|
val annotatedText = remember(multiLineText, MaterialTheme.colorScheme.primary) {
|
||||||
buildAnnotatedString {
|
buildAnnotatedString {
|
||||||
multiLineText.split(">").mapIndexed { index, text ->
|
val lines = multiLineText.lines()
|
||||||
if (index %2 == 0) {
|
lines.forEachIndexed { lineIndex, line ->
|
||||||
|
if (lineIndex > 0) {
|
||||||
|
append("\n")
|
||||||
|
}
|
||||||
|
line.split(">").mapIndexed { index, text ->
|
||||||
|
if (index % 2 == 0) {
|
||||||
append(text)
|
append(text)
|
||||||
} else {
|
} else {
|
||||||
withStyle(
|
withStyle(
|
||||||
|
|
@ -485,7 +490,7 @@ fun TimeUnitComposable(
|
||||||
append(text+" ")
|
append(text+" ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue