diff --git a/app/src/main/java/io/github/jeffshee/visualizerdemo/MainActivity.kt b/app/src/main/java/io/github/jeffshee/visualizerdemo/MainActivity.kt index 0373c2a..db781b2 100644 --- a/app/src/main/java/io/github/jeffshee/visualizerdemo/MainActivity.kt +++ b/app/src/main/java/io/github/jeffshee/visualizerdemo/MainActivity.kt @@ -4,14 +4,20 @@ import android.Manifest import android.content.pm.PackageManager import android.graphics.Bitmap import android.graphics.BitmapFactory +import android.graphics.Paint +import android.os.Build import android.os.Bundle import android.support.v4.app.ActivityCompat import android.support.v4.content.ContextCompat import android.support.v7.app.AppCompatActivity -import io.github.jeffshee.visualizer.painters.fft.FftBar +import android.view.View +import io.github.jeffshee.visualizer.painters.fft.FftCircle import io.github.jeffshee.visualizer.painters.fft.FftWave -import io.github.jeffshee.visualizer.painters.fft.FftWaveRgb +import io.github.jeffshee.visualizer.painters.misc.Background import io.github.jeffshee.visualizer.painters.misc.SimpleIcon +import io.github.jeffshee.visualizer.painters.modifier.Shake +import io.github.jeffshee.visualizer.painters.modifier.Zoom +import io.github.jeffshee.visualizer.painters.waveform.Waveform import io.github.jeffshee.visualizer.utils.Preset import io.github.jeffshee.visualizer.utils.VisualizerHelper import kotlinx.android.synthetic.main.activity_main.* @@ -19,11 +25,14 @@ import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { private lateinit var helper: VisualizerHelper + private lateinit var background: Bitmap private lateinit var bitmap: Bitmap private lateinit var circleBitmap: Bitmap override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + hideSystemUI() + setContentView(R.layout.activity_main) if (ContextCompat.checkSelfPermission( this, Manifest.permission.RECORD_AUDIO @@ -38,15 +47,36 @@ class MainActivity : AppCompatActivity() { super.onRequestPermissionsResult(requestCode, permissions, grantResults) } + override fun onWindowFocusChanged(hasFocus: Boolean) { + super.onWindowFocusChanged(hasFocus) + hideSystemUI() + } + + private fun hideSystemUI() { + val decorView = window.decorView + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + decorView.systemUiVisibility = ( + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + or View.SYSTEM_UI_FLAG_FULLSCREEN + or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + or View.SYSTEM_UI_FLAG_LAYOUT_STABLE + or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + ) + } + } + private fun init() { + background = BitmapFactory.decodeResource(resources, R.drawable.background) bitmap = BitmapFactory.decodeResource(resources, R.drawable.chino512) circleBitmap = SimpleIcon.getCircledBitmap(bitmap) helper = VisualizerHelper(0) visual.setPainterList( helper, listOf( - //Preset.getPresetWithIcon("cWaveRgbIcon", bitmap) - Preset.getPresetWithIcon("cIcon", bitmap) + Preset.getPresetWithBitmap("liveBg", background), + + FftCircle().apply { paint.strokeWidth = 8f;paint.strokeCap = Paint.Cap.ROUND } ) ) } diff --git a/app/src/main/res/drawable-xxhdpi/background.png b/app/src/main/res/drawable-xxhdpi/background.png deleted file mode 100644 index 3dfe522..0000000 Binary files a/app/src/main/res/drawable-xxhdpi/background.png and /dev/null differ diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/Painter.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/Painter.kt index 969d669..4348cd2 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/Painter.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/Painter.kt @@ -6,7 +6,6 @@ import org.apache.commons.math3.analysis.interpolation.AkimaSplineInterpolator import org.apache.commons.math3.analysis.interpolation.LinearInterpolator import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction import kotlin.math.cos -import kotlin.math.exp import kotlin.math.sin abstract class Painter { @@ -14,6 +13,8 @@ abstract class Painter { private val li = LinearInterpolator() private val sp = AkimaSplineInterpolator() + abstract fun calc(helper: VisualizerHelper) + /** * An abstract function that every painters must implement and do their drawing there. * @@ -36,7 +37,7 @@ abstract class Painter { * @param interpolator Which interpolator to use, `li` for Linear, `sp` for Spline * * @return a `PolynomialSplineFunction` (psf). To get the value, use - * `psf.value(x)`, where `x` must be a Double value from 0 to `sliceNum` + * `psf.value(x)`, where `x` must be a Double value from 0 to `num` */ fun interpolateFft( gravityModels: Array, sliceNum: Int, interpolator: String @@ -64,7 +65,7 @@ abstract class Painter { * @param interpolator Which interpolator to use, `li` for Linear, `sp` for Spline * * @return a `PolynomialSplineFunction` (psf). To get the value, use - * `psf.value(x)`, where `x` must be a Double value from 0 to `sliceNum` + * `psf.value(x)`, where `x` must be a Double value from 0 to `num` */ fun interpolateFftCircle( gravityModels: Array, sliceNum: Int, interpolator: String @@ -125,27 +126,43 @@ abstract class Painter { /** * Patch the Fft to a MirrorFft * - * `[0, 1, ..., n] -> [0, 1, ..., n, n, ... , 1, 0]` - * * @param fft Fft + * @param mode when 0 -> do nothing + * when 1 -> + * `[0, 1, ..., n] -> [n, ..., 1, 0, 0, 1, ..., n]` + * when 2 -> + * `[0, 1, ..., n] -> [0, 1, ..., n, n, ..., 1, 0]` + * when 3 -> + * `[0, 1, ..., n] -> [n/2, ..., 1, 0, 0, 1, ..., n/2]` + * when 4 -> + * `[0, 1, ..., n] -> [0, 1, ..., n/2, n/2, ..., 1, 0]` * @return MirrorFft */ - fun getMirrorFft(fft: DoubleArray): DoubleArray { - val patched = DoubleArray(fft.size * 2) - fft.forEachIndexed { index, d -> - patched[fft.lastIndex - index] = d - patched[fft.size + index] = d + fun getMirrorFft(fft: DoubleArray, mode: Int = 1): DoubleArray { + return when (mode) { + 1 -> { + fft.sliceArray(0..fft.lastIndex).reversedArray() + fft.sliceArray(0..fft.lastIndex) + } + 2 -> { + fft.sliceArray(0..fft.lastIndex) + fft.sliceArray(0..fft.lastIndex).reversedArray() + } + 3 -> { + fft.sliceArray(0..fft.lastIndex / 2).reversedArray() + fft.sliceArray(0..fft.lastIndex / 2) + } + 4 -> { + fft.sliceArray(0..fft.lastIndex / 2) + fft.sliceArray(0..fft.lastIndex / 2).reversedArray() + } + else -> fft } - return patched } /** * Boost high values while suppress low values, generally give a powerful feeling * @param fft Fft * @param param Parameter, adjust to fit your liking - * @return BoostedFft + * @return PowerFft */ - fun boost(fft: DoubleArray, param: Double = 100.0): DoubleArray { + fun getPowerFft(fft: DoubleArray, param: Double = 100.0): DoubleArray { return fft.map { it * it / param }.toDoubleArray() } diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftBar.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftBar.kt index 8f5b223..e8caefc 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftBar.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftBar.kt @@ -5,53 +5,58 @@ import android.graphics.Color import android.graphics.Paint import io.github.jeffshee.visualizer.painters.Painter import io.github.jeffshee.visualizer.utils.VisualizerHelper +import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction class FftBar( var paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG).apply { color = Color.WHITE;style = Paint.Style.STROKE;strokeWidth = 2f }, + // var startHz: Int = 0, var endHz: Int = 2000, - var barNum: Int = 128, + // + var num: Int = 128, var interpolator: String = "li", + // var side: String = "a", - var mode: String = "", - var xR: Float = 0f, - var yR: Float = 1f, - var wR: Float = 1f, + var mirror: Boolean = false, + var power: Boolean = false, + // var gapX: Float = 0f, - var ampR: Float = 1f, - var enableBoost: Boolean = false + var ampR: Float = 1f ) : Painter() { private var points = Array(0) { GravityModel() } + private var skipFrame = false + lateinit var fft: DoubleArray + lateinit var psf: PolynomialSplineFunction + + override fun calc(helper: VisualizerHelper) { + fft = helper.getFftMagnitudeRange(startHz, endHz) + + if (isQuiet(fft)) { + skipFrame = true + return + } else skipFrame = false + + if (power) fft = getPowerFft(fft) + if (mirror) fft = getMirrorFft(fft) + + if (points.size != fft.size) points = + Array(fft.size) { GravityModel(0f) } + points.forEachIndexed { index, bar -> bar.update(fft[index].toFloat() * ampR) } + + psf = interpolateFft(points, num, interpolator) + } override fun draw(canvas: Canvas, helper: VisualizerHelper) { - var fft = helper.getFftMagnitudeRange(startHz, endHz) - if (isQuiet(fft)) return - - val width = canvas.width.toFloat() * wR - if(enableBoost) fft = boost(fft) - - when (mode) { - "mirror" -> { - val mirrorFft = getMirrorFft(fft) - if (points.size != mirrorFft.size) points = - Array(mirrorFft.size) { GravityModel(0f) } - points.forEachIndexed { index, bar -> bar.update(mirrorFft[index].toFloat() * ampR) } - } - else -> { - if (points.size != fft.size) points = - Array(fft.size) { GravityModel(0f) } - points.forEachIndexed { index, bar -> bar.update(fft[index].toFloat() * ampR) } - } - } + if (skipFrame) return - val psf = interpolateFft(points, barNum, interpolator) + val width = canvas.width.toFloat() + val barWidth = (width - (num + 1) * gapX) / num - val barWidth = (width - (barNum + 1) * gapX) / barNum - drawHelper(canvas, side, xR, yR) { - for (i in 0 until barNum) { + drawHelper(canvas, side, 0f, .5f) { + for (i in 0 until num) { canvas.drawRect( barWidth * i + gapX * (i + 1), -psf.value(i.toDouble()).toFloat(), barWidth * (i + 1) + gapX * (i + 1), 0f, diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftCircle.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftCircle.kt index cf29521..a5b3d79 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftCircle.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftCircle.kt @@ -5,70 +5,88 @@ import android.graphics.Color import android.graphics.Paint import io.github.jeffshee.visualizer.painters.Painter import io.github.jeffshee.visualizer.utils.VisualizerHelper +import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction import kotlin.math.PI +import kotlin.math.min class FftCircle( var paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG).apply { color = Color.WHITE;style = Paint.Style.STROKE;strokeWidth = 2f }, + // var startHz: Int = 0, var endHz: Int = 2000, - var barNum: Int = 64, + // + var num: Int = 64, var interpolator: String = "li", + // var side: String = "a", - var xR: Float = .5f, - var yR: Float = .5f, - var baseR: Float = .4f, - var ampR: Float = 1f, - var enableBoost: Boolean = true + var mirror: Boolean = false, + var power: Boolean = true, + // + var radiusR: Float = .4f, + var ampR: Float = 1f ) : Painter() { private var points = Array(0) { GravityModel() } + private var skipFrame = false + lateinit var fft: DoubleArray + lateinit var psf: PolynomialSplineFunction - override fun draw(canvas: Canvas, helper: VisualizerHelper) { - val fft = helper.getFftMagnitudeRange(startHz, endHz) - if (isQuiet(fft)) return + override fun calc(helper: VisualizerHelper) { + fft = helper.getFftMagnitudeRange(startHz, endHz) + if (isQuiet(fft)) { + skipFrame = true + return + } else skipFrame = false + + if (power) fft = getPowerFft(fft) + fft = if (mirror) getMirrorFft(fft) + else getCircleFft(fft) - var circleFft = this.getCircleFft(fft) - if(enableBoost) circleFft = boost(circleFft) + if (points.size != fft.size) points = Array(fft.size) { GravityModel(0f) } + points.forEachIndexed { index, bar -> bar.update(fft[index].toFloat() * ampR) } - if (points.size != circleFft.size) points = Array(circleFft.size) { GravityModel(0f) } - points.forEachIndexed { index, bar -> bar.update(circleFft[index].toFloat() * ampR) } - val psf = interpolateFftCircle(points, barNum, interpolator) + psf = interpolateFftCircle(points, num, interpolator) + } + + override fun draw(canvas: Canvas, helper: VisualizerHelper) { + if (skipFrame) return - val angle = 2 * PI.toFloat() / barNum - val pts = FloatArray(4 * barNum) + val angle = 2 * PI.toFloat() / num + val pts = FloatArray(4 * num) + val shortest = min(canvas.width, canvas.height) - drawHelper(canvas, side, xR, yR, { - for (i in 0 until barNum) { + drawHelper(canvas, side, .5f, .5f, { + for (i in 0 until num) { val start = - toCartesian(canvas.width / 2f * baseR, angle * i) + toCartesian(shortest / 2f * radiusR, angle * i) val stop = toCartesian( - canvas.width / 2f * baseR + psf.value(i.toDouble()).toFloat(), angle * i + shortest / 2f * radiusR + psf.value(i.toDouble()).toFloat(), angle * i ) pts[4 * i] = start[0];pts[4 * i + 1] = start[1] pts[4 * i + 2] = stop[0];pts[4 * i + 3] = stop[1] } canvas.drawLines(pts, paint) }, { - for (i in 0 until barNum) { + for (i in 0 until num) { val start = - toCartesian(canvas.width / 2f * baseR, angle * i) + toCartesian(shortest / 2f * radiusR, angle * i) val stop = toCartesian( - canvas.width / 2f * baseR - psf.value(i.toDouble()).toFloat(), angle * i + shortest / 2f * radiusR - psf.value(i.toDouble()).toFloat(), angle * i ) pts[4 * i] = start[0];pts[4 * i + 1] = start[1] pts[4 * i + 2] = stop[0];pts[4 * i + 3] = stop[1] } canvas.drawLines(pts, paint) }, { - for (i in 0 until barNum) { + for (i in 0 until num) { val start = toCartesian( - canvas.width / 2f * baseR + psf.value(i.toDouble()).toFloat(), angle * i + shortest / 2f * radiusR + psf.value(i.toDouble()).toFloat(), angle * i ) val stop = toCartesian( - canvas.width / 2f * baseR - psf.value(i.toDouble()).toFloat(), angle * i + shortest / 2f * radiusR - psf.value(i.toDouble()).toFloat(), angle * i ) pts[4 * i] = start[0];pts[4 * i + 1] = start[1] pts[4 * i + 2] = stop[0];pts[4 * i + 3] = stop[1] diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftCircleWave.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftCircleWave.kt index cb2e868..a4c0dd8 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftCircleWave.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftCircleWave.kt @@ -6,42 +6,61 @@ import android.graphics.Paint import android.graphics.Path import io.github.jeffshee.visualizer.painters.Painter import io.github.jeffshee.visualizer.utils.VisualizerHelper +import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction import kotlin.math.PI +import kotlin.math.min class FftCircleWave( var paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG).apply { color = Color.WHITE }, + // var startHz: Int = 0, var endHz: Int = 2000, - var sliceNum: Int = 128, + // + var num: Int = 128, var interpolator: String = "sp", + // var side: String = "a", - var xR: Float = .5f, - var yR: Float = .5f, - var baseR: Float = .4f, - var ampR: Float = .6f, - var enableBoost: Boolean = true + var mirror: Boolean = false, + var power: Boolean = true, + // + var radiusR: Float = .4f, + var ampR: Float = .6f ) : Painter() { private val path = Path() private var points = Array(0) { GravityModel() } + private var skipFrame = false + lateinit var fft: DoubleArray + lateinit var psf: PolynomialSplineFunction - override fun draw(canvas: Canvas, helper: VisualizerHelper) { - val fft = helper.getFftMagnitudeRange(startHz, endHz) + override fun calc(helper: VisualizerHelper) { + fft = helper.getFftMagnitudeRange(startHz, endHz) + if (isQuiet(fft) && paint.style == Paint.Style.STROKE) { + skipFrame = true + return + } else skipFrame = false + + if (power) fft = getPowerFft(fft) + fft = if (mirror) getMirrorFft(fft) + else getCircleFft(fft) - var circleFft = this.getCircleFft(fft) - if (enableBoost) circleFft = boost(circleFft) + if (points.size != fft.size) points = Array(fft.size) { GravityModel(0f) } + points.forEachIndexed { index, bar -> bar.update(fft[index].toFloat() * ampR) } - if (points.size != circleFft.size) points = Array(circleFft.size) { GravityModel(0f) } - points.forEachIndexed { index, bar -> bar.update(circleFft[index].toFloat() * ampR) } - val psf = interpolateFftCircle(points, sliceNum, interpolator) + psf = interpolateFftCircle(points, num, interpolator) + } + + override fun draw(canvas: Canvas, helper: VisualizerHelper) { + if (skipFrame) return - val angle = 2 * PI.toFloat() / sliceNum + val angle = 2 * PI.toFloat() / num + val shortest = min(canvas.width, canvas.height) - drawHelper(canvas, side, xR, yR, { - for (i in 0..sliceNum) { - val point = toCartesian(canvas.width / 2f * baseR + psf.value(i.toDouble()).toFloat(), angle * i) + drawHelper(canvas, side, .5f, .5f, { + for (i in 0..num) { + val point = toCartesian(shortest / 2f * radiusR + psf.value(i.toDouble()).toFloat(), angle * i) if (i == 0) path.moveTo(point[0], point[1]) else path.lineTo(point[0], point[1]) } @@ -49,14 +68,14 @@ class FftCircleWave( canvas.drawPath(path, paint) path.reset() }, { - for (i in 0..sliceNum) { - val point = toCartesian(canvas.width / 2f * baseR, angle * i) + for (i in 0..num) { + val point = toCartesian(shortest / 2f * radiusR, angle * i) if (i == 0) path.moveTo(point[0], point[1]) else path.lineTo(point[0], point[1]) } path.close() - for (i in 0..sliceNum) { - val point = toCartesian(canvas.width / 2f * baseR - psf.value(i.toDouble()).toFloat(), angle * i) + for (i in 0..num) { + val point = toCartesian(shortest / 2f * radiusR - psf.value(i.toDouble()).toFloat(), angle * i) if (i == 0) path.moveTo(point[0], point[1]) else path.lineTo(point[0], point[1]) } @@ -65,14 +84,14 @@ class FftCircleWave( canvas.drawPath(path, paint) path.reset() }, { - for (i in 0..sliceNum) { - val point = toCartesian(canvas.width / 2f * baseR + psf.value(i.toDouble()).toFloat(), angle * i) + for (i in 0..num) { + val point = toCartesian(shortest / 2f * radiusR + psf.value(i.toDouble()).toFloat(), angle * i) if (i == 0) path.moveTo(point[0], point[1]) else path.lineTo(point[0], point[1]) } path.close() - for (i in 0..sliceNum) { - val point = toCartesian(canvas.width / 2f * baseR - psf.value(i.toDouble()).toFloat(), angle * i) + for (i in 0..num) { + val point = toCartesian(shortest / 2f * radiusR - psf.value(i.toDouble()).toFloat(), angle * i) if (i == 0) path.moveTo(point[0], point[1]) else path.lineTo(point[0], point[1]) } diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftCircleWaveRgb.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftCircleWaveRgb.kt index ea0eb8d..b262778 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftCircleWaveRgb.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftCircleWaveRgb.kt @@ -6,43 +6,42 @@ import io.github.jeffshee.visualizer.utils.VisualizerHelper class FftCircleWaveRgb( flags: Int = Paint.ANTI_ALIAS_FLAG, - startHzR: Int = 0, - endHzR: Int = 2000, - startHzG: Int = 0, - endHzG: Int = 2000, - startHzB: Int = 0, - endHzB: Int = 2000, - sliceNum: Int = 128, + var color: List = listOf(Color.RED, Color.GREEN, Color.BLUE), + // + startHz: Int = 0, + endHz: Int = 2000, + // + num: Int = 128, interpolator: String = "sp", + // side: String = "a", - var xR: Float = .5f, - var yR: Float = .5f, - var color: List = listOf(Color.RED, Color.GREEN, Color.BLUE) + mirror: Boolean = false, + power: Boolean = true, + // + radiusR: Float = .4f, + ampR: Float = .6f, + var rot: Float = 10f ) : Painter() { - private val waveR = FftCircleWave(Paint(flags).apply { - style = Paint.Style.FILL;color = this@FftCircleWaveRgb.color[0];xfermode = PorterDuffXfermode( - PorterDuff.Mode.ADD - ) - }, startHzR, endHzR, sliceNum, interpolator, side, xR, yR) + private val wave = FftCircleWave(Paint(flags).apply { + style = Paint.Style.FILL;xfermode = PorterDuffXfermode(PorterDuff.Mode.ADD) + }, startHz, endHz, num, interpolator, side, mirror, power, radiusR, ampR) - private val waveG = FftCircleWave(Paint(flags).apply { - style = Paint.Style.FILL;color = this@FftCircleWaveRgb.color[1];xfermode = PorterDuffXfermode( - PorterDuff.Mode.ADD - ) - }, startHzG, endHzG, sliceNum, interpolator, side, xR, yR) - - private val waveB = FftCircleWave(Paint(flags).apply { - style = Paint.Style.FILL;color = this@FftCircleWaveRgb.color[2];xfermode = PorterDuffXfermode( - PorterDuff.Mode.ADD - ) - }, startHzB, endHzB, sliceNum, interpolator, side, xR, yR) + override fun calc(helper: VisualizerHelper) { + wave.calc(helper) + } override fun draw(canvas: Canvas, helper: VisualizerHelper) { - waveR.draw(canvas, helper) - rotateHelper(canvas, 5f, xR, yR){waveG.draw(canvas, helper)} - rotateHelper(canvas, 10f, xR, yR){waveB.draw(canvas, helper)} - + wave.paint.color = color[0] + wave.draw(canvas, helper) + rotateHelper(canvas, rot, .5f, .5f) { + wave.paint.color = color[1] + wave.draw(canvas, helper) + } + rotateHelper(canvas, rot * 2, .5f, .5f) { + wave.paint.color = color[2] + wave.draw(canvas, helper) + } } } \ No newline at end of file diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftLine.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftLine.kt index 185d0a0..15b9fd0 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftLine.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftLine.kt @@ -5,64 +5,69 @@ import android.graphics.Color import android.graphics.Paint import io.github.jeffshee.visualizer.painters.Painter import io.github.jeffshee.visualizer.utils.VisualizerHelper +import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction class FftLine( var paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG).apply { color = Color.WHITE;style = Paint.Style.STROKE;strokeWidth = 2f }, + // var startHz: Int = 0, var endHz: Int = 2000, - var barNum: Int = 128, + // + var num: Int = 128, var interpolator: String = "li", + // var side: String = "a", - var mode: String = "", - var xR: Float = 0f, - var yR: Float = 1f, - var wR: Float = 1f, - var ampR: Float = 1f, - var enableBoost: Boolean = false + var mirror: Boolean = false, + var power: Boolean = false, + // + var ampR: Float = 1f ) : Painter() { private var points = Array(0) { GravityModel() } + private var skipFrame = false + lateinit var fft: DoubleArray + lateinit var psf: PolynomialSplineFunction - override fun draw(canvas: Canvas, helper: VisualizerHelper) { - var fft = helper.getFftMagnitudeRange(startHz, endHz) - if (isQuiet(fft)) return + override fun calc(helper: VisualizerHelper) { + fft = helper.getFftMagnitudeRange(startHz, endHz) - val width = canvas.width.toFloat() * wR - if(enableBoost) fft = boost(fft) + if (isQuiet(fft)) { + skipFrame = true + return + } else skipFrame = false - when (mode) { - "mirror" -> { - val mirrorFft = getMirrorFft(fft) - if (points.size != mirrorFft.size) points = - Array(mirrorFft.size) { GravityModel(0f) } - points.forEachIndexed { index, bar -> bar.update(mirrorFft[index].toFloat() * ampR) } - } - else -> { - if (points.size != fft.size) points = - Array(fft.size) { GravityModel(0f) } - points.forEachIndexed { index, bar -> bar.update(fft[index].toFloat() * ampR) } - } - } + if (power) fft = getPowerFft(fft) + if (mirror) fft = getMirrorFft(fft) + + if (points.size != fft.size) points = + Array(fft.size) { GravityModel(0f) } + points.forEachIndexed { index, bar -> bar.update(fft[index].toFloat() * ampR) } + + psf = interpolateFft(points, num, interpolator) + } + + override fun draw(canvas: Canvas, helper: VisualizerHelper) { + if (skipFrame) return - val psf = interpolateFft(points, barNum, interpolator) + val width = canvas.width.toFloat() + val gapWidth = width / num - val barWidth = width / barNum - val pts = FloatArray(4 * barNum) - drawHelper(canvas, side, xR, yR, { - for (i in 0 until barNum) { - pts[4 * i] = barWidth * (i + .5f) + val pts = FloatArray(4 * num) + drawHelper(canvas, side, 0f, .5f, { + for (i in 0 until num) { + pts[4 * i] = gapWidth * (i + .5f) pts[4 * i + 1] = -psf.value(i.toDouble()).toFloat() - pts[4 * i + 2] = barWidth * (i + .5f) + pts[4 * i + 2] = gapWidth * (i + .5f) pts[4 * i + 3] = 0f } canvas.drawLines(pts, paint) }, { - for (i in 0 until barNum) { - pts[4 * i] = barWidth * (i + .5f) + for (i in 0 until num) { + pts[4 * i] = gapWidth * (i + .5f) pts[4 * i + 1] = -psf.value(i.toDouble()).toFloat() - pts[4 * i + 2] = barWidth * (i + .5f) + pts[4 * i + 2] = gapWidth * (i + .5f) pts[4 * i + 3] = psf.value(i.toDouble()).toFloat() } canvas.drawLines(pts, paint) diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftWave.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftWave.kt index 786e4a8..ab85b05 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftWave.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftWave.kt @@ -6,64 +6,70 @@ import android.graphics.Paint import android.graphics.Path import io.github.jeffshee.visualizer.painters.Painter import io.github.jeffshee.visualizer.utils.VisualizerHelper +import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction class FftWave( var paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG).apply { color = Color.WHITE }, + // var startHz: Int = 0, var endHz: Int = 2000, - var sliceNum: Int = 128, + // + var num: Int = 128, var interpolator: String = "sp", + // var side: String = "a", - var mode: String = "", - var xR: Float = 0f, - var yR: Float = 1f, - var wR: Float = 1f, - var ampR: Float = 1f, - var enableBoost: Boolean = false + var mirror: Boolean = false, + var power: Boolean = false, + // + var ampR: Float = 1f ) : Painter() { private val path = Path() private var points = Array(0) { GravityModel() } + private var skipFrame = false + lateinit var fft: DoubleArray + lateinit var psf: PolynomialSplineFunction - override fun draw(canvas: Canvas, helper: VisualizerHelper) { - var fft = helper.getFftMagnitudeRange(startHz, endHz) - if (isQuiet(fft)) return + override fun calc(helper: VisualizerHelper) { + fft = helper.getFftMagnitudeRange(startHz, endHz) - val width = canvas.width.toFloat() * wR - if(enableBoost) fft = boost(fft) + if (isQuiet(fft)) { + skipFrame = true + return + } else skipFrame = false - when (mode) { - "mirror" -> { - val mirrorFft = getMirrorFft(fft) - if (points.size != mirrorFft.size) points = - Array(mirrorFft.size) { GravityModel(0f) } - points.forEachIndexed { index, bar -> bar.update(mirrorFft[index].toFloat() * ampR) } - } - else -> { - if (points.size != fft.size) points = - Array(fft.size) { GravityModel(0f) } - points.forEachIndexed { index, bar -> bar.update(fft[index].toFloat() * ampR) } - } - } + if (power) fft = getPowerFft(fft) + if (mirror) fft = getMirrorFft(fft) + + if (points.size != fft.size) points = + Array(fft.size) { GravityModel(0f) } + points.forEachIndexed { index, bar -> bar.update(fft[index].toFloat() * ampR) } + + psf = interpolateFft(points, num, interpolator) + } + + override fun draw(canvas: Canvas, helper: VisualizerHelper) { + if (skipFrame) return + + val width = canvas.width.toFloat() - val psf = interpolateFft(points, sliceNum, interpolator) - val sliceWidth = width / sliceNum + val sliceWidth = width / num if (paint.style == Paint.Style.STROKE) { path.moveTo(0f, -psf.value(0.0).toFloat()) - for (i in 1..sliceNum) { + for (i in 1..num) { path.lineTo(sliceWidth * i, -psf.value(i.toDouble()).toFloat()) } } else { path.moveTo(0f, 1f) - for (i in 0..sliceNum) { + for (i in 0..num) { path.lineTo(sliceWidth * i, -psf.value(i.toDouble()).toFloat()) } path.lineTo(width, 1f) path.close() } - drawHelper(canvas, side, xR, yR) { canvas.drawPath(path, paint) } + drawHelper(canvas, side, 0f, .5f) { canvas.drawPath(path, paint) } path.reset() } } \ No newline at end of file diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftWaveRgb.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftWaveRgb.kt index 3057556..f82629e 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftWaveRgb.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/fft/FftWaveRgb.kt @@ -6,45 +6,42 @@ import io.github.jeffshee.visualizer.utils.VisualizerHelper class FftWaveRgb( flags: Int = Paint.ANTI_ALIAS_FLAG, - startHzR: Int = 0, - endHzR: Int = 1000, - startHzG: Int = 400, - endHzG: Int = 1500, - startHzB: Int = 800, - endHzB: Int = 2000, - sliceNum: Int = 128, + var color: List = listOf(Color.RED, Color.GREEN, Color.BLUE), + // + startHz: Int = 0, + endHz: Int = 2000, + // + num: Int = 128, interpolator: String = "sp", - side: String = "a", - mode: String = "", - xR: Float = 0f, - yR: Float = 1f, - wR: Float = 1f, - ampR: Float = 1f, - var color: List = listOf(Color.RED, Color.GREEN, Color.BLUE) - + // + var side: String = "a", + mirror: Boolean = false, + power: Boolean = false, + // + ampR: Float = 1f ) : Painter() { - private val waveR = FftWave(Paint(flags).apply { - style = Paint.Style.FILL;color = this@FftWaveRgb.color[0];xfermode = PorterDuffXfermode( - PorterDuff.Mode.ADD - ) - }, startHzR, endHzR, sliceNum, interpolator, side, mode, xR, yR, wR, ampR) - - private val waveG = FftWave(Paint(flags).apply { - style = Paint.Style.FILL;color = this@FftWaveRgb.color[1];xfermode = PorterDuffXfermode( - PorterDuff.Mode.ADD - ) - }, startHzG, endHzG, sliceNum, interpolator, side, mode, xR, yR, wR, ampR) + private val wave = FftWave(Paint(flags).apply { + style = Paint.Style.FILL;xfermode = PorterDuffXfermode(PorterDuff.Mode.ADD) + }, startHz, endHz, num, interpolator, side, mirror, power, ampR) - private val waveB = FftWave(Paint(flags).apply { - style = Paint.Style.FILL;color = this@FftWaveRgb.color[2];xfermode = PorterDuffXfermode( - PorterDuff.Mode.ADD - ) - }, startHzB, endHzB, sliceNum, interpolator, side, mode, xR, yR, wR, ampR) + override fun calc(helper: VisualizerHelper) { + wave.calc(helper) + } override fun draw(canvas: Canvas, helper: VisualizerHelper) { - waveR.draw(canvas, helper) - waveG.draw(canvas, helper) - waveB.draw(canvas, helper) + canvas.save() + canvas.scale(1.2f, 1f, canvas.width / 2f, canvas.height.toFloat()) + drawHelper(canvas, side, -.03f, 0f) { + wave.paint.color = color[0] + wave.draw(canvas, helper) + } + wave.paint.color = color[1] + wave.draw(canvas, helper) + drawHelper(canvas, side, .03f, 0f) { + wave.paint.color = color[2] + wave.draw(canvas, helper) + } + canvas.restore() } } \ No newline at end of file diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/misc/Background.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/misc/Background.kt index 0662403..91f39c2 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/misc/Background.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/misc/Background.kt @@ -7,24 +7,26 @@ import kotlin.math.max class Background( var bitmap: Bitmap, - var xR: Float = .5f, - var yR: Float = .5f, - var wR: Float = 1f + // + var scaleXY: Float = 1f ) : Painter() { private val matrix = Matrix() + override fun calc(helper: VisualizerHelper) { + } + override fun draw(canvas: Canvas, helper: VisualizerHelper) { bitmap.apply bitmap@{ matrix.apply { val scale = max( - canvas.width.toFloat() * wR / this@bitmap.width, - canvas.height.toFloat() * wR / this@bitmap.height + canvas.width.toFloat() * scaleXY / this@bitmap.width, + canvas.height.toFloat() * scaleXY / this@bitmap.height ) postScale(scale, scale) postTranslate(-scale * this@bitmap.width / 2f, -scale * this@bitmap.height.toFloat() / 2f) } - drawHelper(canvas, "a", xR, yR) { + drawHelper(canvas, "a", .5f, .5f) { canvas.drawBitmap(this, matrix, null) } matrix.reset() diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/misc/SimpleIcon.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/misc/SimpleIcon.kt index e6ac937..9daf1b7 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/misc/SimpleIcon.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/misc/SimpleIcon.kt @@ -3,12 +3,12 @@ package io.github.jeffshee.visualizer.painters.misc import android.graphics.* import io.github.jeffshee.visualizer.painters.Painter import io.github.jeffshee.visualizer.utils.VisualizerHelper +import kotlin.math.min class SimpleIcon( var bitmap: Bitmap, - var xR: Float = .5f, - var yR: Float = .5f, - var baseR: Float = .3f + // + var radiusR: Float = .3f ) : Painter() { private val matrix = Matrix() @@ -27,14 +27,18 @@ class SimpleIcon( } } + override fun calc(helper: VisualizerHelper) { + } + override fun draw(canvas: Canvas, helper: VisualizerHelper) { + val shortest = min(canvas.width, canvas.height) bitmap.apply bitmap@{ - val radius = canvas.width * baseR + val radius = shortest * radiusR matrix.apply { postScale(radius / this@bitmap.width, radius / this@bitmap.width) postTranslate(-radius / 2f, -radius / 2f) } - drawHelper(canvas, "a", xR, yR) { + drawHelper(canvas, "a", .5f, .5f) { canvas.drawBitmap(this, matrix, null) } matrix.reset() diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/misc/SimpleText.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/misc/SimpleText.kt index 209bfcc..8750307 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/misc/SimpleText.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/misc/SimpleText.kt @@ -7,11 +7,14 @@ import io.github.jeffshee.visualizer.utils.VisualizerHelper class SimpleText( private val paint: Paint = Paint(), + var text: String = "", + // var x: Float = 100f, - var y: Float = 100f, - var text: String = "" + var y: Float = 100f ) : Painter() { + override fun calc(helper: VisualizerHelper) { + } override fun draw(canvas: Canvas, helper: VisualizerHelper) { canvas.drawText(text, x, y, paint) diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Beat.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Beat.kt index 5429aa9..dfebc3c 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Beat.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Beat.kt @@ -7,44 +7,53 @@ import io.github.jeffshee.visualizer.utils.VisualizerHelper class Beat : Painter { var painters: List + // var startHz: Int var endHz: Int - var xR: Float - var yR: Float - var baseR: Float + // + var pxR: Float + var pyR: Float + // + var radiusR: Float var beatAmpR: Float var peak: Float constructor( - painters: List, startHz: Int = 60, endHz: Int = 800, xR: Float = .5f, yR: Float = .5f, - baseR: Float = 1f, beatAmpR: Float = 1f, peak: Float = 200f + painters: List, startHz: Int = 60, endHz: Int = 800, pxR: Float = .5f, pyR: Float = .5f, + radiusR: Float = 1f, beatAmpR: Float = 1f, peak: Float = 200f ) { this.painters = painters this.startHz = startHz this.endHz = endHz - this.xR = xR - this.yR = yR - this.baseR = baseR + this.pxR = pxR + this.pyR = pyR + this.radiusR = radiusR this.beatAmpR = beatAmpR this.peak = peak } constructor( - painter: Painter, startHz: Int = 60, endHz: Int = 800, xR: Float = .5f, yR: Float = .5f, - baseR: Float = 1f, beatAmpR: Float = 1f, peak: Float = 200f + painter: Painter, startHz: Int = 60, endHz: Int = 800, pxR: Float = .5f, pyR: Float = .5f, + radiusR: Float = 1f, beatAmpR: Float = 1f, peak: Float = 200f ) : this( - listOf(painter), startHz, endHz, xR, yR, baseR, beatAmpR, peak + listOf(painter), startHz, endHz, pxR, pyR, radiusR, beatAmpR, peak ) private val energy = GravityModel(0f) + override fun calc(helper: VisualizerHelper) { + energy.update(helper.getFftMagnitudeRange(startHz, endHz).average().toFloat()) + painters.forEach { painter -> + painter.calc(helper) + } + } + override fun draw(canvas: Canvas, helper: VisualizerHelper) { canvas.save() - energy.update(helper.getFftMagnitudeRange(startHz, endHz).average().toFloat()) - val width = canvas.width * (baseR + energy.height / peak * beatAmpR) + val width = canvas.width * (radiusR + energy.height / peak * beatAmpR) canvas.scale( width / canvas.width, width / canvas.width, - canvas.width * xR, canvas.height * yR + canvas.width * pxR, canvas.height * pyR ) painters.forEach { painter -> painter.draw(canvas, helper) diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Move.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Move.kt index 91eb1d5..a8aeff8 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Move.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Move.kt @@ -6,6 +6,7 @@ import io.github.jeffshee.visualizer.utils.VisualizerHelper class Move : Painter { var painters: List + // var xR: Float var yR: Float @@ -19,6 +20,12 @@ class Move : Painter { listOf(painter), xR, yR ) + override fun calc(helper: VisualizerHelper) { + painters.forEach { painter -> + painter.calc(helper) + } + } + override fun draw(canvas: Canvas, helper: VisualizerHelper) { canvas.save() canvas.translate(canvas.width * xR, canvas.height * yR) diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Rotate.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Rotate.kt index 8b1cb75..08b2dd7 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Rotate.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Rotate.kt @@ -6,27 +6,34 @@ import io.github.jeffshee.visualizer.utils.VisualizerHelper class Rotate : Painter { var painters: List - var xR: Float - var yR: Float + // + var pxR: Float + var pyR: Float + // var rpm: Float var offset: Float - constructor(painters: List, xR: Float = .5f, yR: Float = .5f, rpm: Float = 1f, offset: Float = 0f) { + constructor(painters: List, pxR: Float = .5f, pyR: Float = .5f, rpm: Float = 1f, offset: Float = 0f) { this.painters = painters - this.xR = xR - this.yR = yR + this.pxR = pxR + this.pyR = pyR this.rpm = rpm this.offset = offset } - constructor(painter: Painter, xR: Float = .5f, yR: Float = .5f, rpm: Float = 1f, offset: Float = 0f) : this( - listOf(painter), xR, yR, rpm, offset + constructor(painter: Painter, pxR: Float = .5f, pyR: Float = .5f, rpm: Float = 1f, offset: Float = 0f) : this( + listOf(painter), pxR, pyR, rpm, offset ) private var rot: Float = 0f + override fun calc(helper: VisualizerHelper) { + painters.forEach { painter -> + painter.calc(helper) + } + } override fun draw(canvas: Canvas, helper: VisualizerHelper) { - rotateHelper(canvas, rot + offset, xR, yR) { + rotateHelper(canvas, rot + offset, pxR, pyR) { painters.forEach { painter -> painter.draw(canvas, helper) } diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Scale.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Scale.kt index 77635c2..4b8ea0d 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Scale.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Scale.kt @@ -6,27 +6,35 @@ import io.github.jeffshee.visualizer.utils.VisualizerHelper class Scale : Painter { var painters: List - var wR: Float - var hR: Float + // + var scaleX: Float + var scaleY: Float + // var pxR: Float var pyR: Float - constructor(painters: List, wR: Float = 1f, hR: Float = 1f, pxR: Float = .5f, pyR: Float = .5f) { + constructor(painters: List, scaleX: Float = 1f, scaleY: Float = 1f, pxR: Float = .5f, pyR: Float = .5f) { this.painters = painters - this.wR = wR - this.hR = hR + this.scaleX = scaleX + this.scaleY = scaleY this.pxR = pxR this.pyR = pyR } - constructor(painter: Painter, wR: Float = 1f, hR: Float = 1f, pxR: Float = .5f, pyR: Float = .5f) : this( - listOf(painter), wR, hR, pxR, pyR + constructor(painter: Painter, scaleX: Float = 1f, scaleY: Float = 1f, pxR: Float = .5f, pyR: Float = .5f) : this( + listOf(painter), scaleX, scaleY, pxR, pyR ) + override fun calc(helper: VisualizerHelper) { + painters.forEach { painter -> + painter.calc(helper) + } + } + override fun draw(canvas: Canvas, helper: VisualizerHelper) { canvas.save() - canvas.scale(wR, hR, pxR * canvas.width, pyR * canvas.height) + canvas.scale(scaleX, scaleY, pxR * canvas.width, pyR * canvas.height) painters.forEach { painter -> painter.draw(canvas, helper) } diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Sequential.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Sequential.kt index 57a600d..d36abf2 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Sequential.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Sequential.kt @@ -6,6 +6,12 @@ import io.github.jeffshee.visualizer.utils.VisualizerHelper class Sequential(var painters: List) : Painter() { + override fun calc(helper: VisualizerHelper) { + painters.forEach { painter -> + painter.calc(helper) + } + } + override fun draw(canvas: Canvas, helper: VisualizerHelper) { painters.forEach { painter -> painter.draw(canvas, helper) } } diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Shake.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Shake.kt index 2d270a4..e223589 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Shake.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Shake.kt @@ -1,61 +1,57 @@ package io.github.jeffshee.visualizer.painters.modifier +import android.animation.ValueAnimator import android.graphics.Canvas import io.github.jeffshee.visualizer.painters.Painter import io.github.jeffshee.visualizer.utils.VisualizerHelper -import kotlin.math.* -import kotlin.random.Random class Shake : Painter { var painters: List - var xR: Float - var yR: Float - var shaker: Shaker - - constructor(painters: List, xR: Float = .05f, yR: Float = .05f, shaker: Shaker = Shaker()) { + // + var animX: ValueAnimator + var animY: ValueAnimator + + constructor( + painters: List, + animX: ValueAnimator = ValueAnimator.ofFloat(0f, .01f, 0f, -.01f, 0f).apply { + duration = 16000;repeatCount = ValueAnimator.INFINITE + }, + animY: ValueAnimator = ValueAnimator.ofFloat(0f, .01f, 0f, -.01f, 0f).apply { + duration = 8000;repeatCount = ValueAnimator.INFINITE + } + ) { this.painters = painters - this.xR = xR - this.yR = yR - this.shaker = shaker + this.animX = animX + this.animY = animY + animX.start() + animY.start() } - constructor(painter: Painter, xR: Float = .05f, yR: Float = .05f, shaker: Shaker = Shaker()) : this( - listOf(painter), xR, yR, shaker - ) - - override fun draw(canvas: Canvas, helper: VisualizerHelper) { - shaker.update() - drawHelper(canvas, "a", xR * shaker.x, yR * shaker.y) { - painters.forEach { painter -> - painter.draw(canvas, helper) - } + constructor( + painter: Painter, + animX: ValueAnimator = ValueAnimator.ofFloat(0f, .01f, 0f, -.01f, 0f).apply { + duration = 16000;repeatCount = ValueAnimator.INFINITE + }, + animY: ValueAnimator = ValueAnimator.ofFloat(0f, .01f, 0f, -.01f, 0f).apply { + duration = 8000;repeatCount = ValueAnimator.INFINITE } - } - - class Shaker { - var x = 0f - var y = 0f - var v = .01f - var theta = 0f + ) : this(listOf(painter), animX, animY) - private val range = toRad(60f) - private val pi = PI.toFloat() - fun update() { - if (x * x + y * y >= 1f) { - theta = toCenter() + range * Random.nextFloat() - range / 2f - } - x += v * cos(theta) - y += v * sin(theta) + override fun calc(helper: VisualizerHelper) { + painters.forEach { painter -> + painter.calc(helper) } - private fun toCenter(): Float { - return pi + atan2(y, x) - } + } - private fun toRad(deg: Float): Float { - return deg / 180f * PI.toFloat() + override fun draw(canvas: Canvas, helper: VisualizerHelper) { + canvas.save() + drawHelper(canvas, "a", animX.animatedValue as Float, animY.animatedValue as Float) { + painters.forEach { painter -> + painter.draw(canvas, helper) + } } - + canvas.restore() } } \ No newline at end of file diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Zoom.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Zoom.kt index 0f09a6a..6491c45 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Zoom.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/modifier/Zoom.kt @@ -1,48 +1,56 @@ package io.github.jeffshee.visualizer.painters.modifier +import android.animation.ValueAnimator import android.graphics.Canvas +import android.renderscript.Sampler import io.github.jeffshee.visualizer.painters.Painter import io.github.jeffshee.visualizer.utils.VisualizerHelper -import kotlin.math.* -import kotlin.random.Random class Zoom : Painter { var painters: List - var xR: Float - var yR: Float - var zoomer: Zoomer - - constructor(painters: List, xR: Float = .05f, yR: Float = .05f, zoomer: Zoomer = Zoomer()) { + // + var pxR: Float + var pyR: Float + // + var anim: ValueAnimator + + constructor( + painters: List, pxR: Float = .5f, pyR: Float = .5f, + anim: ValueAnimator = ValueAnimator.ofFloat(.9f, 1.1f).apply { + duration = 8000;repeatCount = ValueAnimator.INFINITE;repeatMode = ValueAnimator.REVERSE + } + ) { this.painters = painters - this.xR = xR - this.yR = yR - this.zoomer = zoomer + this.pxR = pxR + this.pyR = pyR + this.anim = anim + anim.start() } - constructor(painter: Painter, xR: Float = .05f, yR: Float = .05f, zoomer: Zoomer = Zoomer()) : this( - listOf(painter), xR, yR, zoomer + constructor( + painter: Painter, pxR: Float = .5f, pyR: Float = .5f, + anim: ValueAnimator = ValueAnimator.ofFloat(.9f, 1.1f).apply { + duration = 8000;repeatCount = ValueAnimator.INFINITE;repeatMode = ValueAnimator.REVERSE + } + ) : this( + listOf(painter), pxR, pyR, anim ) + override fun calc(helper: VisualizerHelper) { + painters.forEach { painter -> + painter.calc(helper) + } + } + override fun draw(canvas: Canvas, helper: VisualizerHelper) { - zoomer.update() canvas.save() - canvas.scale(1f + .1f*zoomer.x,1f + .1f*zoomer.x, canvas.width/2f, canvas.height/2f) + canvas.scale( + anim.animatedValue as Float, anim.animatedValue as Float, + pxR * canvas.width, pyR * canvas.height + ) painters.forEach { painter -> painter.draw(canvas, helper) } canvas.restore() } - - class Zoomer { - var x = 0f - var v = .01f - - fun update() { - if (abs(x) >= 1f) { - v = -v - } - x += v - } - - } } \ No newline at end of file diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/waveform/Waveform.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/waveform/Waveform.kt index 20108bf..b467b4a 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/waveform/Waveform.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/painters/waveform/Waveform.kt @@ -11,32 +11,43 @@ class Waveform( var paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG).apply { color = Color.WHITE;style = Paint.Style.STROKE;strokeWidth = 2f }, + // var startHz: Int = 0, var endHz: Int = 2000, - var sliceNum: Int = 256, - var xR: Float = 0f, - var yR: Float = .5f, - var wR: Float = 1f, + // + var num: Int = 256, + // var ampR: Float = 1f ) : Painter() { private val path = Path() + private var skipFrame = false + lateinit var waveform : ByteArray + + override fun calc(helper: VisualizerHelper) { + val fft = helper.getFftMagnitudeRange(startHz, endHz) + + if (isQuiet(fft)) { + skipFrame = true + return + } else skipFrame = false + + waveform = helper.getWave() + } @ExperimentalUnsignedTypes override fun draw(canvas: Canvas, helper: VisualizerHelper) { - val fft = helper.getFftMagnitudeRange(startHz, endHz) - if (isQuiet(fft)) return + if (skipFrame) return - val width = canvas.width.toFloat() * wR + val width = canvas.width.toFloat() - val wave = helper.getWave() - val point = wave.size / (sliceNum + 1) - val sliceWidth = width / sliceNum + val point = waveform.size / (num + 1) + val sliceWidth = width / num - path.moveTo(0f, (-wave[0].toUByte().toInt() + 128f) * ampR) - for (i in 1..sliceNum) - path.lineTo(sliceWidth * i, (-wave[point * i].toUByte().toInt() + 128f) * ampR) - drawHelper(canvas, "a", xR, yR) { canvas.drawPath(path, paint) } + path.moveTo(0f, (-waveform[0].toUByte().toInt() + 128f) * ampR) + for (i in 1..num) + path.lineTo(sliceWidth * i, (-waveform[point * i].toUByte().toInt() + 128f) * ampR) + drawHelper(canvas, "a", 0f, .5f) { canvas.drawPath(path, paint) } path.reset() } } \ No newline at end of file diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/utils/Preset.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/utils/Preset.kt index 810c732..5f622d0 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/utils/Preset.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/utils/Preset.kt @@ -1,33 +1,36 @@ package io.github.jeffshee.visualizer.utils -import android.graphics.Bitmap -import io.github.jeffshee.visualizer.painters.Painter -import io.github.jeffshee.visualizer.painters.fft.FftBar -import io.github.jeffshee.visualizer.painters.fft.FftCircle -import io.github.jeffshee.visualizer.painters.fft.FftCircleWaveRgb -import io.github.jeffshee.visualizer.painters.misc.SimpleIcon -import io.github.jeffshee.visualizer.painters.modifier.Beat -import io.github.jeffshee.visualizer.painters.modifier.Rotate +import android.graphics.* +import io.github.jeffshee.visualizer.painters.* +import io.github.jeffshee.visualizer.painters.fft.* +import io.github.jeffshee.visualizer.painters.misc.* +import io.github.jeffshee.visualizer.painters.modifier.* class Preset { - companion object{ + companion object { /** * Feel free to add your awesome preset here ;) - * Hint: You can use `Group` painter to group multiple painters together as a single painter + * Hint: You can use `Sequential` painter to group multiple painters together as a single painter */ - fun getPreset(name: String): Painter{ - return when(name){ + fun getPreset(name: String): Painter { + return when (name) { "debug" -> FftBar() else -> FftBar() } } - fun getPresetWithIcon(name: String, bitmap: Bitmap): Painter{ - return when(name){ + fun getPresetWithBitmap(name: String, bitmap: Bitmap): Painter { + return when (name) { + "cIcon" -> Sequential(listOf(Rotate(FftCircle()), SimpleIcon(SimpleIcon.getCircledBitmap(bitmap)))) + "cWaveRgbIcon" -> Sequential( + listOf( + Rotate(FftCircleWaveRgb()), + SimpleIcon(SimpleIcon.getCircledBitmap(bitmap)) + ) + ) + "liveBg" -> Scale(Shake(Background(bitmap)), 1.02f, 1.02f) "debug" -> SimpleIcon(bitmap) - "cIcon" -> Beat(listOf(Rotate(FftCircle()), SimpleIcon(SimpleIcon.getCircledBitmap(bitmap)))) - "cWaveRgbIcon" -> Beat(listOf(Rotate(FftCircleWaveRgb()), SimpleIcon(SimpleIcon.getCircledBitmap(bitmap)))) else -> SimpleIcon(bitmap) } } diff --git a/visualizer/src/main/java/io/github/jeffshee/visualizer/views/VisualizerView.kt b/visualizer/src/main/java/io/github/jeffshee/visualizer/views/VisualizerView.kt index 701d31a..b23cde9 100644 --- a/visualizer/src/main/java/io/github/jeffshee/visualizer/views/VisualizerView.kt +++ b/visualizer/src/main/java/io/github/jeffshee/visualizer/views/VisualizerView.kt @@ -56,7 +56,9 @@ class VisualizerView : View { super.onDraw(canvas) setLayerType(LAYER_TYPE_HARDWARE, paint) canvas?.apply { - painterList.forEach { it.draw(canvas, helper) } + painterList.forEach { + it.calc(helper) + it.draw(canvas, helper) } simpleText.text = "FPS: ${frameManager.fps()}" if (fps) simpleText.draw(canvas, helper) }