aniwave 2d - April 25

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
dafhi
Posts: 1641
Joined: Jun 04, 2005 9:51

aniwave 2d - April 25

Post by dafhi »

Code: Select all

'#include "aniwave_2d.bas"

/' -- aniwave_2d -- 2023 April 25 - by dafhi

  2d animated wave generator

    important functions showcased in demo subs
  randomize_layers
  show_all
  
    update:
  wave_group
  param-less layer constructor

'/

#define flo(x)      (((x)*2.0-0.5)shr 1) '' replaces int (and faster) - http://www.freebasic.net/forum/viewtopic.php?p=118633

#undef int

#define int         as integer
#define sng         as single
#define dbl         as double

#define min( a, b)  iif( (a)<(b), (a), (b) )
#define max( a, b)  iif( (a)>(b), (a), (b) )

function clamp( in sng, hi sng = 1, lo sng = 0) sng
  return min( max(in, lo), hi ) '' Mar 8
End Function

const               tau = 8 * atn(1)
'
' ------------ boilerplate


function tr_wave( i sng ) sng
  return abs(i - flo(i) - .5) - .25 '' by Stonemonkey
End function

function sw_wave( i sng ) sng
  return i - flo(i) - .5
End function

  
  namespace aniwave_2d '' 2023 April 23 - by dafhi

dim sng       dt

sub grab_delta_time( _dt sng )
  dt = _dt
end sub


type _osc_endpoint
  declare sub     calc
  sng             rad = .15 + rnd * 1.33
  sng             ia = .5 * (.3 + rnd)
  dbl             a = rnd *  tau
  sng             x
  sng             _result
End Type

sub _osc_endpoint.calc
  _result = rad * sin(a) + x
end sub


type _anim_frame_vars
  declare constructor
  declare sub       advance
  as _osc_endpoint e0, e1
end type

constructor _anim_frame_vars
  const c_b = 1.5, c_a = .3
  e0.x = -c_b * ( c_a + rnd )
  e1.x =  c_b * ( c_a + rnd )
  if rnd < .5 then swap e0, e1
end constructor

sub _anim_frame_vars.advance
  e0.a += e0.ia * dt
  e1.a += e1.ia * dt
end sub

type _clip_vars
  sng     y_offs = 1.2 * (rnd - .5) '' > 1.3 = frequent high offset
  const   clip_a = .05, clip_b = 2.5
  sng     hi =  clip_a + rnd * clip_b
  sng     lo = -clip_a - rnd * clip_b
  declare constructor
end type

constructor _clip_vars
  hi += y_offs
  lo += y_offs
end constructor


type _layer_base
  declare sub           frame_precalcs( () sng )
  as _anim_frame_vars   anim
  as _clip_vars         clip
  sng                   amp
  sng                   _slen
  sng                   x_zoom
  sng                   x, dx
end type

sub _layer_base.frame_precalcs( out() sng )
  anim.e0.calc
  anim.e1.calc
  _slen = anim.e1._result - anim.e0._result
  dx = _slen / ( ( ubound(out) + 0) * x_zoom)
end sub


const triangle = 0
const sawtooth = 1

type layer extends _layer_base
  
  declare constructor
  declare constructor(x_zoom sng = 1, tri_to_saw_ratio sng = .75 )
  
  declare sub           addto( () sng )
  declare sub           rand( x_zoom sng = 1, tri_to_saw_ratio sng = .75 )
  
  declare sub           _set_function_type( int )
  as function(sng) sng  f
end type

constructor layer
  rand
end constructor

constructor layer( xzoom sng, tri_to_saw_ratio sng )
  rand xzoom, tri_to_saw_ratio
end constructor

sub layer.rand( xzoom sng, tri_to_saw_ratio sng )
  
  '' cast(myRand, this) = myRand() - gracias fxm
  cast( _layer_base, this).constructor()
  
  x_zoom = xzoom
  _set_function_type rnd > tri_to_saw_ratio
end sub

sub layer._set_function_type( j int )
  if j then
    f = @sw_wave '' muchas gracias fxm
    amp = 3 * (.15 + rnd)
  else
    f = @tr_wave
    amp = 8 * (.15 + rnd)
  endif
end sub

sub layer.addto( out() sng )

  frame_precalcs out()
  x = ( anim.e0._result ) / x_zoom
  
  for j int = 0 to ubound( out )
    var f = f(x) * amp + clip.y_offs
    out(j) += clamp( f, clip.hi, clip.lo )
    x += dx
  next
  
  anim.advance
  
end sub


type wave_group
  declare           constructor( c int = -1, xzoom sng = 0, tri sng = -1)
  declare sub       init( c int = -1, xzoom sng = 0, tri sng = -1 )
  
  declare property  val( sng ) sng
  declare sub       calc( w int = 50 )

  as layer          L(any)
  dim sng           result(any)
  
  dim sng         _tri = .5
  dim sng         _xzoom = .5
  dim int         _c = 3
end type

constructor wave_group( c int, xzoom sng, tri_to_saw_ratio sng )
  init c, xzoom, tri_to_saw_ratio
end constructor

sub wave_group.init( c int, xzoom sng, tri_to_saw_ratio sng )
  if c < 1 then c = _c
  redim L(c-1)
  
  if xzoom = 0 then xzoom = _xzoom
  if tri_to_saw_ratio = -1 then tri_to_saw_ratio = _tri
  
  for i int = 0 to c-1
    L(i).rand xzoom, tri_to_saw_ratio
  next
  
  _tri = tri_to_saw_ratio
  _xzoom = xzoom
  _c = max(c, 1)
end sub

property wave_group.val( x sng ) sng
  static sng sum:  sum = 0 '' i think static stays 1 instance
  
      for i int = 0 to ubound(L)
    with L(i)
  var x0 = .anim.e0.rad * sin(.anim.e0.a)
  var x1 = .anim.e1.rad * sin(.anim.e1.a)
  sum += (x1 - x0) / .x_zoom
  end with
  next
  
  return sum * x
end property

sub wave_group.calc( w int )
  var additive_downscale = 1 / ( ubound(L)+1 ) ^ .7
  redim result(w-1)
  for i int = 0 to ubound( L )
    L(i).addto result()
  next
  for i int = 0 to ubound( result )
    result(i) *= additive_downscale
  next
end sub

end namespace ' -- aniwave_2d


' -- demo support
'
sub demo_rect( ary_out() sng, _
  x int = 1, _
  y int = 1, _
  w int = 150, h int = 50, _
  col as ulong = rgb(99,99,99) )
  
  var hh = y + h / 2
  for i int = x to x + w-1
    var y = h * clamp( ary_out(i-x), .5, -.5 )
    pset ( i, hh - y ), col
  next
  
end sub


' -- meat and potatoes demo
'
sub show_all( wg as aniwave_2d.wave_group, rcw int, rch int )
  
  dim sng sum( rcw - 1 )
  var sum_yscale = 1 / (ubound(wg.L)+1) ^ .7
  var y = 15
  var x = 20
  
  for i int = 0 to ubound( wg.L )
    dim sng result( rcw - 1 )
    wg.L(i).addto result() '' meat-and-potatoes
    
    demo_rect result(), x, y, rcw, rch
    for i int = 0 to ubound( sum )
      sum(i) += result(i) * sum_yscale
    next
    y += rch + 3
  next
  y += rch * 1.5
  demo_rect sum(), x, y, rcw, rch, rgb(255,255,255)
  
end sub

sub randomize_layers( wg as aniwave_2d.wave_group )
  var tri_to_saw_ratio = .5
  for i int = 0 to ubound( wg.L )
    var x_zoom = .5 * (.2 + rnd)
    wg.L(i).rand x_zoom, tri_to_saw_ratio '' meat-and-potatoes
  next
end sub


' ---------------- Main
'
var wid = 800
var hgt = 600

screenres wid,hgt,32

var       seconds_max = 290

var       time_between_new = 3.5

var       rcw = 600
var       rch = 30

  randomize


var cLayers           = 2
var xzoom             = 6
var tri_to_saw_ratio  = .5

  dim as aniwave_2d.wave_group _
wg = type( cLayers, xzoom, tri_to_saw_ratio )


var       curr_run_time = 0f

var       tp = timer
var       report_next = tp + 2.5
var       new_waves_trig = tp

while curr_run_time < seconds_max
    
    screenlock
  cls
  
  var t = timer
  dim sng dt = t - tp
  tp = t
  curr_run_time += dt
  
  if t > new_waves_trig then
    randomize_layers wg
    new_waves_trig += time_between_new
  endif
  
  aniwave_2d.grab_delta_time dt
  
  show_all wg, rcw, rch
    
  static sng  dt2, dt_sum
  if t > report_next then
    dt_sum = dt + dt2
    var m = str(report_next)
    windowtitle "FPS: " + str( 2 / dt_sum ) '' deltatime avg
    report_next += 1
  elseif curr_run_time < 1.75 then
    locate 2,2
    ? "demo runs"; seconds_max; " seconds"
  endif
  screenunlock
  
  dt2 = dt
  
  var k = inkey
  select case lcase(k)
  case ""
  case "a" to "z", " "
    new_waves_trig = t
  case else
   end
  end select
  
  sleep 1

wend
Last edited by dafhi on May 21, 2023 5:31, edited 1 time in total.
neil
Posts: 590
Joined: Mar 17, 2022 23:26

Re: aniwave 2d - April 25

Post by neil »

At first I didn't get it aniwave 2d.
Now I do. Nice one dafhi.
Last edited by neil on May 20, 2023 7:40, edited 1 time in total.
neil
Posts: 590
Joined: Mar 17, 2022 23:26

Re: aniwave 2d - April 25

Post by neil »

Here's an online oscilloscope. You need a microphone for your PC for it to work.
https://academo.org/demos/virtual-oscilloscope/.

I tested this wlth a 1 Khz sine wave test tone from my phone. And it was not a clean sine wave.
Probably because the PC microphone picked up background noise along with the test tone.
dafhi
Posts: 1641
Joined: Jun 04, 2005 9:51

Re: aniwave 2d - April 25

Post by dafhi »

that's impressive! browser technology is nuts these days
neil
Posts: 590
Joined: Mar 17, 2022 23:26

Re: aniwave 2d - April 25

Post by neil »

That's only a 1 channel oscilloscope.
Your aniwave 2d is simulating a 3 channel oscilloscope.
Change the color to green and you have a nice 3 channel oscilloscope simulator.
Maybe you could add another wave form and make it a 4 channel.
dafhi
Posts: 1641
Joined: Jun 04, 2005 9:51

Re: aniwave 2d - April 25

Post by dafhi »

classic case on my part of poor code purpose info
this is a wave generator
neil
Posts: 590
Joined: Mar 17, 2022 23:26

Re: aniwave 2d - April 25

Post by neil »

dafhi Here's my first attempt for generating a sine wave. It's not animated like yours.

Code: Select all

Screen 12
Cls
Dim As single p,x,y,x2,y2
x2 =0
y2 = 80
p = 20

for x = 1 to 640
sleep 2
y = 100 + 60 * sin(x / p)
line(x,y)-(x2, y2),2
x2 = x
y2 = y
next
sleep
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: aniwave 2d - April 25

Post by fxm »

The last position of the graphic cursor is stored internally (as for the text cursor), so your above code can be simplified as follows:

Code: Select all

Dim As Integer p, x, y
p = 20

Screen 12
Cls
Pset(0, 100), 10
For x = 1 to 639
    y = 100 + 60 * sin(x / p)
    Line -(x, y), 10
    Sleep 2
Next

Sleep
neil
Posts: 590
Joined: Mar 17, 2022 23:26

Re: aniwave 2d - April 25

Post by neil »

Thanks fxm.
Here's a mod.
I made another change this looks nicer.
I changed p = 20 to p = 40.

Code: Select all

Dim As Integer j, p, x, y
p = 40

Screen 12
Cls
for j = 1 to 20
Pset(0, 100), 10
For x = 1 to 639
    y = 100 + 60 * sin(x / p)
    Line -(x, y), 10
    Sleep 1
Next
p += 1
Next
Sleep
More changes a larger sine wave.

Code: Select all

Dim As Integer j, p, x, y
p = 60

Screen 12
Cls
for j = 1 to 20
Pset(0, 240), 10
For x = 1 to 639
    y = 240 + 160 * sin(x / p)
    Line -(x, y), 10
    Sleep 1
Next
p += 1
Next
Sleep
Last edited by neil on May 23, 2023 1:46, edited 1 time in total.
neil
Posts: 590
Joined: Mar 17, 2022 23:26

Re: aniwave 2d - April 25

Post by neil »

With the above examples you can get different effects with a sine wave with minimal code.
Post Reply