Skip to content

Instantly share code, notes, and snippets.

@olexpono
Created August 15, 2012 03:55
Show Gist options
  • Save olexpono/3355702 to your computer and use it in GitHub Desktop.
Save olexpono/3355702 to your computer and use it in GitHub Desktop.
little bitty LFO class for ruby-processing
# LFO for ruby-processing
# Calculates a triangle or sine function for a given frame.
# triangle wave min/rising/max/down ./`\ from [0..1]
# sine wave sine is 0/1/0/-1/0
# The current location of the wave can skip if you change
# the tempo on the fly, each LFO location is not simulated.
#
# Usage:
# create new lfo with a some tempo in frames:
# @lfo_engine = BasicLFO.new(100)
#
# call every frame to run, don't call and the lfo will be paused:
# @lfo_engine.ping frame_count
#
# now the fun stuff:
#
# rect 0, 0, width * @lfo_engine.lfo(:sine), width * @lfo_engine.lfo(:triangle)
#
# 10.times do |i|
# sector_x = i * (width/10)
# sector_x2= (i+1) * (width/10)
# sec_height = height/2 + height/2 * @lfo_engine.lfo(:sine , 0.1 * i)
# rect sec_x, 0, (width/10), sec_height
# end
#
class BasicLFO
def initialize(tempo=120, frame_count=0)
# TODO - lfo half-rate needs to actually be tempo
@tempo = tempo.to_f
@frame_reset_count = frame_count
@count_this_frame = frame_count
end
# Resets logical frame count
def reset!(frame_count)
@frame_reset_count = frame_count
@count_this_frame = frame_count
end
# Pings and updates logical frame count
# i.e. call it at start of draw.
def ping(frame_count)
@count_this_frame = frame_count - @frame_reset_count
@rising = {} if @rising.nil?
@rising.clear
end
# number of frames for the animation / 2
# this tempo is the time in frames for one rise or fall
# (full cycle = 2x tempo frames)
def tempo=(new_tempo)
@tempo = new_tempo.to_f
end
# phase [0.0..2.0] - rotates value 360 degrees through the function
# Returns value between 0.0 and 1.0 for :triangle
# Returns value between -1.0 and 1.0 for :sine (yeah I'm lazy)
#
# This is ripe for optimization around [current_frame & wave & phase]
def lfo(wavetype = :triangle, phase = 0.0)
triangle = (((@count_this_frame % @tempo) + (phase * @tempo)) % @tempo ) / @tempo
triangle = 1.0 - triangle unless rising?(phase)
return triangle if wavetype == :triangle
sine = Processing::App::sin(triangle * Math::PI)
sine = -sine unless rising?(phase)
return sine if wavetype == :sine
0.5
end
# hmm...
def lfov2(wavetype = :triangle, phase = 0.0)
end
# Internal - calculates whether rising or not
# Returns true from frames [0..tempo], false for frames [tempo..2*tempo]
#
# this _definitely_ could be cached
def rising?(phase)
(((@count_this_frame + phase * @tempo) / @tempo).to_i % 2 ) == 1
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment