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 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 {
TextureRegionPack(it, capsuleMosaicSize, capsuleMosaicSize)
@@ -59,17 +60,41 @@ class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
init {
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) {
batch.end()
renderNameToFBO(batch, camera, AudioMixer.musicTrack.currentTrack?.name ?: "", 0f..(width - 2*STRIP_W - capsuleHeight + maskOffWidth))
batch.begin()
if (renderFBOreq != null) {
batch.end()
width = if (renderFBOreq!!.isEmpty())
2*STRIP_W.toInt()
else {
val slen = App.fontGameFBO.getWidth(renderFBOreq!!)
if (slen > nameStrMaxLen) { nameOverflown = true }
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 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 fftOut = ComplexArray(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 STRIP_W = 9f

Binary file not shown.

View File

@@ -176,7 +176,8 @@ object AudioMixer: Disposable {
masterTrack.filters[0] = SoftClp
masterTrack.filters[1] = Buffer
masterTrack.filters[2] = Scope()
masterTrack.filters[2] = Spectro()
masterTrack.filters[3] = Vecto()
listOf(sumBus, convolveBusOpen, convolveBusCave).forEach {
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 kotlin.math.*
class Scope : 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)
}
class Spectro : TerrarumAudioFilter() {
private val FFTSIZE = 1024
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>) {
// shift buffer
for (i in backbufL.lastIndex downTo 1) {
@@ -74,16 +124,6 @@ class Scope : TerrarumAudioFilter() {
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
outbuf.forEachIndexed { index, outTrack ->
System.arraycopy(inbuf[index], 0, outTrack, 0, outTrack.size)
@@ -93,47 +133,23 @@ class Scope : TerrarumAudioFilter() {
private val halfStripW = STRIP_W / 2
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) {
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
}
// vectorscope
batch.color = scopePlotCol
val xxs = backbufR
val yys = backbufL
for (t in xxs.lastIndex downTo 0) {
val xs = xxs[t]
val ys = yys[t]
for (i in xs.indices.reversed()) {
val px = xs[i] * halfStripW + halfStripW
val py = ys[i] * halfStripW + halfStripW
Toolkit.fillArea(batch, x + px, y + py, 1f, 1f)
}
}
// TODO correlation meter
}
override val debugViewHeight = STRIP_W

View File

@@ -418,7 +418,7 @@ class BasicDebugInfoWindow : UICanvas() {
fun getSmoothingFactor(sampleCount: Int) = (1.0 - (256.0 / sampleCount))
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 RMS_SMOOTHING_FACTOR = getSmoothingFactor(12000)
}
@@ -427,7 +427,7 @@ class BasicDebugInfoWindow : UICanvas() {
private val stripGap = 1
private val stripFilterHeight = 16
private val stripFaderHeight = meterHeight + 20
private val numberOfFilters = 10
private val numberOfFilters = 14
private val stripH = stripFaderHeight + stripFilterHeight * numberOfFilters + 16
private val trackBack = listOf(COL_WELL, COL_WELL2)