Created
January 16, 2012 12:58
-
-
Save wacaw/1620758 to your computer and use it in GitHub Desktop.
simple ruby sound visualization - with ruby processing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'ruby-processing' | |
# Pird | |
class Pird < Processing::App | |
load_library "minim" | |
import "ddf.minim" | |
import "ddf.minim.analysis" | |
load_library "control_panel" | |
attr_accessor :m,:x,:y,:input | |
#co się dzieje onload | |
def setup | |
@viscircles = [] | |
setup_sound | |
control_panel do |c| | |
c.slider(:fft_smoothing,0..0.99,0.8 ) | |
c.slider(:number,0..4,0) | |
# => c.menu(:options, ['03 Winter Winds.mp3', '16 The Legend of Jesse James.mp3', 'majk'], '16 The Legend of Jesse James.mp3') {|m| load_from(m) } | |
# => c.slider(:volume,1..100,50){|v| voll(m)} | |
c.checkbox :show_waveform | |
c.checkbox :show_frequency | |
c.checkbox :show_clicked | |
c.checkbox :onplace | |
c.button :pause_vis | |
c.button :clear_clicked | |
end | |
smooth # smoother == prettier | |
size(800,600) # let's pick a more interesting size | |
background 0.50 | |
@loo=true | |
end | |
def clear_clicked | |
@viscircles.each do |vc| | |
vc = vc.stop() | |
end | |
@viscircles=[] | |
end | |
def mouse_pressed | |
return if mouse_x == 0 || mouse_y == 0 | |
return if viscircle_grab | |
@viscircles << VisCircle.new(mouse_x,mouse_y) | |
end | |
def mouse_released | |
@grabbed = nil | |
end | |
def viscircle_grab | |
return if @onplace | |
@grabbed = @viscircles.detect {|p| dist(mouse_x, mouse_y, p.x0, p.y0) < 100 } | |
unless @grabbed.nil? | |
#if @grabbed.size =1 | |
@grabbed.changestate | |
#else | |
# @grabbed.each {|vc| vc.changestate} unless @grabbed.nil? | |
#end | |
end | |
end | |
def pause_vis | |
@loo= (@loo==true) ? false : true | |
#@input.close() | |
#load_from | |
#@input.play() | |
#@loo=true | |
end | |
def load_from(m=nil) | |
@input.close() unless @input.nil? | |
case m | |
when "majk" | |
@input = @minim.get_line_in | |
@fft = FFT.new(@input.left.size, 44100) | |
else | |
@input = @minim.loadFile(m) | |
@input.play(); | |
@fft = FFT.new(@input.bufferSize(), @input.sampleRate()); | |
end | |
end | |
def draw | |
if @loo | |
update_sound | |
animate_sound | |
draw_waveform if @show_waveform | |
draw_frequency if @show_frequency | |
end | |
#t = Time.now | |
#if @frame_time | |
# fps = 1.0 / (t - @frame_time) | |
# printf "%0.1ffps\n", fps | |
#end | |
#@frame_time = t | |
end | |
def draw_waveform | |
if @number < 1 | |
@red1 = @scaled_ffts[2]*255 | |
@green1 = @scaled_ffts[3]*255 | |
@blue1 = @scaled_ffts[4]*255 | |
fill @red1, @green1, @blue1 | |
end | |
scale = height / 4 | |
(@input.buffer_size - 1).times do |i| | |
line(i, scale + @input.left.get(i)*scale, | |
i+1, scale + @input.left.get(i+1) * scale) | |
end | |
end | |
def draw_frequency | |
if @number < 1 | |
@red1 = @scaled_ffts[2]*255 | |
@green1 = @scaled_ffts[3]*255 | |
@blue1 = @scaled_ffts[4]*255 | |
fill @red1, @green1, @blue1 | |
end | |
num=20 | |
@fft.forward @input.left | |
scale = width / num | |
num.times do |i| | |
@fft.scale_band i, i * 0.35 + 1 | |
@fft.scale_band i, 0.3 | |
line i*scale, height, i*scale+5, height - @fft.get_band(i)*4 | |
end | |
end | |
def setup_sound | |
@number=1 | |
@onplace=false | |
@radius = 0 | |
# Creates a Minim object | |
@minim = Minim.new(self) | |
#mikrofon | |
#@input = @minim.get_line_in | |
#@fft = FFT.new(@input.left.size, 44100) | |
#plik | |
#@input = @minim.loadFile("03 Winter Winds.mp3") | |
#load_from("03 Winter Winds.mp3") | |
load_from("majk") | |
#@input = @minim.loadFile("16 The Legend of Jesse James.mp3") | |
#@input.play(); | |
#@fft = FFT.new(@input.bufferSize(), @input.sampleRate()); | |
#FFT | |
#@fft = FFT.new(@input.left.size, 44100) | |
#@fft = FFT.new(@input.bufferSize(), @input.sampleRate()); | |
# Our beat detector object | |
@beat = BeatDetect.new | |
# Tablica częstotliwości które chcemy zbadać | |
# -- skopiowane z VLC | |
@freqs = [60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000] | |
# Create arrays to store the current FFT values, | |
# previous FFT values, highest FFT values we've seen, | |
# and scaled/normalized FFT values (which are easier to work with) | |
@current_ffts = Array.new(@freqs.size, 0.001) | |
@previous_ffts = Array.new(@freqs.size, 0.001) | |
@max_ffts = Array.new(@freqs.size, 0.001) | |
@scaled_ffts = Array.new(@freqs.size, 0.001) | |
# We'll use this value to adjust the "smoothness" factor | |
# of our sound responsiveness | |
@fft_smoothing = 0.8 | |
end | |
def update_sound | |
@fft.forward(@input.left) | |
@previous_ffts = @current_ffts | |
# Itaracja po wszystkich zdefiniowanych czestotliwoscicach by znalesc ich wartosci FFT | |
@freqs.each_with_index do |freq, i| | |
# Nowa wartosc FFT dla tej czestotliwosci | |
new_fft = @fft.get_freq(freq) | |
# maksymalna czestotliwosc | |
@max_ffts[i] = new_fft if new_fft > @max_ffts[i] | |
# Połącznie poprzedniej i aktualnej próbki, | |
@current_ffts[i] = ((1 - @fft_smoothing) * new_fft) + (@fft_smoothing * @previous_ffts[i]) | |
# Skalowanie wartości FFT by ogarnąć pracę z częstotliwością | |
@scaled_ffts[i] = (@current_ffts[i]/@max_ffts[i]) | |
end | |
# Check if there's a beat, will be stored in @beat.is_onset | |
@beat.detect(@input.left) | |
end | |
def animate_sound | |
if @number > 0 | |
@size = @scaled_ffts[1]*height | |
@size *= 3 if @beat.is_onset | |
@x1 = @scaled_ffts[0]*width + width/2 | |
@y1 = @scaled_ffts[2]*height + height/2 | |
@red1 = @scaled_ffts[2]*255 | |
@green1 = @scaled_ffts[3]*255 | |
@blue1 = @scaled_ffts[4]*255 | |
fill @red1, @green1, @blue1 | |
stroke @red1+20, @green1+20, @blue1+20 | |
ellipse(@x1, @y1, @size, @size) | |
end | |
if @number > 1 | |
@size = @scaled_ffts[2]*height | |
@size *= 3 if @beat.is_onset | |
@x2 = width/2 + @scaled_ffts[4]*width | |
@y2 = height/2 + @scaled_ffts[6]*height | |
@red2 = @scaled_ffts[7]*255 | |
@green2 = @scaled_ffts[8]*255 | |
@blue2 = @scaled_ffts[9]*255 | |
fill @red2, @green2, @blue2 | |
stroke @red2+20, @green2+20, @blue2+20 | |
ellipse(@x2, @y2, @size, @size) | |
end | |
if @number > 2 | |
@size = @scaled_ffts[3]*height | |
@size *= 3 if @beat.is_onset | |
@x2 = width/2 - @scaled_ffts[7]*width | |
@y2 = height/2 - @scaled_ffts[9]*height | |
@red2 = @scaled_ffts[9]*255 | |
@green2 = @scaled_ffts[0]*255 | |
@blue2 = @scaled_ffts[1]*255 | |
fill @red2, @green2, @blue2 | |
stroke @red2+20, @green2+20, @blue2+20 | |
ellipse(@x2, @y2, @size, @size) | |
end | |
if @number > 3 | |
@size = @scaled_ffts[4]*height | |
@size *= 3 if @beat.is_onset | |
@x4 = @x ||=@scaled_ffts[2]*width | |
@y4 = @y ||=@scaled_ffts[8]*height | |
@red2 = @scaled_ffts[4]*255 | |
@green2 = @scaled_ffts[5]*255 | |
@blue2 = @scaled_ffts[9]*255 | |
fill @red2, @green2, @blue2 | |
stroke @red2+20, @green2+20, @blue2+20 | |
ellipse(@x4, @y4, @size, @size) | |
end | |
if @show_clicked | |
@viscircles.each do |vc| | |
vc.draw(@scaled_ffts,@beat) | |
end | |
end | |
end | |
def stop | |
@input.close() | |
end | |
class VisCircle | |
attr_reader :x0, :y0, :a1, :a1, :a3, :a4, :a5, :a6,:free | |
def initialize(x, y) | |
#r = Random.new | |
@x0, @y0 = x, y | |
@a1,@a2,@a3,@a4,@a5,@a6 = rand(9),rand(9),rand(9),rand(9),rand(9),rand(9) | |
@free = false | |
end | |
def changestate | |
@free= (@free==true) ? false :true | |
end | |
def stop | |
@stop=true | |
end | |
def draw(scaled_ffts,beat) | |
unless @stop | |
@size = scaled_ffts[@a1]*height/2 | |
@size *= 3 if beat.is_onset | |
@red = scaled_ffts[@a4]*255 | |
@green = scaled_ffts[@a5]*255 | |
@blue = scaled_ffts[@a6]*255 | |
fill @red, @green, @blue | |
stroke @red+20, @green+20, @blue+20 | |
if @free | |
#@x0=(scaled_ffts[@a3]*width + @x0/2)%width | |
#@y0=(scaled_ffts[@a2]*height + @y0/2)%height | |
@x0=(scaled_ffts[@a3]*@x0 + width/2)%width | |
@y0=(scaled_ffts[@a2]*@y0 + height/2)%height | |
end | |
ellipse(@x0, @y0, @size, @size) | |
end | |
end | |
end | |
end | |
Pird.new :title => "Pird" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment