Skip to content

Instantly share code, notes, and snippets.

@nagachika
Created October 28, 2009 15:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nagachika/220547 to your computer and use it in GitHub Desktop.
Save nagachika/220547 to your computer and use it in GitHub Desktop.
spectrum analyzer using resonance
require "wavefile"
class Oscilator
def initialize(opt={})
@freq = opt[:freq] || 440.0
@sample_rate = opt[:sample_rate] || 44100
@delta_time = 1.0 / @sample_rate
# k/M (k = strength of spring, M = mass of object) => @k
@k = (2.0*Math::PI*@freq)**2
@m = opt[:mass] || 1.0
@k *= @m
# fliction. F = -mu*dx
@mu = opt[:mu] || 100
@mu *= @m # for convinience
@x = 0
@dx = 0
end
def step(pivot)
@pivot = pivot
ddx = (- @mu * @dx - @k * (@x - @pivot)) / @m
dx_new = @dx + ddx * @delta_time
x_new = @x + dx_new * @delta_time
@dx = dx_new
@x = x_new
end
attr_reader :x, :dx
def amplitude
@x
end
def velocity
@dx
end
def potential
(@k * ((@x - @pivot) ** 2) + @dx ** 2 / @m) / 2.0
end
def normalized_potential
potential / (0.5 * @k)
end
end
wav = WaveFile.open(ARGV[0])
data = wav.normalized_sample_data
if data[0].is_a?(Array)
data = data.map {|pair| pair[0] }
end
osc_ary = [ 32, 64, 125, 250, 500, 1000, 2000, 4000, 8000 ].map do |freq|
Oscilator.new(:freq => freq, :mu => 50)
end
data.each do |val|
osc_ary.each do |osc|
osc.step(val)
end
ary = osc_ary.map do |osc|
"%.10f" % osc.normalized_potential
end
ary.unshift val
puts ary.join(", ")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment