more musicplayer things

This commit is contained in:
minjaesong
2023-12-24 03:54:48 +09:00
parent c4836a3fe2
commit 7371253398
5 changed files with 102 additions and 60 deletions

View File

@@ -29,7 +29,8 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
private val maskOffWidth = 8 private val maskOffWidth = 8
private val nameFBO = FrameBuffer(Pixmap.Format.RGBA8888, 400, capsuleHeight, false) private val nameStrMaxLen = 180
private val nameFBO = FrameBuffer(Pixmap.Format.RGBA8888, nameStrMaxLen + 2*maskOffWidth, capsuleHeight, false)
private val baloonTexture = ModMgr.getGdxFile("musicplayer", "gui/blob.tga").let { private val baloonTexture = ModMgr.getGdxFile("musicplayer", "gui/blob.tga").let {
TextureRegionPack(it, capsuleMosaicSize, capsuleMosaicSize) TextureRegionPack(it, capsuleMosaicSize, capsuleMosaicSize)
@@ -59,17 +60,41 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
init { init {
setAsAlwaysVisible() setAsAlwaysVisible()
ingame.musicGovernor.addMusicStartHook { music ->
setMusicName(music.name)
}
ingame.musicGovernor.addMusicStopHook { music ->
setIntermission()
}
}
private var renderFBOreq: String? = ""
private var nameOverflown = false
private fun setIntermission() {
renderFBOreq = ""
nameOverflown = false
}
private fun setMusicName(str: String) {
renderFBOreq = str
} }
override fun renderUI(batch: SpriteBatch, camera: OrthographicCamera) { override fun renderUI(batch: SpriteBatch, camera: OrthographicCamera) {
batch.end() if (renderFBOreq != null) {
batch.end()
width = if (renderFBOreq!!.isEmpty())
renderNameToFBO(batch, camera, AudioMixer.musicTrack.currentTrack?.name ?: "", 0f..(width - 2*STRIP_W - capsuleHeight + maskOffWidth)) 2*STRIP_W.toInt()
else {
val slen = App.fontGameFBO.getWidth(renderFBOreq!!)
if (slen > nameStrMaxLen) { nameOverflown = true }
batch.begin() slen.coerceAtMost(nameStrMaxLen) + 2 * STRIP_W.toInt() + maskOffWidth
}
renderNameToFBO(batch, camera, renderFBOreq!!, 0f..width.toFloat() - 2*STRIP_W.toInt() - maskOffWidth)
batch.begin()
renderFBOreq = null
}
val posX = ((Toolkit.drawWidth - width) / 2).toFloat() val posX = ((Toolkit.drawWidth - width) / 2).toFloat()
val posY = (App.scr.height - App.scr.tvSafeGraphicsHeight - height).toFloat() val posY = (App.scr.height - App.scr.tvSafeGraphicsHeight - height).toFloat()
@@ -143,7 +168,7 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
private val chsum = ComplexArray(FloatArray(FFTSIZE * 2)) private val chsum = ComplexArray(FloatArray(FFTSIZE * 2))
private val fftOut = ComplexArray(FloatArray(FFTSIZE * 2)) private val fftOut = ComplexArray(FloatArray(FFTSIZE * 2))
private val binHeights = FloatArray(FFTSIZE / 2) private val binHeights = FloatArray(FFTSIZE / 2)
private val FFT_SMOOTHING_FACTOR = BasicDebugInfoWindow.getSmoothingFactor(1600) private val FFT_SMOOTHING_FACTOR = BasicDebugInfoWindow.getSmoothingFactor(2048)
private val lowlim = -36.0f private val lowlim = -36.0f
private val STRIP_W = 9f private val STRIP_W = 9f

Binary file not shown.

View File

@@ -176,7 +176,8 @@ object AudioMixer: Disposable {
masterTrack.filters[0] = SoftClp masterTrack.filters[0] = SoftClp
masterTrack.filters[1] = Buffer masterTrack.filters[1] = Buffer
masterTrack.filters[2] = Scope() masterTrack.filters[2] = Spectro()
masterTrack.filters[3] = Vecto()
listOf(sumBus, convolveBusOpen, convolveBusCave).forEach { listOf(sumBus, convolveBusOpen, convolveBusCave).forEach {
it.addSidechainInput(musicTrack, 1.0) it.addSidechainInput(musicTrack, 1.0)

View File

@@ -11,14 +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 Scope : TerrarumAudioFilter() { class Spectro : TerrarumAudioFilter() {
val backbufL = Array((6144f / AUDIO_BUFFER_SIZE).roundToInt().coerceAtLeast(1)) {
FloatArray(AUDIO_BUFFER_SIZE)
}
val backbufR = Array((6144f / AUDIO_BUFFER_SIZE).roundToInt().coerceAtLeast(1)) {
FloatArray(AUDIO_BUFFER_SIZE)
}
private val FFTSIZE = 1024 private val FFTSIZE = 1024
private val inBuf = Array(2) { FloatArray(FFTSIZE) } private val inBuf = Array(2) { FloatArray(FFTSIZE) }
@@ -53,6 +46,63 @@ class Scope : TerrarumAudioFilter() {
} }
} }
override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) {
// create (L+R)/2 array
push(inbuf[0], inBuf[0])
push(inbuf[1], inBuf[1])
for (i in 0 until FFTSIZE) {
chsum.reim[2*i] = ((inBuf[0][i] + inBuf[1][i]) / 2f) * fftWin[i]
}
// do fft
FFT.fftInto(chsum, fftOut)
// copy samples over
outbuf.forEachIndexed { index, outTrack ->
System.arraycopy(inbuf[index], 0, outTrack, 0, outTrack.size)
}
}
private val spectroPlotCol = Color(0xdf6fa0_aa.toInt())
private val lowlim = -60.0
override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) {
// spectrometer
batch.color = spectroPlotCol
for (bin in 0 until FFTSIZE / 2) {
val freqL = (SAMPLING_RATED / FFTSIZE) * bin
val freqR = (SAMPLING_RATED / FFTSIZE) * (bin + 1)
val magn0 = fftOut.reim[2 * bin].absoluteValue / FFTSIZE * (freqR / 10.0) // apply slope
val magn = FastMath.interpolateLinear(BasicDebugInfoWindow.FFT_SMOOTHING_FACTOR, magn0, oldFFTmagn[bin])
val magnLog = fullscaleToDecibels(magn)
if (magnLog >= lowlim) {
val xL = linToLogPerc(freqL, 24.0, 24000.0).coerceIn(0.0, 1.0) * STRIP_W
val xR = linToLogPerc(freqR, 24.0, 24000.0).coerceIn(0.0, 1.0) * STRIP_W
val w = (xR - xL)
val h = (magnLog - lowlim) / lowlim * STRIP_W
Toolkit.fillArea(batch, x + xL.toFloat(), y + STRIP_W.toFloat(), w.toFloat(), h.toFloat())
}
oldFFTmagn[bin] = magn
}
}
override val debugViewHeight = STRIP_W
}
class Vecto : TerrarumAudioFilter() {
val backbufL = Array((6144f / AUDIO_BUFFER_SIZE).roundToInt().coerceAtLeast(1)) {
FloatArray(AUDIO_BUFFER_SIZE)
}
val backbufR = Array((6144f / AUDIO_BUFFER_SIZE).roundToInt().coerceAtLeast(1)) {
FloatArray(AUDIO_BUFFER_SIZE)
}
private val sqrt2p = 0.7071067811865475
override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) { override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) {
// shift buffer // shift buffer
for (i in backbufL.lastIndex downTo 1) { for (i in backbufL.lastIndex downTo 1) {
@@ -74,16 +124,6 @@ class Scope : TerrarumAudioFilter() {
backbufR[0][i] = y.toFloat() backbufR[0][i] = y.toFloat()
} }
// create (L+R)/2 array
push(inbuf[0], inBuf[0])
push(inbuf[1], inBuf[1])
for (i in 0 until FFTSIZE) {
chsum.reim[2*i] = ((inBuf[0][i] + inBuf[1][i]) / 2f) * fftWin[i]
}
// do fft
FFT.fftInto(chsum, fftOut)
// copy samples over // copy samples over
outbuf.forEachIndexed { index, outTrack -> outbuf.forEachIndexed { index, outTrack ->
System.arraycopy(inbuf[index], 0, outTrack, 0, outTrack.size) System.arraycopy(inbuf[index], 0, outTrack, 0, outTrack.size)
@@ -93,47 +133,23 @@ class Scope : TerrarumAudioFilter() {
private val halfStripW = STRIP_W / 2 private val halfStripW = STRIP_W / 2
private val scopePlotCol = Color(0x61b3df_33) private val scopePlotCol = Color(0x61b3df_33)
private val spectroPlotCol = Color(0xdf6fa0_aa.toInt())
private val lowlim = -60.0
override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) { override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) {
batch.color = spectroPlotCol // vectorscope
for (bin in 0 until FFTSIZE / 2) {
val freqL = (SAMPLING_RATED / FFTSIZE) * bin
val freqR = (SAMPLING_RATED / FFTSIZE) * (bin + 1)
val magn0 = fftOut.reim[2 * bin].absoluteValue / FFTSIZE * (freqR / 10.0) // apply slope
val magn = FastMath.interpolateLinear(BasicDebugInfoWindow.FFT_SMOOTHING_FACTOR, magn0, oldFFTmagn[bin])
val magnLog = fullscaleToDecibels(magn)
if (magnLog >= lowlim) {
val xL = linToLogPerc(freqL, 24.0, 24000.0).coerceIn(0.0, 1.0) * STRIP_W
val xR = linToLogPerc(freqR, 24.0, 24000.0).coerceIn(0.0, 1.0) * STRIP_W
val w = (xR - xL)
val h = (magnLog - lowlim) / lowlim * STRIP_W
Toolkit.fillArea(batch, x + xL.toFloat(), y + STRIP_W.toFloat(), w.toFloat(), h.toFloat())
}
oldFFTmagn[bin] = magn
}
batch.color = scopePlotCol batch.color = scopePlotCol
val xxs = backbufR val xxs = backbufR
val yys = backbufL val yys = backbufL
for (t in xxs.lastIndex downTo 0) { for (t in xxs.lastIndex downTo 0) {
val xs = xxs[t] val xs = xxs[t]
val ys = yys[t] val ys = yys[t]
for (i in xs.indices.reversed()) { for (i in xs.indices.reversed()) {
val px = xs[i] * halfStripW + halfStripW val px = xs[i] * halfStripW + halfStripW
val py = ys[i] * halfStripW + halfStripW val py = ys[i] * halfStripW + halfStripW
Toolkit.fillArea(batch, x + px, y + py, 1f, 1f) Toolkit.fillArea(batch, x + px, y + py, 1f, 1f)
} }
} }
// TODO correlation meter
} }
override val debugViewHeight = STRIP_W override val debugViewHeight = STRIP_W

View File

@@ -418,7 +418,7 @@ class BasicDebugInfoWindow : UICanvas() {
fun getSmoothingFactor(sampleCount: Int) = (1.0 - (256.0 / sampleCount)) fun getSmoothingFactor(sampleCount: Int) = (1.0 - (256.0 / sampleCount))
val PEAK_SMOOTHING_FACTOR = getSmoothingFactor(640) val PEAK_SMOOTHING_FACTOR = getSmoothingFactor(640)
val FFT_SMOOTHING_FACTOR = getSmoothingFactor(1200) val FFT_SMOOTHING_FACTOR = getSmoothingFactor(2048)
val LAMP_SMOOTHING_FACTOR = getSmoothingFactor(3200) val LAMP_SMOOTHING_FACTOR = getSmoothingFactor(3200)
val RMS_SMOOTHING_FACTOR = getSmoothingFactor(12000) val RMS_SMOOTHING_FACTOR = getSmoothingFactor(12000)
} }
@@ -427,7 +427,7 @@ class BasicDebugInfoWindow : UICanvas() {
private val stripGap = 1 private val stripGap = 1
private val stripFilterHeight = 16 private val stripFilterHeight = 16
private val stripFaderHeight = meterHeight + 20 private val stripFaderHeight = meterHeight + 20
private val numberOfFilters = 10 private val numberOfFilters = 14
private val stripH = stripFaderHeight + stripFilterHeight * numberOfFilters + 16 private val stripH = stripFaderHeight + stripFilterHeight * numberOfFilters + 16
private val trackBack = listOf(COL_WELL, COL_WELL2) private val trackBack = listOf(COL_WELL, COL_WELL2)