mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-11 11:04:05 +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 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.
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user