more musicplayer things

This commit is contained in:
minjaesong
2023-12-28 15:59:33 +09:00
parent fa915d63d2
commit 3e7434a9c6
5 changed files with 59 additions and 52 deletions

View File

@@ -65,21 +65,21 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
private val TRANSITION_LENGTH = 0.6f private val TRANSITION_LENGTH = 0.6f
private var colourEdge = Color(0xFFFFFF_40.toInt()) private val colourBack = Color(0xffffff_99.toInt())
private val colourBack = Color.BLACK
private val colourText = Color(0xf0f0f0ff.toInt()) private val colourText = Color(0xffffff_cc.toInt())
private val colourMeter = Color(0xddddddff.toInt()) private val colourMeter = Color(0xeeeeee_cc.toInt())
private val colourMeter2 = Color(0xdddddd80.toInt()) private val colourMeter2 = Color(0xeeeeee_66.toInt())
private val colourControlButton = Color(0xddddddff.toInt()) private val colourControlButton = Color(0xeeeeee_cc.toInt())
init { init {
setAsAlwaysVisible() setAsAlwaysVisible()
// test code // test code
// val albumDir = App.customMusicDir + "/Gapless Test" val albumDir = App.customMusicDir + "/Gapless Test"
val albumDir = App.customMusicDir + "/FurryJoA 2023 Live" // val albumDir = App.customMusicDir + "/FurryJoA 2023 Live"
// val albumDir = App.customMusicDir + "/Audio Test"
val playlistFile = JsonFetcher.invoke("$albumDir/playlist.json") val playlistFile = JsonFetcher.invoke("$albumDir/playlist.json")
val diskJockeyingMode = playlistFile.get("diskJockeyingMode").asString() val diskJockeyingMode = playlistFile.get("diskJockeyingMode").asString()
@@ -279,8 +279,15 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
relativeMouseY.toFloat() in _posY .. _posY+height relativeMouseY.toFloat() in _posY .. _posY+height
override fun renderUI(batch: SpriteBatch, camera: OrthographicCamera) { override fun renderUI(batch: SpriteBatch, camera: OrthographicCamera) {
val widthForFreqMeter = if (transitionOngoing && modeNext >= MODE_MOUSE_UP || mode >= MODE_MOUSE_UP)
uiWidthFromTextWidth(nameLength)
else
width
batch.end() batch.end()
renderNameToFBO(batch, camera, currentMusicName) renderNameToFBO(batch, camera, currentMusicName, widthForFreqMeter.toFloat())
batch.begin() batch.begin()
@@ -294,10 +301,6 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
else else
_posX _posX
val widthForFreqMeter = if (transitionOngoing && modeNext >= MODE_MOUSE_UP || mode >= MODE_MOUSE_UP)
uiWidthFromTextWidth(nameLength)
else
width
blendNormalStraightAlpha(batch) blendNormalStraightAlpha(batch)
drawBaloon(batch, _posX, _posY, width.toFloat(), (height - capsuleHeight.toFloat()).coerceAtLeast(0f)) drawBaloon(batch, _posX, _posY, width.toFloat(), (height - capsuleHeight.toFloat()).coerceAtLeast(0f))
@@ -310,30 +313,28 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
private fun drawBaloon(batch: SpriteBatch, x: Float, y: Float, width: Float, height: Float) { private fun drawBaloon(batch: SpriteBatch, x: Float, y: Float, width: Float, height: Float) {
val x = x - capsuleMosaicSize val x = x - capsuleMosaicSize
for (k in 0..3 step 3) { batch.color = colourBack// (if (mouseUp) Color.MAROON else colourBack)
batch.color = if (k == 0) colourEdge else colourBack// (if (mouseUp) Color.MAROON else colourBack)
// top left // top left
batch.draw(baloonTexture.get(k+0, 0), x, y, capsuleMosaicSize.toFloat(), capsuleMosaicSize.toFloat()) batch.draw(baloonTexture.get(0, 0), x, y, capsuleMosaicSize.toFloat(), capsuleMosaicSize.toFloat())
// top // top
batch.draw(baloonTexture.get(k+1, 0), x + capsuleMosaicSize, y, width, capsuleMosaicSize.toFloat()) batch.draw(baloonTexture.get(1, 0), x + capsuleMosaicSize, y, width, capsuleMosaicSize.toFloat())
// top right // top right
batch.draw(baloonTexture.get(k+2, 0), x + capsuleMosaicSize + width, y, capsuleMosaicSize.toFloat(), capsuleMosaicSize.toFloat()) batch.draw(baloonTexture.get(2, 0), x + capsuleMosaicSize + width, y, capsuleMosaicSize.toFloat(), capsuleMosaicSize.toFloat())
// left // left
batch.draw(baloonTexture.get(k+0, 1), x, y + capsuleMosaicSize, capsuleMosaicSize.toFloat(), height) batch.draw(baloonTexture.get(0, 1), x, y + capsuleMosaicSize, capsuleMosaicSize.toFloat(), height)
// centre // centre
batch.draw(baloonTexture.get(k+1, 1), x + capsuleMosaicSize, y + capsuleMosaicSize, width, height) batch.draw(baloonTexture.get(1, 1), x + capsuleMosaicSize, y + capsuleMosaicSize, width, height)
// right // right
batch.draw(baloonTexture.get(k+2, 1), x + capsuleMosaicSize + width, y + capsuleMosaicSize, capsuleMosaicSize.toFloat(), height) batch.draw(baloonTexture.get(2, 1), x + capsuleMosaicSize + width, y + capsuleMosaicSize, capsuleMosaicSize.toFloat(), height)
// bottom left // bottom left
batch.draw(baloonTexture.get(k+0, 2), x, y + capsuleMosaicSize + height, capsuleMosaicSize.toFloat(), capsuleMosaicSize.toFloat()) batch.draw(baloonTexture.get(0, 2), x, y + capsuleMosaicSize + height, capsuleMosaicSize.toFloat(), capsuleMosaicSize.toFloat())
// bottom // bottom
batch.draw(baloonTexture.get(k+1, 2), x + capsuleMosaicSize, y + capsuleMosaicSize + height, width, capsuleMosaicSize.toFloat()) batch.draw(baloonTexture.get(1, 2), x + capsuleMosaicSize, y + capsuleMosaicSize + height, width, capsuleMosaicSize.toFloat())
// bottom right // bottom right
batch.draw(baloonTexture.get(k+2, 2), x + capsuleMosaicSize + width, y + capsuleMosaicSize + height, capsuleMosaicSize.toFloat(), capsuleMosaicSize.toFloat()) batch.draw(baloonTexture.get(2, 2), x + capsuleMosaicSize + width, y + capsuleMosaicSize + height, capsuleMosaicSize.toFloat(), capsuleMosaicSize.toFloat())
}
} }
private fun drawControls(batch: SpriteBatch, posX: Float, posY: Float) { private fun drawControls(batch: SpriteBatch, posX: Float, posY: Float) {
@@ -348,12 +349,12 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
if (alpha > 0f) { if (alpha > 0f) {
val alpha0 = alpha.coerceIn(0f, 1f).organicOvershoot().coerceAtMost(1f) val alpha0 = alpha.coerceIn(0f, 1f).organicOvershoot().coerceAtMost(1f)
batch.color = colourControlButton mul Color(1f, 1f, 1f, (if (reverse) 1f - alpha0 else alpha0).pow(2f)) batch.color = colourControlButton mul Color(1f, 1f, 1f, (if (reverse) 1f - alpha0 else alpha0).pow(3f))
val posX = Toolkit.hdrawWidthf - 100f val posX = Toolkit.hdrawWidthf - 120f
val posY = posY + 10f val posY = posY + 10f
for (i in 0..4) { for (i in 0..4) {
val iconY = if (!AudioMixer.musicTrack.isPlaying && i == 2) 1 else 0 val iconY = if (!AudioMixer.musicTrack.isPlaying && i == 2) 1 else 0
batch.draw(controlButtons.get(i, iconY), posX + i * BUTTON_SIZE, posY) batch.draw(controlButtons.get(i, iconY), posX + i * (BUTTON_SIZE + 8) + 4, posY)
} }
} }
} }
@@ -363,8 +364,8 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
batch.draw(nameFBO.colorBufferTexture, posX - maskOffWidth, posY + height - capsuleHeight + 1) batch.draw(nameFBO.colorBufferTexture, posX - maskOffWidth, posY + height - capsuleHeight + 1)
} }
private fun renderNameToFBO(batch: SpriteBatch, camera: OrthographicCamera, str: String) { private fun renderNameToFBO(batch: SpriteBatch, camera: OrthographicCamera, str: String, width: Float) {
val windowEnd = width.toFloat() - METERS_WIDTH - maskOffWidth val windowEnd = width - METERS_WIDTH - maskOffWidth
nameFBO.inAction(camera, batch) { nameFBO.inAction(camera, batch) {
batch.inUse { batch.inUse {
@@ -420,7 +421,7 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
// apply slope to the fft bins, also converts fullscale to decibels // apply slope to the fft bins, also converts fullscale to decibels
for (bin in binHeights.indices) { for (bin in binHeights.indices) {
val freqR = (TerrarumAudioMixerTrack.SAMPLING_RATED / FFTSIZE) * (bin + 1) val freqR = (TerrarumAudioMixerTrack.SAMPLING_RATED / FFTSIZE) * (bin + 1)
val magn0 = fftOut.reim[2 * bin].absoluteValue / FFTSIZE * (freqR / 10.0) // apply slope val magn0 = fftOut.reim[2 * bin].absoluteValue / FFTSIZE * (freqR / 20.0) // apply slope
val magn = FastMath.interpolateLinear(FFT_SMOOTHING_FACTOR, magn0, oldFFTmagn[bin]) val magn = FastMath.interpolateLinear(FFT_SMOOTHING_FACTOR, magn0, oldFFTmagn[bin])
val magnLog = fullscaleToDecibels(magn) val magnLog = fullscaleToDecibels(magn)

Binary file not shown.

View File

@@ -177,7 +177,10 @@ object AudioMixer: Disposable {
masterTrack.filters[0] = SoftClp masterTrack.filters[0] = SoftClp
masterTrack.filters[1] = Buffer masterTrack.filters[1] = Buffer
masterTrack.filters[2] = Spectro() masterTrack.filters[2] = Spectro()
masterTrack.filters[3] = Vecto() masterTrack.filters[3] = Vecto(2f)
musicTrack.filters[1] = Spectro()
ambientTrack.filters[1] = Spectro()
listOf(sumBus, convolveBusOpen, convolveBusCave).forEach { listOf(sumBus, convolveBusOpen, convolveBusCave).forEach {
it.addSidechainInput(musicTrack, 1.0) it.addSidechainInput(musicTrack, 1.0)
@@ -201,7 +204,7 @@ object AudioMixer: Disposable {
masterTrack.addSidechainInput(fadeBus, 1.0) masterTrack.addSidechainInput(fadeBus, 1.0)
masterTrack.addSidechainInput(guiTrack, 1.0) masterTrack.addSidechainInput(guiTrack, 1.0)
musicTrack.filters[1] = Gain(0.5f) musicTrack.filters[3] = Gain(0.5f)
dynamicTracks.forEach { dynamicTracks.forEach {
it.filters[0] = BinoPan(0f) it.filters[0] = BinoPan(0f)

View File

@@ -11,7 +11,7 @@ import net.torvald.terrarum.ui.BasicDebugInfoWindow.Companion.STRIP_W
import net.torvald.terrarum.ui.Toolkit import net.torvald.terrarum.ui.Toolkit
import kotlin.math.* import kotlin.math.*
class Spectro : TerrarumAudioFilter() { class Spectro(val gain: Float = 1f) : TerrarumAudioFilter() {
private val FFTSIZE = 1024 private val FFTSIZE = 1024
private val inBuf = Array(2) { FloatArray(FFTSIZE) } private val inBuf = Array(2) { FloatArray(FFTSIZE) }
@@ -51,7 +51,7 @@ class Spectro : TerrarumAudioFilter() {
push(inbuf[0], inBuf[0]) push(inbuf[0], inBuf[0])
push(inbuf[1], inBuf[1]) push(inbuf[1], inBuf[1])
for (i in 0 until FFTSIZE) { for (i in 0 until FFTSIZE) {
chsum.reim[2*i] = ((inBuf[0][i] + inBuf[1][i]) / 2f) * fftWin[i] chsum.reim[2*i] = ((inBuf[0][i] + inBuf[1][i]) / 2f) * fftWin[i] * gain
} }
// do fft // do fft
@@ -74,7 +74,7 @@ class Spectro : TerrarumAudioFilter() {
for (bin in 0 until FFTSIZE / 2) { for (bin in 0 until FFTSIZE / 2) {
val freqL = (SAMPLING_RATED / FFTSIZE) * bin val freqL = (SAMPLING_RATED / FFTSIZE) * bin
val freqR = (SAMPLING_RATED / FFTSIZE) * (bin + 1) val freqR = (SAMPLING_RATED / FFTSIZE) * (bin + 1)
val magn0 = fftOut.reim[2 * bin].absoluteValue / FFTSIZE * (freqR / 10.0) // apply slope val magn0 = fftOut.reim[2 * bin].absoluteValue / FFTSIZE * (freqR / 20.0) // apply slope
val magn = FastMath.interpolateLinear(BasicDebugInfoWindow.FFT_SMOOTHING_FACTOR, magn0, oldFFTmagn[bin]) val magn = FastMath.interpolateLinear(BasicDebugInfoWindow.FFT_SMOOTHING_FACTOR, magn0, oldFFTmagn[bin])
val magnLog = fullscaleToDecibels(magn) val magnLog = fullscaleToDecibels(magn)
@@ -94,7 +94,7 @@ class Spectro : TerrarumAudioFilter() {
} }
class Vecto : TerrarumAudioFilter() { class Vecto(val gain: Float = 1f) : TerrarumAudioFilter() {
val backbufL = Array((6144f / AUDIO_BUFFER_SIZE).roundToInt().coerceAtLeast(1)) { val backbufL = Array((6144f / AUDIO_BUFFER_SIZE).roundToInt().coerceAtLeast(1)) {
FloatArray(AUDIO_BUFFER_SIZE) FloatArray(AUDIO_BUFFER_SIZE)
} }
@@ -115,8 +115,8 @@ class Vecto : TerrarumAudioFilter() {
// plot dots // plot dots
for (i in 0 until TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) { for (i in 0 until TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) {
val y0 = +inbuf[0][i] * 2f val y0 = +inbuf[0][i] * gain
val x0 = -inbuf[1][i] * 2f// rotate the domain by -90 deg val x0 = -inbuf[1][i] * gain// rotate the domain by -90 deg
val x = (+x0*sqrt2p -y0*sqrt2p) * 1.4142 val x = (+x0*sqrt2p -y0*sqrt2p) * 1.4142
val y = (-x0*sqrt2p -y0*sqrt2p) * 1.4142 // further rotate by -45 deg then flip along the y axis val y = (-x0*sqrt2p -y0*sqrt2p) * 1.4142 // further rotate by -45 deg then flip along the y axis

View File

@@ -148,6 +148,9 @@ class TerrarumMusicGovernor : MusicGovernor() {
private var diskJockeyingMode = "intermittent" // intermittent, continuous private var diskJockeyingMode = "intermittent" // intermittent, continuous
private fun registerSongsFromDir(musicDir: String, fileToName: ((String) -> String)?) { private fun registerSongsFromDir(musicDir: String, fileToName: ((String) -> String)?) {
printdbg(this, "registerSongsFromDir $musicDir")
val fileToName = if (fileToName == null) { val fileToName = if (fileToName == null) {
{ name: String -> name.substringBeforeLast('.').replace('_', ' ').split(" ").map { it.capitalize() }.joinToString(" ") } { name: String -> name.substringBeforeLast('.').replace('_', ' ').split(" ").map { it.capitalize() }.joinToString(" ") }
} }
@@ -295,11 +298,11 @@ class TerrarumMusicGovernor : MusicGovernor() {
if (!musicFired) { if (!musicFired) {
musicFired = true musicFired = true
val song = songs[musicBin.removeAt(0)]
// prevent same song to play twice // prevent same song to play twice
if (musicBin.isEmpty()) { if (musicBin.isEmpty()) {
restockMUsicBin() restockMUsicBin()
} }
val song = songs[musicBin.removeAt(0)]
startMusic(song) startMusic(song)
} }
@@ -322,11 +325,11 @@ class TerrarumMusicGovernor : MusicGovernor() {
if (!ambFired) { if (!ambFired) {
ambFired = true ambFired = true
val song = ambients[ambientsBin.removeAt(0)]
// prevent same song to play twice // prevent same song to play twice
if (ambientsBin.isEmpty()) { if (ambientsBin.isEmpty()) {
ambientsBin = ArrayList(ambients.indices.toList().shuffled()) ambientsBin = ArrayList(ambients.indices.toList().shuffled())
} }
val song = ambients[ambientsBin.removeAt(0)]
startAmbient(song) startAmbient(song)
} }