Remember volume per voices [satb] - for desktop
This commit is contained in:
parent
84a9626b08
commit
e6af7bd39e
4 changed files with 33 additions and 56 deletions
|
|
@ -15,7 +15,7 @@ private var androidMediaPlayer: MediaPlayer?= null
|
||||||
|
|
||||||
actual class FMediaPlayer actual constructor(val filename: String, onFinished: () -> Unit) {
|
actual class FMediaPlayer actual constructor(val filename: String, onFinished: () -> Unit) {
|
||||||
private var mediaPlayer: android.media.MediaPlayer? = android.media.MediaPlayer()
|
private var mediaPlayer: android.media.MediaPlayer? = android.media.MediaPlayer()
|
||||||
private val voiceStates = mutableListOf(true, true, true, true)
|
// private val voiceStates = mutableListOf(true, true, true, true)
|
||||||
private val midiFileName = filename
|
private val midiFileName = filename
|
||||||
// private var currentGlobalVolume: Float = 0.8f
|
// private var currentGlobalVolume: Float = 0.8f
|
||||||
|
|
||||||
|
|
@ -132,11 +132,12 @@ actual fun setVolume(level: Float) {
|
||||||
|
|
||||||
actual fun getLoopState() = Triple(pointA, pointB, isLoopingAB)
|
actual fun getLoopState() = Triple(pointA, pointB, isLoopingAB)
|
||||||
actual fun toggleVoice(index: Int) {
|
actual fun toggleVoice(index: Int) {
|
||||||
voiceStates[index] = !voiceStates[index]
|
// voiceStates[index] = !voiceStates[index]
|
||||||
println("Toggle voice $index (Limitation: Nécessite SoundFont/Fluidsynth sur Android)")
|
println("Toggle voice $index (Limitation: Nécessite SoundFont/Fluidsynth sur Android)")
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun getVoiceStates(): List<Boolean> = voiceStates
|
// actual fun getVoiceStates(): List<Boolean> = voiceStates
|
||||||
|
actual fun getVoiceVolumes(): List<Float> = MutableList(4) { 127f }
|
||||||
|
|
||||||
actual fun changeInstru(noInstru: Int) {
|
actual fun changeInstru(noInstru: Int) {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ expect class FMediaPlayer(filename: String, onFinished: () -> Unit) {
|
||||||
fun getDuration(): Long
|
fun getDuration(): Long
|
||||||
fun getLoopState(): Triple<Long, Long, Boolean>
|
fun getLoopState(): Triple<Long, Long, Boolean>
|
||||||
fun toggleVoice(index: Int)
|
fun toggleVoice(index: Int)
|
||||||
fun getVoiceStates(): List<Boolean>
|
fun getVoiceVolumes(): List<Float>
|
||||||
fun changeInstru(noInstru: Int)
|
fun changeInstru(noInstru: Int)
|
||||||
fun getCurrentPosition(): Long
|
fun getCurrentPosition(): Long
|
||||||
fun seekTo(position: Long)
|
fun seekTo(position: Long)
|
||||||
|
|
|
||||||
|
|
@ -64,9 +64,8 @@ fun MidiControlPanel(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val voiceStates = mediaPlayer.getVoiceStates()
|
|
||||||
val sliderVolumes = remember {
|
val sliderVolumes = remember {
|
||||||
mutableStateListOf(127f, 127f, 127f, 127f)
|
mediaPlayer.getVoiceVolumes().map { mutableStateOf(it) }.toMutableStateList()
|
||||||
}
|
}
|
||||||
val labels = listOf("S", "A", "T", "B")
|
val labels = listOf("S", "A", "T", "B")
|
||||||
listOf("Soprano", "Alto", "Ténor", "Basse")
|
listOf("Soprano", "Alto", "Ténor", "Basse")
|
||||||
|
|
@ -201,9 +200,9 @@ fun MidiControlPanel(
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
Slider(
|
Slider(
|
||||||
value = sliderVolumes[i],
|
value = sliderVolumes[i].value,
|
||||||
onValueChange = { newValue ->
|
onValueChange = { newValue ->
|
||||||
sliderVolumes[i] = newValue
|
sliderVolumes[i].value = newValue
|
||||||
mediaPlayer.updateVoiceVolume(i, newValue)
|
mediaPlayer.updateVoiceVolume(i, newValue)
|
||||||
},
|
},
|
||||||
valueRange = 0f..126f,
|
valueRange = 0f..126f,
|
||||||
|
|
@ -234,22 +233,6 @@ fun MidiControlPanel(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*Row(
|
|
||||||
modifier = Modifier.padding(vertical = 8.dp),
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(4.dp)
|
|
||||||
) {
|
|
||||||
labels.forEachIndexed { index, label ->
|
|
||||||
FilterChip(
|
|
||||||
selected = voiceStates[index],
|
|
||||||
onClick = { mediaPlayer.toggleVoice(index) },
|
|
||||||
label = { Text(label) },
|
|
||||||
colors = FilterChipDefaults.filterChipColors(
|
|
||||||
selectedContainerColor = MaterialTheme.colorScheme.primaryContainer,
|
|
||||||
selectedLabelColor = MaterialTheme.colorScheme.primary
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,11 @@ package mg.dot.feufaro.midi
|
||||||
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import mg.dot.feufaro.getConfigDirectoryPath
|
import mg.dot.feufaro.getConfigDirectoryPath
|
||||||
import java.io.ByteArrayInputStream
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.prefs.Preferences
|
import java.util.prefs.Preferences
|
||||||
import javax.sound.midi.MidiSystem
|
import javax.sound.midi.MidiSystem
|
||||||
import javax.sound.midi.Sequencer
|
import javax.sound.midi.Sequencer
|
||||||
import javax.sound.midi.Synthesizer
|
import javax.sound.midi.Synthesizer
|
||||||
import javax.sound.sampled.AudioFormat
|
|
||||||
import javax.sound.sampled.AudioSystem
|
import javax.sound.sampled.AudioSystem
|
||||||
import javax.sound.sampled.FloatControl
|
import javax.sound.sampled.FloatControl
|
||||||
|
|
||||||
|
|
@ -31,7 +29,6 @@ actual class FMediaPlayer actual constructor(
|
||||||
private var pointB: Long = -1L
|
private var pointB: Long = -1L
|
||||||
private var isLoopingAB: Boolean = false
|
private var isLoopingAB: Boolean = false
|
||||||
|
|
||||||
private val voiceStates = mutableListOf(true, true, true, true)
|
|
||||||
private val voiceVolumes = FloatArray(4) { 127f }
|
private val voiceVolumes = FloatArray(4) { 127f }
|
||||||
private var currentGlobalVolume: Float = 0.8f
|
private var currentGlobalVolume: Float = 0.8f
|
||||||
|
|
||||||
|
|
@ -53,7 +50,7 @@ actual class FMediaPlayer actual constructor(
|
||||||
val file = File(filename)
|
val file = File(filename)
|
||||||
if (file.exists()){
|
if (file.exists()){
|
||||||
sequencer?.sequence = MidiSystem.getSequence(file)
|
sequencer?.sequence = MidiSystem.getSequence(file)
|
||||||
loadVoiceStates()
|
loadVoiceVolumes()
|
||||||
applyVoiceStates()
|
applyVoiceStates()
|
||||||
sequencer?.addMetaEventListener { meta ->
|
sequencer?.addMetaEventListener { meta ->
|
||||||
if(meta.type == 47){
|
if(meta.type == 47){
|
||||||
|
|
@ -103,7 +100,7 @@ actual class FMediaPlayer actual constructor(
|
||||||
|
|
||||||
synthetizer?.channels?.forEachIndexed { index, channel ->
|
synthetizer?.channels?.forEachIndexed { index, channel ->
|
||||||
if (index < 4) {
|
if (index < 4) {
|
||||||
val vol = if (voiceStates[index]) volumeInt else 0
|
val vol = if (voiceVolumes[index] != 0f) volumeInt else 0
|
||||||
channel?.controlChange(7, vol)
|
channel?.controlChange(7, vol)
|
||||||
} else {
|
} else {
|
||||||
channel?.controlChange(7, volumeInt)
|
channel?.controlChange(7, volumeInt)
|
||||||
|
|
@ -158,13 +155,13 @@ actual class FMediaPlayer actual constructor(
|
||||||
actual fun getLoopState() = Triple(pointA, pointB, isLoopingAB)
|
actual fun getLoopState() = Triple(pointA, pointB, isLoopingAB)
|
||||||
|
|
||||||
actual fun toggleVoice(index: Int) {
|
actual fun toggleVoice(index: Int) {
|
||||||
voiceStates[index] = !voiceStates[index]
|
saveVoicesVolumes()
|
||||||
saveVoiceStates()
|
|
||||||
applyVoiceStates()
|
applyVoiceStates()
|
||||||
}
|
}
|
||||||
actual fun updateVoiceVolume(voiceIndex: Int, newVolume: Float) {
|
actual fun updateVoiceVolume(voiceIndex: Int, newVolume: Float) {
|
||||||
if (voiceIndex in 0..3) {
|
if (voiceIndex in 0..3) {
|
||||||
voiceVolumes[voiceIndex] = newVolume
|
voiceVolumes[voiceIndex] = newVolume
|
||||||
|
saveVoicesVolumes()
|
||||||
applyVoiceStates()
|
applyVoiceStates()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -172,28 +169,24 @@ actual class FMediaPlayer actual constructor(
|
||||||
private fun applyVoiceStates() {
|
private fun applyVoiceStates() {
|
||||||
try {
|
try {
|
||||||
synthetizer?.channels?.let { channels ->
|
synthetizer?.channels?.let { channels ->
|
||||||
for (i in 0 until 4) {
|
for (i in 0 until 4) {
|
||||||
if (i < channels.size) {
|
if (i < channels.size) {
|
||||||
val volume = voiceVolumes[i].toInt()
|
val targetVolume = voiceVolumes[i].toInt()
|
||||||
val isVoiceActive = voiceStates[i]
|
|
||||||
val currentVolume = voiceVolumes[i].toInt()
|
|
||||||
|
|
||||||
if (volume == 0) {
|
channels[i].controlChange(7, targetVolume)
|
||||||
channels[i].controlChange(123, 0)
|
channels[i].controlChange(11, targetVolume)
|
||||||
voiceStates[i] = false
|
|
||||||
} else {
|
if (targetVolume == 0) {
|
||||||
channels[i].controlChange(7, currentVolume)
|
channels[i].controlChange(123, 0)
|
||||||
channels[i].controlChange(11, currentVolume)
|
}
|
||||||
voiceStates[i] = true
|
|
||||||
}
|
}
|
||||||
|
println("SATB $i Volumes: ${voiceVolumes[i]}")
|
||||||
}
|
}
|
||||||
println("SATB màj: $voiceStates, Volumes: ${voiceVolumes[i]}")
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} catch (e: Exception) { e.printStackTrace() }
|
} catch (e: Exception) { e.printStackTrace() }
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun getVoiceStates(): List<Boolean> = voiceStates
|
actual fun getVoiceVolumes(): List<Float> = voiceVolumes.toList()
|
||||||
|
|
||||||
actual fun changeInstru(noInstru: Int) {
|
actual fun changeInstru(noInstru: Int) {
|
||||||
val pgm = noInstru
|
val pgm = noInstru
|
||||||
|
|
@ -230,19 +223,19 @@ actual class FMediaPlayer actual constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveVoiceStates() {
|
private fun saveVoicesVolumes() {
|
||||||
val data = voiceStates.joinToString(",")
|
val data = voiceVolumes.joinToString(",")
|
||||||
prefs.put("voice_states", data)
|
prefs.put("voices_volumes", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadVoiceStates() {
|
private fun loadVoiceVolumes() {
|
||||||
val defaultValue = "true,true,true,true"
|
val data = prefs.get("voices_volumes", "127,127,127,127")
|
||||||
val savedData = prefs.get("voice_states", defaultValue)
|
val volumesArray = data.split(",")
|
||||||
|
|
||||||
val states = savedData.split(",").map { it.toBoolean() }
|
if (volumesArray.size == 4) {
|
||||||
for (i in 0 until 4) {
|
for (i in 0 until 4) {
|
||||||
if (i < states.size) voiceStates[i] = states[i]
|
voiceVolumes[i] = volumesArray[i].toFloatOrNull() ?: 127f
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
Add table
Reference in a new issue