You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

291 lines
6.3 KiB

// pixilang-based music visualizer
// by acheney (with help from nightradio, silent broadcast, and others)
// under mit license
include "demo.pixi"
// - CONFIG BEGIN -
// -- DEMO LIB CONFIG --
// use opengl (could improve performance and make everything look smoother) (0 = false, 1 = true)
demo_opengl = 1
// demo width in pixels
demo_xsize = 1920
// demo height in pixels
demo_ysize = 1080
// demo video export filename, comment it out if you don't want to export
//demo_video_export = "video.mkv"
// demo video export fps (frames per second)
demo_video_export_fps = 60
// demo video export quality (0 - 100)
demo_video_export_q = 100
// -- FFT/VISUALIZER CONFIG --
// fft size (must be a power of 2)
fft_size = 2048
// visualizer minimum midi pitch
vis_min_pitch = 21
// visualizer maximum midi pitch
vis_max_pitch = 135
// visualizer floor in decibels (everything below this is cut out)
vis_floor = 80
// visualizer smoothing factor
vis_smooth = 3
// visualizer horizontal scale
vis_scale = 8
// visualizer enter time delay in ms
vis_delay = 2000
// visualizer enter time in ms
vis_time = 1000
// -- EXIT TIME CONFIG --
// time for everything to fade out in ms (this divided by 3 is the amount of time for each element to fade out)
all_exit = 3000
// -- LOGO CONFIG --
// logo size scale
logo_scale = 0.25
// logo enter time delay in ms
logo_delay = 1000
// logo enter time in ms
logo_time = 1000
// -- ARTIST CONFIG --
// artist size scale
artist_scale = 0.25
// artist enter time in ms
artist_time = 1000
// artist exit time in ms
artist_exit = 1000
// -- COVER CONFIG --
// cover gaussian blur radius
cover_blur_rad = 20
// cover brightness scale
cover_brightness = 0.5
// - END CONFIG -
demo_load_wav( "media/song.wav" )
cover = load( "media/cover.png" )
logo = load("media/logo.png")
artist = load("media/artist.png")
demo_length = 0
fft_im = new( fft_size, 1, FLOAT )
fft_re = new( fft_size, 1, FLOAT )
fft_im2 = new( fft_size, 1, FLOAT )
fft_re2 = new( fft_size, 1, FLOAT )
fft_db = new( fft_size, 1, FLOAT )
cover_xsize = get_xsize(cover)
cover_ysize = get_ysize(cover)
cover_size = cover_xsize * cover_ysize
cover_src = clone(cover)
logo_xsize = get_xsize(logo)
logo_ysize = get_ysize(logo)
artist_xsize = get_xsize(artist)
artist_ysize = get_ysize(artist)
demo_init()
custom_init()
demo_add_scene( 0, 0, 0, view )
demo_add_scene( 0, 0, demo_length, DEMO_STOP )
demo_play()
demo_deinit()
fn view( $t1, $t2, $len )
{
clear( #000000 )
cover_render($t1)
vis_render($t1)
artist_render($t1)
logo_render($t1)
transp(255)
}
fn vis_render($t1)
{
rel_time = max($t1, vis_delay) - vis_delay
exit_point = demo_length - ((2 * all_exit) / 3)
rel_time_end = max($t1, exit_point) - exit_point
speed_enter = 255 / vis_time
speed_exit = 255 / (all_exit / 3)
trans = min(255 - (rel_time_end * speed_exit), min(rel_time * speed_enter, 255))
transp(trans)
t_scale(vis_scale, 1, 1)
width = (vis_max_pitch - vis_min_pitch)
t_translate(-(width / 2), ((demo_ysize / 3) - vis_floor) , 0)
i = 0 while i < fft_size {
v = demo_sound_pcm_stream[ (demo_sound_pcm_stream_ptr + i) * demo_sound_channels ] / 256
win = sin( M_PI * i / fft_size )
fft_re[i] = v * win
fft_im[i] = 0
i = i + 1
}
fft(0, fft_im, fft_re)
i = 0 while i < (fft_size / 2) {
v = fft_re[ i ] * fft_re[ i ] + fft_im[ i ] * fft_im[ i ]
v = sqrt( v )
v = 20 * log10( v )
old_v = fft_db[ i ]
fft_db[ i ] = old_v + (v - old_v) * (1 / vis_smooth)
i = i + 1
}
bin_width = demo_sound_rate / fft_size
p = vis_min_pitch
while p < vis_max_pitch {
f = pow( 2, p / 12) * 8.175799
bin = f / bin_width
idx = floor( bin )
frac = bin - idx
dB = ( 1 - frac ) * fft_db[ idx ] + frac * fft_db[ idx +1 ]
if (dB >= -vis_floor) {
line( (p - vis_min_pitch), vis_floor, (p - vis_min_pitch), -dB, WHITE)
}
p = p + (1 / vis_scale)
}
t_reset()
}
fn cover_render($t1) {
exit_point = demo_length - all_exit
rel_time = max($t1, exit_point) - exit_point
speed = 255 / (all_exit / 3)
trans = min(255 - (rel_time * speed), 255)
transp(trans)
base = 255 * cover_brightness
flash = base * (abs(demo_sound_pcm_stream[demo_sound_pcm_stream_ptr * demo_sound_channels]) + 1)
pixi(cover, 0, 0, get_color(flash, flash, flash), ((demo_xsize / cover_xsize)), ((demo_xsize / cover_xsize)))
}
fn logo_render($t1) {
exit_point = demo_length - (all_exit / 3)
rel_time = max($t1, exit_point) - exit_point
speed = 255 / (all_exit / 3)
trans = min(255 - (rel_time * speed), 255)
transp(trans)
rel_time = max($t1, logo_delay) - logo_delay
speed = demo_ysize / logo_time
perc = min(((rel_time * speed) / demo_ysize), 1)
perc_curved = (atan(((2 * perc) - 1)*10)/(M_PI/2)/2 + 0.5) + 0.032765
pixi(logo, 0, ((1 - perc_curved) * demo_ysize), WHITE, logo_scale, logo_scale)
}
fn artist_render($t1) {
transp(255)
rel_time = max($t1, artist_time) - artist_time
speed = demo_ysize / artist_exit
perc = min(((rel_time * speed) / demo_ysize), 1)
perc_curved = (atan(((2 * perc) - 1)*10)/(M_PI/2)/2 + 0.5) - 0.032765
pixi(artist, 0, perc_curved * -demo_ysize, WHITE, logo_scale, logo_scale)
}
fn custom_init()
{
//gaussian blur
sigma = max((cover_blur_rad / 2), 1)
kernel_width = (2 * cover_blur_rad) + 1
kernel = new(kernel_width, kernel_width, FLOAT)
sum = 0
for (x = -cover_blur_rad ; x <= cover_blur_rad ; x + 1) {
for (y = -cover_blur_rad ; y <= cover_blur_rad ; y + 1) {
exp_num = -(x * x + y * y)
exp_dem = 2 * sigma * sigma
expression = pow(M_E, exp_num / exp_dem)
ker_val = (expression / (2 * M_PI * sigma * sigma))
kernel[(x + cover_blur_rad), (y + cover_blur_rad)] = ker_val
sum = sum + ker_val
}
}
FIXED_POINT_MUL = 32768
for (x = 0 ; x < kernel_width ; x + 1) {
for (y = 0 ; y < kernel_width ; y + 1) {
kernel[x, y] = kernel[x, y] / sum * FIXED_POINT_MUL
}
}
convert_type( kernel, INT )
conv_filter( cover, cover_src, kernel, FIXED_POINT_MUL, 0, CONV_FILTER_COLOR )
demo_length = (demo_sound_len / demo_sound_rate) * 1000
}
fn max($a, $b) {
if ($a >= $b) {
ret($a)
} else {
ret($b)
}
}
fn min($a, $b) {
if ($a < $b) {
ret($a)
} else {
ret($b)
}
}
show_memory_debug_messages( 1 )