mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
more musicplayer things
This commit is contained in:
@@ -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.
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user