65 lines
1.9 KiB
Kotlin
65 lines
1.9 KiB
Kotlin
package org.openrndr.extra.timeoperators
|
|
|
|
import org.openrndr.extra.parameters.Description
|
|
import org.openrndr.extra.parameters.OptionParameter
|
|
import org.openrndr.math.clamp
|
|
import org.openrndr.math.mod
|
|
import kotlin.math.*
|
|
|
|
internal const val TAU = 2.0 * PI
|
|
|
|
enum class LFOWave {
|
|
Saw, Sine, Square, Triangle
|
|
}
|
|
|
|
@Suppress("UNUSED")
|
|
@Description("LFO")
|
|
class LFO(wave: LFOWave = LFOWave.Saw) : TimeTools {
|
|
@OptionParameter("Wave")
|
|
var wave = wave
|
|
|
|
private var current = 0.0
|
|
set(value) {
|
|
field = clamp(value, 0.0, 1.0)
|
|
}
|
|
|
|
private var initialTime = Double.NEGATIVE_INFINITY
|
|
private var dt = 0.0
|
|
private var time = 0.0
|
|
|
|
override fun tick(seconds: Double, deltaTime: Double, frameCount: Int) {
|
|
time += deltaTime
|
|
}
|
|
|
|
fun sample(frequency: Double = 1.0, phase: Double = 0.0): Double {
|
|
return when(wave) {
|
|
LFOWave.Saw -> saw(frequency, phase)
|
|
LFOWave.Sine -> sine(frequency, phase)
|
|
LFOWave.Square -> square(frequency, phase)
|
|
LFOWave.Triangle -> triangle(frequency, phase)
|
|
}
|
|
}
|
|
|
|
fun saw(frequency: Double = 1.0, phase: Double = 0.0): Double {
|
|
val cycleFreq = 1.0 / frequency
|
|
val cycleTime = mod(time + (phase * frequency), cycleFreq)
|
|
current = (cycleTime) / cycleFreq
|
|
return current
|
|
}
|
|
|
|
fun sine(frequency: Double = 1.0, phase: Double = 0.0): Double {
|
|
current = sin((phase * TAU) + time * frequency * TAU) * 0.5 + 0.5
|
|
return current
|
|
}
|
|
|
|
fun square(frequency: Double = 1.0, phase: Double = 0.0): Double {
|
|
current = max(sign(sin((phase * TAU) + time * frequency * TAU)), 0.0)
|
|
return current
|
|
}
|
|
|
|
fun triangle(frequency: Double = 1.0, phase: Double = 0.0): Double {
|
|
val t = (time * frequency) + (phase * frequency)
|
|
current = 1.0 - 2.0 * abs(mod(t, 1.0) - 0.5)
|
|
return current
|
|
}
|
|
} |