Skip to content

Commit

Permalink
Optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffshee committed Jun 15, 2019
1 parent 3e282ed commit dc6799a
Show file tree
Hide file tree
Showing 23 changed files with 531 additions and 369 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,35 @@ 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.*

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
Expand All @@ -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 }
)
)
}
Expand Down
Binary file removed app/src/main/res/drawable-xxhdpi/background.png
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ 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 {

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.
*
Expand All @@ -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<GravityModel>, sliceNum: Int, interpolator: String
Expand Down Expand Up @@ -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<GravityModel>, sliceNum: Int, interpolator: String
Expand Down Expand Up @@ -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()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
Loading

0 comments on commit dc6799a

Please sign in to comment.