Update ui & Dynamic factor slider - Settings
This commit is contained in:
parent
83a26110e6
commit
38edfe4834
3 changed files with 29 additions and 31 deletions
|
|
@ -5,14 +5,15 @@ import mg.dot.feufaro.provideSettings
|
||||||
import java.util.prefs.Preferences
|
import java.util.prefs.Preferences
|
||||||
|
|
||||||
enum class Dynamic(val velocity: Int, val label: String, val defaultFactor: Float) {
|
enum class Dynamic(val velocity: Int, val label: String, val defaultFactor: Float) {
|
||||||
PPP(16, "ppp", 0.80f),
|
PPP(16, "ppp", 0.60f),
|
||||||
PP (32, "pp", 0.85f),
|
PP (32, "pp", 0.70f),
|
||||||
P (48, "p", 0.90f),
|
P (48, "p", 0.80f),
|
||||||
MP (64, "mp", 0.95f),
|
MP (64, "mp", 0.90f),
|
||||||
MF (80, "mf", 1.00f),
|
ZERO(72, "z", 1.00f),
|
||||||
F (96, "f", 1.05f),
|
MF (80, "mf", 1.10f),
|
||||||
FF (112, "ff", 1.10f),
|
F (96, "f", 1.20f),
|
||||||
FFF(127, "fff", 1.15f);
|
FF (112, "ff", 1.30f),
|
||||||
|
FFF(127, "fff", 1.40f);
|
||||||
private val prefs: Settings = provideSettings()
|
private val prefs: Settings = provideSettings()
|
||||||
var savedFactor: Float = prefs.getFloat("dynamic_${name.lowercase()}", defaultFactor)
|
var savedFactor: Float = prefs.getFloat("dynamic_${name.lowercase()}", defaultFactor)
|
||||||
set(value) {
|
set(value) {
|
||||||
|
|
|
||||||
|
|
@ -467,10 +467,10 @@ fun Settings(
|
||||||
|
|
||||||
key(refreshTrigger) {
|
key(refreshTrigger) {
|
||||||
val dynamicEntries = Dynamic.entries
|
val dynamicEntries = Dynamic.entries
|
||||||
val minF = 0.20f
|
val minF = 0.10f
|
||||||
val maxF = 1.59f
|
val maxF = 2.50f
|
||||||
val gapStep = 0.01f
|
val gapStep = 0.01f
|
||||||
val mfIndex = dynamicEntries.indexOfFirst { it == Dynamic.MF }.let { if (it == -1) 4 else it }
|
val zeroIndex = dynamicEntries.indexOfFirst { it == Dynamic.ZERO }.let { if (it == -1) 4 else it }
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
@ -497,7 +497,7 @@ fun Settings(
|
||||||
if (isDynamicEnabled) {
|
if (isDynamicEnabled) {
|
||||||
val deltaGap = gapStep
|
val deltaGap = gapStep
|
||||||
val projected = dynamicEntries.mapIndexed { i, item ->
|
val projected = dynamicEntries.mapIndexed { i, item ->
|
||||||
item.savedFactor + ((i - mfIndex) * deltaGap)
|
item.savedFactor + ((i - zeroIndex) * deltaGap)
|
||||||
}
|
}
|
||||||
val insideBounds = projected.all { it in minF..maxF }
|
val insideBounds = projected.all { it in minF..maxF }
|
||||||
val maintainsOrder = projected.zipWithNext().all { (a, b) -> a < b }
|
val maintainsOrder = projected.zipWithNext().all { (a, b) -> a < b }
|
||||||
|
|
@ -537,14 +537,14 @@ fun Settings(
|
||||||
Slider(
|
Slider(
|
||||||
value = dynamicItem.savedFactor,
|
value = dynamicItem.savedFactor,
|
||||||
onValueChange = { newValue ->
|
onValueChange = { newValue ->
|
||||||
if (isDynamicEnabled) {
|
if (isDynamicEnabled && dynamicItem != Dynamic.ZERO) {
|
||||||
val oldValue = dynamicItem.savedFactor
|
val oldValue = dynamicItem.savedFactor
|
||||||
val delta = newValue - oldValue
|
val delta = newValue - oldValue
|
||||||
|
|
||||||
if (delta != 0f) {
|
if (delta != 0f) {
|
||||||
val deltaGap = delta
|
val deltaGap = delta
|
||||||
val projected = dynamicEntries.mapIndexed { i, item ->
|
val projected = dynamicEntries.mapIndexed { i, item ->
|
||||||
item.savedFactor + ((i - mfIndex) * deltaGap)
|
item.savedFactor + ((i - zeroIndex) * deltaGap)
|
||||||
}
|
}
|
||||||
val insideBounds = projected.all { it in minF..maxF }
|
val insideBounds = projected.all { it in minF..maxF }
|
||||||
val maintainsOrder = projected.zipWithNext().all { (a, b) -> a < b }
|
val maintainsOrder = projected.zipWithNext().all { (a, b) -> a < b }
|
||||||
|
|
@ -559,13 +559,13 @@ fun Settings(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
valueRange = minF..maxF,
|
valueRange = minF..maxF,
|
||||||
enabled = isDynamicEnabled,
|
enabled = isDynamicEnabled && dynamicItem != Dynamic.ZERO,
|
||||||
track = { sliderState ->
|
track = { sliderState ->
|
||||||
SliderDefaults.Track(
|
SliderDefaults.Track(
|
||||||
sliderState = sliderState,
|
sliderState = sliderState,
|
||||||
enabled = isDynamicEnabled,
|
enabled = isDynamicEnabled && dynamicItem != Dynamic.ZERO,
|
||||||
colors = SliderDefaults.colors(
|
colors = SliderDefaults.colors(
|
||||||
activeTrackColor = if (isDynamicEnabled) Color.Blue else Color.Gray,
|
activeTrackColor = if (isDynamicEnabled && dynamicItem != Dynamic.ZERO) Color.Blue else Color.Gray,
|
||||||
inactiveTrackColor = Color.LightGray
|
inactiveTrackColor = Color.LightGray
|
||||||
),
|
),
|
||||||
modifier = Modifier.height(6.dp)
|
modifier = Modifier.height(6.dp)
|
||||||
|
|
@ -575,7 +575,7 @@ fun Settings(
|
||||||
SliderDefaults.Thumb(
|
SliderDefaults.Thumb(
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
interactionSource = remember { MutableInteractionSource() },
|
||||||
colors = SliderDefaults.colors(
|
colors = SliderDefaults.colors(
|
||||||
thumbColor = if (isDynamicEnabled) Color(0xFFFF4081) else Color.LightGray
|
thumbColor = if (isDynamicEnabled && dynamicItem != Dynamic.ZERO) Color(0xFFFF4081) else Color.LightGray
|
||||||
),
|
),
|
||||||
modifier = Modifier.size(12.dp),
|
modifier = Modifier.size(12.dp),
|
||||||
)
|
)
|
||||||
|
|
@ -609,7 +609,7 @@ fun Settings(
|
||||||
if (isDynamicEnabled) {
|
if (isDynamicEnabled) {
|
||||||
val deltaGap = -gapStep
|
val deltaGap = -gapStep
|
||||||
val projected = dynamicEntries.mapIndexed { i, item ->
|
val projected = dynamicEntries.mapIndexed { i, item ->
|
||||||
item.savedFactor + ((i - mfIndex) * deltaGap)
|
item.savedFactor + ((i - zeroIndex) * deltaGap)
|
||||||
}
|
}
|
||||||
val insideBounds = projected.all { it in minF..maxF }
|
val insideBounds = projected.all { it in minF..maxF }
|
||||||
val maintainsOrder = projected.zipWithNext().all { (a, b) -> a < b }
|
val maintainsOrder = projected.zipWithNext().all { (a, b) -> a < b }
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,8 @@ actual class FMediaPlayer actual constructor(
|
||||||
|
|
||||||
private val voiceVolumes = FloatArray(4) { 127f }
|
private val voiceVolumes = FloatArray(4) { 127f }
|
||||||
private var currentGlobalVolume: Float = 0.8f
|
private var currentGlobalVolume: Float = 0.8f
|
||||||
private var currentDynamicVelocity: Int = Dynamic.MF.velocity
|
private var currentDynamicVelocity: Int = Dynamic.ZERO.velocity
|
||||||
private var currentDynamicFactor: Float = Dynamic.MF.factor
|
private var currentDynamicFactor: Float = Dynamic.ZERO.factor
|
||||||
|
|
||||||
private var targetBpm: Float = sharedScreenModel.currentBpmFlow.value
|
private var targetBpm: Float = sharedScreenModel.currentBpmFlow.value
|
||||||
private var initialBpm: Float = sharedScreenModel.currentBpmFlow.value
|
private var initialBpm: Float = sharedScreenModel.currentBpmFlow.value
|
||||||
|
|
@ -159,10 +159,7 @@ actual class FMediaPlayer actual constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private fun applyDynamic(dynamic: Dynamic) {
|
private fun applyDynamic(dynamic: Dynamic) {
|
||||||
val targetFactor = when (dynamic) {
|
val targetFactor = dynamic.factor
|
||||||
Dynamic.MF -> 1.0f
|
|
||||||
else -> dynamic.factor
|
|
||||||
}
|
|
||||||
println("applyDynamic → ${dynamic.label} | ${currentDynamicFactor} → $targetFactor")
|
println("applyDynamic → ${dynamic.label} | ${currentDynamicFactor} → $targetFactor")
|
||||||
applyDynamicSmooth(targetFactor, durationMs = 300L)
|
applyDynamicSmooth(targetFactor, durationMs = 300L)
|
||||||
}
|
}
|
||||||
|
|
@ -170,7 +167,7 @@ actual class FMediaPlayer actual constructor(
|
||||||
val clean = marker.trim().removeSuffix("=").trim()
|
val clean = marker.trim().removeSuffix("=").trim()
|
||||||
return Dynamic.entries.firstOrNull { it.label == clean }
|
return Dynamic.entries.firstOrNull { it.label == clean }
|
||||||
}
|
}
|
||||||
fun factorToDynamic(factor: Float): Dynamic = Dynamic.entries.minByOrNull { kotlin.math.abs(it.factor - factor) } ?: Dynamic.MF
|
fun factorToDynamic(factor: Float): Dynamic = Dynamic.entries.minByOrNull { kotlin.math.abs(it.factor - factor) } ?: Dynamic.ZERO
|
||||||
fun nextDynamic(currentFactor: Float, symbol: Char): Float {
|
fun nextDynamic(currentFactor: Float, symbol: Char): Float {
|
||||||
val current = factorToDynamic(currentFactor)
|
val current = factorToDynamic(currentFactor)
|
||||||
val index = Dynamic.entries.indexOf(current)
|
val index = Dynamic.entries.indexOf(current)
|
||||||
|
|
@ -243,7 +240,7 @@ actual class FMediaPlayer actual constructor(
|
||||||
val metadataList = sharedScreenModel.getFullMarkers()
|
val metadataList = sharedScreenModel.getFullMarkers()
|
||||||
navigationSteps.clear()
|
navigationSteps.clear()
|
||||||
var lastSegno = 0
|
var lastSegno = 0
|
||||||
var lastFactor = Dynamic.MF.factor
|
var lastFactor = Dynamic.ZERO.factor
|
||||||
val ritRegex = Regex("""rit\.?|ritard\.?|ritenuto\.?|ritardando""", RegexOption.IGNORE_CASE)
|
val ritRegex = Regex("""rit\.?|ritard\.?|ritenuto\.?|ritardando""", RegexOption.IGNORE_CASE)
|
||||||
val rallRegex = Regex("""rall\.?|rallent\.?|rallentando""", RegexOption.IGNORE_CASE)
|
val rallRegex = Regex("""rall\.?|rallent\.?|rallentando""", RegexOption.IGNORE_CASE)
|
||||||
val modulaRegex = Regex("""D(ô|o)?\s*dia\s*(C|Db|D|Eb|E|F|Gb|G|Ab|A|Bb|B)""", RegexOption.IGNORE_CASE)
|
val modulaRegex = Regex("""D(ô|o)?\s*dia\s*(C|Db|D|Eb|E|F|Gb|G|Ab|A|Bb|B)""", RegexOption.IGNORE_CASE)
|
||||||
|
|
@ -446,7 +443,7 @@ actual class FMediaPlayer actual constructor(
|
||||||
extractDynamic(marker) != null && mTrim != "=" -> {
|
extractDynamic(marker) != null && mTrim != "=" -> {
|
||||||
val dyn = extractDynamic(marker) ?: return@forEach
|
val dyn = extractDynamic(marker) ?: return@forEach
|
||||||
lastFactor = when (dyn) {
|
lastFactor = when (dyn) {
|
||||||
Dynamic.MF -> 1.0f
|
Dynamic.ZERO -> 1.0f
|
||||||
else -> dyn.factor
|
else -> dyn.factor
|
||||||
}
|
}
|
||||||
navigationSteps.add(
|
navigationSteps.add(
|
||||||
|
|
@ -473,7 +470,7 @@ actual class FMediaPlayer actual constructor(
|
||||||
|
|
||||||
val dynBefore = navigationSteps
|
val dynBefore = navigationSteps
|
||||||
.filter { it.dynamic != null && it.gridIndex <= currentIndex }
|
.filter { it.dynamic != null && it.gridIndex <= currentIndex }
|
||||||
.maxByOrNull { it.gridIndex }?.dynamic ?: Dynamic.MF
|
.maxByOrNull { it.gridIndex }?.dynamic ?: Dynamic.ZERO
|
||||||
|
|
||||||
val dynAfter = metadataList
|
val dynAfter = metadataList
|
||||||
.filter { m -> (m.gridIndex ?: 0) >= pair.endGrid }
|
.filter { m -> (m.gridIndex ?: 0) >= pair.endGrid }
|
||||||
|
|
@ -720,7 +717,7 @@ actual class FMediaPlayer actual constructor(
|
||||||
val lastDynamic = navigationSteps
|
val lastDynamic = navigationSteps
|
||||||
.filter { it.dynamic != null && it.gridIndex <= gridIndex }
|
.filter { it.dynamic != null && it.gridIndex <= gridIndex }
|
||||||
.maxByOrNull { it.gridIndex }
|
.maxByOrNull { it.gridIndex }
|
||||||
?.dynamic ?: Dynamic.MF
|
?.dynamic ?: Dynamic.ZERO
|
||||||
currentDynamicFactor = lastDynamic.factor
|
currentDynamicFactor = lastDynamic.factor
|
||||||
applyVoiceStates()
|
applyVoiceStates()
|
||||||
sharedScreenModel.updateActiveIndexByIndex(-1)
|
sharedScreenModel.updateActiveIndexByIndex(-1)
|
||||||
|
|
@ -891,7 +888,7 @@ actual class FMediaPlayer actual constructor(
|
||||||
sequencer?.tempoInBPM = initialBpm
|
sequencer?.tempoInBPM = initialBpm
|
||||||
boundModel?.setBpmFlow(initialBpm)
|
boundModel?.setBpmFlow(initialBpm)
|
||||||
clearLoop()
|
clearLoop()
|
||||||
currentDynamicFactor = Dynamic.MF.factor
|
currentDynamicFactor = Dynamic.ZERO.factor
|
||||||
resetTempoToNormal()
|
resetTempoToNormal()
|
||||||
// release()
|
// release()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue