organic 3D oscillator demo

Pixilang programming language
Post Reply
ainegil
Posts: 168
Joined: Thu Sep 22, 2022 11:37 pm

organic 3D oscillator demo

Post by ainegil »

proof of concept for a 3d oscillator
its similar to FM/ AM, but requires less parameters.

Sounds much like a n acoustic piano ( if it does not, and sounds like a buzz you need to restart..)
especially surprising is the dynamic and natural evolution of the deacy

it works like this: the oscillator spins on x, y and z axis, with different speeds,
while the radius decays
the ouput is the radius projected on x,y
( with dc offset you need to filter which I have omitted fior clarity )

Code: Select all


//################ 3D oscillatir demo
// spins in 3d with different speeds of x,y,and z axis
// very similar to fm/am, but more easy to use
// there is some initialisation bug, if it doesnt sound
// like a decent acoustic piano, retry

sample_rate = 44100
num_channels = 2 //stereo output

test=""

scr = get_screen()
xsize = get_xsize( scr )
ysize = get_ysize( scr )
hxsize = xsize / 2
hysize = ysize / 2

ratios = new( 34,1, FLOAT32)  // modulation ratios
ratios[ 0 ] = 1
ratios[ 1 ] = 6/5
ratios[ 2 ] = 4/5
ratios[ 3 ] = 4/3
ratios[ 4 ] = 1.5
ratios[ 5 ] = 5/3
ratios[ 6 ] = 1.75
ratios[ 7 ] = 1.8
for ( i = 8; i<24; i+1){
	ratios[ i ] = ratios[ i % 8 ] * (i div 8 +1)
}


samplerate = 44100
pi2 = 2 * M_PI

voices = 4
unis = 1
voicyc = 0

feedback = 0/ pi2

buf = new( 4096, 1, FLOAT32)

osc = new( voices)
for ( $v = 0; $v < voices; $v +1){
osc[ $v ] = new( 3, 1, FLOAT32)

rt= 4
rt2 = 8

zdep= 0.6

clean( osc_[ $v ] )
set_prop( osc[ $v ], "w", 0.012)
set_prop( osc[ $v ], "rt", ratios[rt])
set_prop( osc[ $v ], "rt2", ratios[rt2])
set_prop( osc[ $v ], "ph", 0.0)
set_prop( osc[ $v ], "ph2", 0.25)
set_prop( osc[ $v ], "ph3", 0.25)
set_prop( osc[ $v ], "r", 0.0)
set_prop( osc[ $v ], "zdep", 0.5)
set_prop( osc[ $v ], "fb", 0.0 )
set_prop( osc[ $v ], "state", 1)
}
for ( $v = 0; $v< voices; $v +1){
set_prop( osc[ $v ], "w", 440/samplerate )
set_prop( osc[ $v ], "ph", 0 ) 
set_prop( osc[ $v ], "ph2", 0.25 )
set_prop( osc[ $v ], "ph3", 0.25 )
	set_prop( osc[ $v ], "rt", ratios[rt])
	set_prop( osc[ $v ], "rt2", ratios[rt2])
tick_osc( $v, 1)
}

fn set_oscf( $v, $f, $zdep){
	set_prop( osc[ $v ], "w", $f / samplerate ) 
    set_prop( osc[ $v ], "zdep", $zdep)
	set_prop( osc[ $v ], "state", 0 ) 
ret
}


fn set_oscrt( $rt, $rt2){   
	for ( $v = 0; $v< voices; $v +1){
	set_prop( osc[ $v ], "rt", ratios[rt])
	set_prop( osc[ $v ], "rt2", ratios[rt2])
	}
ret
}

// ######## below is the oscillator, $v = voice, $scal = decay per tick
// r = radius / amplitude
// w = omega, normalized frequency
// ph..2,3 = phase x, y, z
// rt = frequency ratio y, z
// fb = feedback
// zdep = 2D / 3D z scaling, 0...1
// output is sqrt of x*x + y*y 
// in other words there is dc offset ...
// this doesent matter when you feed the output into a pick simulation
// ( not included in this version )
// not optimized and using trig operations for clarity
//

fn tick_osc( $v, $scal){ 
if get_prop( osc[ $v ], "state" ) ==0 {
	set_prop( osc[ $v ], "r", M_SQRT1_2 )
	set_prop( osc[ $v ], "ph", 0 ) 
	set_prop( osc[ $v ], "ph2", 0.25 )
	set_prop( osc[ $v ], "ph3", 0.25 )
	set_prop( osc[ $v ], "rt", ratios[rt])
	set_prop( osc[ $v ], "rt2", ratios[rt2])
set_prop( osc[ $v ], "state", 1 )
}

    $r = get_prop( osc[ $v ], "r") * $scal
	$w = get_prop( osc[ $v ], "w" ) + get_prop( osc[ $v ], "fb" )
	$rt = get_prop( osc[ $v ], "rt" )
	$rt2 = get_prop( osc[ $v ], "rt2" )
	$zdep= get_prop( osc[ $v ], "zdep" )
$ph = get_prop( osc[ $v ], "ph" ) + get_prop( osc[ $v ], "w" ) + get_prop( osc[ $v ], "fb" )
$ph2 = get_prop( osc[ $v ], "ph2" ) + get_prop( osc[ $v ], "w" ) * $rt
$ph3 = get_prop( osc[ $v ], "ph3" ) + get_prop( osc[ $v ], "w" ) * $rt2 
	set_prop( osc[ $v ], "ph", $ph ) 
	set_prop( osc[ $v ], "ph2", $ph2 )
	set_prop( osc[ $v ], "ph3", $ph3 )
	set_prop( osc[ $v ], "r", $r )  

	osc[ $v ][0] =(1 + ( cos( pi2 * $ph3) -1 ) *$zdep)* cos( pi2 * $ph2) * $r
	osc[ $v ][1] =(1 + (sin( pi2 * $ph3) -1 ) *$zdep)* sin( pi2 * $ph) * $r
	// z positi9n not needed here:
	//osc[ $v ][2] =(1 + ( sin( pi2 * $ph2) -1 ) *$zdep)* cos( pi2 * ph ) * $r
// outpout: [in audiocallback
//$vec = sqrt(osc[ $v ][ 0 ]*osc[ $v ][ 0 ]+ osc[ $v ][ 1 ]*osc[ $v ][ 1 ])

//feedback
$fb = osc[ $v ][0] * feedback 
set_prop( osc[ $v ], "fb", $fb )  
ret
}
// ########### end of oscillator code



//######### ui and audio render, slightly buggy.. ###########№##
fn audio_callback(
    $stream, 
    $userdata, 
    $channels, 
    $frames, 
    $output_time_in_system_ticks, 
    $in_channels, 
    $latency_in_frames )
{
    clean( $channels[ 0 ] )
	clean( buf )
    $ti = 0 
	while $ti < $frames {
		$v = 0
		while $v < voices {
			tick_osc( $v, 0.99995) 
			$vec = sqrt(osc[ $v ][ 0 ]*osc[ $v ][ 0 ]+ osc[ $v ][ 1 ]*osc[ $v ][ 1 ])			
			buf[ $ti ] + $vec *0.3
		 
		$v +1
		}
	$ti +1
	}	
	
	op_cc( OP_ADD, $channels[ 0 ], buf, 0, 0, $frames )
	//num_to_str( test, $frames )
ret( 1 )
}

set_audio_callback( audio_callback, 0, 44100, FLOAT32, 1 )
while( 1 )
{
    while( get_event() ) {
		if EVT[ EVT_TYPE ] == EVT_QUIT { breakall } 
		if EVT[ EVT_TYPE ] == EVT_MOUSEBUTTONDOWN{
			$x = EVT[ EVT_X ]
			$y = EVT[ EVT_Y ]
			if $y > 0 {
mode = -1
            voicyc + unis
			voicyc % voices
			note = 36 + floor(($x + xsize/2) / xsize * 36 ) 
			if note > 35 {
				$f = pow( 2, (note-69)/12 ) * 440 
				set_oscf( voicyc, $f, zdep) 
				//set_oscf( voicyc +1, $f + 0.02)
				zdep = 1- $y / hysize
			}

			} else {
			mode=floor((-4 * $y / hysize))
			if mode == 3
{ 
			$rt = rt
			$rt2 = rt2
			$rtnew = floor(($x + xsize/2) / xsize * 24 ) 
	rt = $rtnew rt2 = $rt2 
	set_oscrt( rt, rt2)
			}
			if mode == 2
{ 
			$rt = rt
			$rt2 = rt2
			$rtnew = floor(($x + xsize/2) / xsize * 24 ) 
	rt = $rt rt2 = $rtnew }
	set_oscrt( rt, rt2)
			}
			if mode == 1
{ feedback = ($x + xsize/2) / xsize
 feedback * feedback
 feedback / pi2
 
}
	}	
    }

	//transp(32)
    clear()
	
    $x = (note -36)/ 36 * xsize - xsize/2
    line( $x, 0, $x, ysize/2, RED)
	line( -xsize/2, 0, xsize/2, 0, RED)
	fbox( -xsize/2, -ysize/2, rt* xsize/24, ysize/8, GREEN)
	fbox( -xsize/2, -ysize*0.4, rt2* xsize/24, ysize/8, GREEN)
	fbox( -xsize/2, -ysize*0.25, sqrt(feedback)* xsize, ysize/8, BLUE)
fbox( -xsize/2, -ysize*0.125, zdep* xsize, ysize/8, WHITE)
	num_to_str(test, mode)
    print( test, -xsize / 2 + 8, -ysize / 2 + 8, WHITE, LEFT | TOP )
    frame(50)

}



ainegil
Posts: 168
Joined: Thu Sep 22, 2022 11:37 pm

Re: organic 3D oscillator demo

Post by ainegil »

short sound demo
User avatar
NightRadio
Site Admin
Posts: 3941
Joined: Fri Jan 23, 2004 12:28 am
Location: Ekaterinburg. Russia
Contact:

Re: organic 3D oscillator demo

Post by NightRadio »

Interesting algorithm!

clean( osc_[ $v ] ) - did you mean clean( osc[ $v ] ) ?

Also this

Code: Select all

set_prop( osc[ $v ], "w", 0.012)
set_prop( osc[ $v ], "rt", ratios[rt])
set_prop( osc[ $v ], "rt2", ratios[rt2])
set_prop( osc[ $v ], "ph", 0.0)
set_prop( osc[ $v ], "ph2", 0.25)
set_prop( osc[ $v ], "ph3", 0.25)
set_prop( osc[ $v ], "r", 0.0)
set_prop( osc[ $v ], "zdep", 0.5)
set_prop( osc[ $v ], "fb", 0.0 )
set_prop( osc[ $v ], "state", 1)
is the same (but slightly faster) as

Code: Select all

$o = osc[ $v ]
$o.w = 0.012
$o.rt = ratios[rt]
$o.rt2 = ratios[rt2]
$o.ph = 0.0
$o.ph2 = 0.25
$o.ph3 = 0.25
$o.r = 0.0
$o.zdep = 0.5
$o.fb = 0.0
$o.state = 1
ainegil
Posts: 168
Joined: Thu Sep 22, 2022 11:37 pm

Re: organic 3D oscillator demo

Post by ainegil »

NightRadio wrote: Sat Oct 29, 2022 1:56 pmg

clean( osc_[ $v ] ) - did you mean clean( osc[ $v ] ) ?
yes, thanks.

I think there are also some other bugs but I havent found them all.

Also the output is still experimental, maybe there is a better way to calculate it.

I wonder if its a bad idea to calculate everything during audiocallback,
but I cant think of another better structure.
ainegil
Posts: 168
Joined: Thu Sep 22, 2022 11:37 pm

Re: organic 3D oscillator demo

Post by ainegil »

here is an update

audio calculation is now outside the callback function,
sin and sqrt uses tables, non interpolated, dc remover filter,
different feedback scaling, some small fixes

still, I dont get enough voices out if it

MIDI or keyboard or multitouch is still missing

Code: Select all


//################ 3D oscillator demo
// spins in 3d with different speeds of x,y,and z axis
// very similar to fm/am, but more easy to use
// there is some initialisation bug, if id doesnt sound
// like a decent acoustic piano, retrx

sample_rate = 44100
num_channels = 2 //stereo output

test=""

recording = new( 30* 44100, 1, INT16)
clean(record)
rectrack = 0
done = 0
saved = 0
recbuf = new(4096,1, INT16)

buf = new( 4096, 1, FLOAT32)
clean(buf)
delay = 256
frameptrw = delay
frameptrr = 0


scr = get_screen()
xsize = get_xsize( scr )
ysize = get_ysize( scr )
hxsize = xsize / 2
hysize = ysize / 2

samplerate = sample_rate
pi2 = 2 * M_PI

voices = 4
unis = 1
voicyc = 0

wts = new( 32768, 1, FLOAT32)
wtc = new( 32768, 1, FLOAT32)
wtsqrt = new( 32768, 1, FLOAT32)
//wtpk = new( 32768, 1, FLOAT32)
for ( i = 0; i<32768; i+1){
 $frac = i / 32768
 wts[ i ] = sin( pi2 * $frac )
 wtc[ i ] = cos( pi2 * $frac )
if $frac == 0 { wtsqrt[ i ] = 0 } else { wtsqrt[ i ] = sqrt( $frac ) }
 //wtpk[ i ] = $frac * $frac / pow( $frac * $frac +0.25, 3/2)
}
fn sint($ii){
$i = floor($ii)
$frc = $ii-$i
ret( wts[ $i ] + ( wts[ ($i +1) & 32767] - wts[ $i ] )*$frc )
}
fn cost($ii){
$i = floor($ii)
$frc = $ii-$i
ret( wtc[ $i ] + ( wtc[ ($i +1) & 32767] - wtc[ $i ] )*$frc )
}

ratios = new( 34,1, FLOAT32)  // modulation ratios
ratios[ 0 ] = 1
ratios[ 1 ] = 6/5
ratios[ 2 ] = 4/5
ratios[ 3 ] = 4/3
ratios[ 4 ] = 1.5
ratios[ 5 ] = 5/3
ratios[ 6 ] = 1.75
ratios[ 7 ] = 1.8
for ( i = 8; i<24; i+1){
	ratios[ i ] = ratios[ i % 8 ] * (i div 8 +1)
}



feedback = 0


rt= 4
rt2 = 20

zdep= 0.6
fb = 0.5

hp = 0
hpz = 0
lp = 0
lpz = 0

osc = new( voices)
for ( $v = 0; $v < voices; $v +1){
osc[ $v ] = new( 3, 1, FLOAT32)
clean( osc[ $v ] )
set_prop( osc[ $v ], "w", 326.96)
set_prop( osc[ $v ], "w2", 326.96 * ratios[rt])
set_prop( osc[ $v ], "w3", 326.96 * ratios[rt2])
set_prop( osc[ $v ], "ph", 0.0)
set_prop( osc[ $v ], "ph2", 8191.0)
set_prop( osc[ $v ], "ph3", 8191.0)
set_prop( osc[ $v ], "r", 0.0)
set_prop( osc[ $v ], "zdep", 0.5)
set_prop( osc[ $v ], "fb", 0.0 )
set_prop( osc[ $v ], "state", 1)
set_prop( osc[ $v ], "rt", ratios[rt])
set_prop( osc[ $v ], "rt2", ratios[rt2])
set_prop( osc[ $v ], "vec", 0.0)
}


fn set_oscf( $v, $f, $zdep){
	set_prop( osc[ $v ], "w",  $f * 32768 / samplerate )
	set_prop( osc[ $v ], "w2",  $f * ratios[rt] * 32768 / samplerate ) 
	set_prop( osc[ $v ], "w3",  $f * ratios[rt2] * 32768 / samplerate ) 
    set_prop( osc[ $v ], "zdep", $zdep)
	set_prop( osc[ $v ], "state", 0 ) 
ret
}


fn set_oscrt( $rt, $rt2){   
	for ( $v = 0; $v< voices; $v +1){
	set_prop( osc[ $v ], "rt", ratios[rt])
	set_prop( osc[ $v ], "rt2", ratios[rt2])
	}
ret
}

// ######## below is the oscillator, $v = voice, $scal = decay per tick
// r = radius / amplitude
// w ..2,3 = omega, normalized frequency
// ph..2,3 = phase x, y, z
// rt, rt2 = frequency ratio y, z
// fb = feedback
// zdep = 2D / 3D z scaling, 0...1
// output is sqrt of x*x + y*y 
// in other words there is dc offset ...
// this doesent matter when you feed the output into a pickup simulation
// not optimized and using trig operations for clarity
//

fn tick_osc( $v, $scal){ 
if get_prop( osc[ $v ], "state" ) ==0 {
	set_prop( osc[ $v ], "r", M_SQRT1_2 )
	set_prop( osc[ $v ], "ph", 0.0 ) 
	set_prop( osc[ $v ], "ph2", 8192.0 )
	set_prop( osc[ $v ], "ph3", 8192.0 )
	set_prop( osc[ $v ], "rt", ratios[rt])
	set_prop( osc[ $v ], "rt2", ratios[rt2])
set_prop( osc[ $v ], "state", 1 )
}

    $r = get_prop( osc[ $v ], "r") * $scal
	$zdep= get_prop( osc[ $v ], "zdep" )
	$o3 = osc[ $v ]
	$fb = ($o3[0] +1 )* feedback16
$ph = get_prop( osc[ $v ], "ph" ) + get_prop( osc[ $v ], "w" ) 
$ph2 = get_prop( osc[ $v ], "ph2" ) + get_prop( osc[ $v ], "w2" ) 
$ph3 = get_prop( osc[ $v ], "ph3" ) + get_prop( osc[ $v ], "w3" ) 

$ph + $fb
$ph = mod( $ph, 32768) 
$ph2 = mod( $ph2, 32768) 
$ph3 = mod( $ph3, 32768) 

	$o3[0] =(1 + (wtc[$ph3] -1 ) *$zdep)* wtc[$ph2] *$r
	$o3[1] =(1 + (wts[$ph3] -1 ) *$zdep)* wts[$ph] *$r
$vec = $o3[0]*$o3[0] + $o3[1]*$o3[1]
$vec = wtsqrt[ $vec * 32768 ] 
osc[ $v ]=$o3
	set_prop( osc[ $v ], "vec", $vec)
	set_prop( osc[ $v ], "ph", $ph ) 
	set_prop( osc[ $v ], "ph2",$ph2 )
	set_prop( osc[ $v ], "ph3",$ph3 )
	set_prop( osc[ $v ], "r", $r )  
testv = $o3[1]
ret
}
// ########### end of oscillator code



//######### ui and audio render, slightly buggy.. ###########№##
fn audio_callback(
    $stream, 
    $userdata, 
    $channels, 
    $frames, 
    $output_time_in_system_ticks, 
    $in_channels, 
    $latency_in_frames )
{
    clean( $channels[ 0 ] )

$ti = 0 
while $ti < $frames {
	$ptr = ($ti  + frameptrr ) & 4095
 	op_cc( OP_ADD, $channels[ 0 ], buf, $ti, $ptr, 1 )
$ti +1
}

frameptrr + $frames
frameptrr & 4095
frames = $frames
    
ret( 1 )
}

set_audio_callback( audio_callback, 0, 44100, FLOAT32, 1 )
start_timer( 0 )
while( 1 ){



    while( get_event() ) {
		if EVT[ EVT_TYPE ] == EVT_QUIT { breakall } 
		if EVT[ EVT_TYPE ] == EVT_MOUSEBUTTONDOWN{
			$x = EVT[ EVT_X ]
			$y = EVT[ EVT_Y ]
			if $y > 0 {
mode = -1
            voicyc + unis
			voicyc % voices
			note = 36 + floor(($x + xsize/2) / xsize * 36 ) 
			if note > 35 {
				$f = pow( 2, (note-69)/12 ) * 440 
				set_oscf( voicyc, $f, zdep) 
				//set_oscf( voicyc +1, $f + 0.02)
				zdep = 1- $y / hysize
				zdep = zdep * zdep
			}

			} else {
			mode=floor((-4 * $y / hysize))
			if mode == 3
{ 
			$rt = rt
			$rt2 = rt2
			$rtnew = floor(($x + xsize/2) / xsize * 24 ) 
	rt = $rtnew rt2 = $rt2 
	set_oscrt( rt, rt2)
			}
			if mode == 2
{ 
			$rt = rt
			$rt2 = rt2
			$rtnew = floor(($x + xsize/2) / xsize * 24 ) 
	rt = $rt rt2 = $rtnew }
	set_oscrt( rt, rt2)
			}
			if mode == 1
{ feedback = ($x + xsize/2) / xsize
 feedback16 = feedback * feedback * feedback
 feedback16 = feedback16 / pi2
 feedback16 = feedback16 * 16384
 
}
	}	
    }

	//transp(32)
    clear()
	
    $x = (note -36)/ 36 * xsize - xsize/2
    line( $x, ysize/2, $x, (1-zdep)*ysize/2, RED)
	line( -xsize/2, 0, xsize/2, 0, RED)
	fbox( -xsize/2, -ysize/2, rt* xsize/24, ysize/8, GREEN)
	fbox( -xsize/2, -ysize*0.4, rt2* xsize/24, ysize/8, GREEN)
	fbox( -xsize/2, -ysize*0.25, feedback* xsize, ysize/8, BLUE)
//fbox( -xsize/2, -ysize*0.125, zdep* xsize, ysize/8, WHITE)
	num_to_str(test, testv)
    print( test, -xsize / 2 + 8, -ysize / 2 + 8, WHITE, LEFT | TOP )


// #№########################### synth
dur = get_timer(0)   
start_timer( 0 )
len = dur / (1000/samplerate)

$ti = frameptrw 
$frameend = frameptrw + len
frameptrw = $frameend & 4095
while $ti < $frameend {
$ptr = $ti & 4095
buf[ $ptr ] = 0
		$v = 0 while $v < voices {
			tick_osc( $v, 0.99992) 
			//$vec = get_prop( osc[ $v ], "vec")		
			// pickup curve			
			//$vec = $vec*$vec / pow( $vec*$vec +0.25, 3/2)

			buf[ $ptr ] + get_prop( osc[ $v ], "vec") *0.2
			
		$v +1
		}
	//dc removal
	hp = buf[ $ptr ]
	hp - hpz
    lp = lpz + ( hp  - lpz )  * 0.9992
    lpz = lp
	buf[ $ptr ] = lp

	$ti +1
	}	



    frame( 20)
}

ainegil
Posts: 168
Joined: Thu Sep 22, 2022 11:37 pm

Re: organic 3D oscillator demo

Post by ainegil »

update with many improvements

however there is one strange thing on Android :
when no notes are played, the main loop starts getting very slow
and the buffer gets out of synch and there is a lot if crackling noise

the number on the display shows the number of samples per loop
on the tablet when you play fast it gets down to below 200 which is good
but when you stop playing it gets up to over 4000

I wonder if its a problem with denormals or if the get_event is taking longer when
there are no events or if Android changes something when there is no touch event

Code: Select all


//################ 3D oscillator demo
// spins in 3d with different speeds of x,y,and z axis
// very similar to fm/am


set_pixel_size( WINDOW_XSIZE / 640 )
resize( get_screen(), WINDOW_XSIZE, WINDOW_YSIZE )

sample_rate = 44100

buf = new( 8192, 1, FLOAT32)
clean(buf)
delay = 384 // internal latency
frameptrw = delay
frameptrr = 0

uirate = 64 // samples per UI tick
uiclock = 0
uicolor = get_color ( 255,191,64)

voices = 3
unis = 1
voicyc = 0

scr = get_screen()
xsize = get_xsize( scr )
ysize = get_ysize( scr )
hxsize = xsize / 2
hysize = ysize / 2

pi2 = 2 * M_PI

denorm = pow(10, -11)

test=""

echbuf = new( 65536, 1, FLOAT32)
clean(echbuf)
echot = 44100 *  375/ 1000
echptrw = echot
echptrr = 0

fn echofx( $in, $fb ){
echptrw + 1
echptrw & 65535
echptrr + 1
echptrr & 65535
$out = echbuf[ echptrr ]

lpe = lpez + ( $in + $fb * $out + denorm - lpez )  * 0.893 + denorm
lpez = lpr

echbuf[ echptrw ] = lpe
ret( $out )
}

fn pckp( $x ){
$x = 0.25 / sqrt( $x*$x +0.0625)
ret( $x )
}


ratios = new( 24,1, FLOAT32)  // modulation ratios
ratios[ 0 ] = 1
ratios[ 1 ] = 6/5
ratios[ 2 ] = 5/4
ratios[ 3 ] = 4/3
ratios[ 4 ] = 1.5
ratios[ 5 ] = 5/3
ratios[ 6 ] = 9/5
ratios[ 7 ] = 15/8
for ( i = 8; i<24; i+1){
	ratios[ i ] = ratios[ i % 8 ] * (i div 8 +1)
}



feedback = 0.0625
decay = 0.5
decay2 = pow(10, decay * 2.3 + 2.9) 
decay2 = pow(M_E, -  0.693147181 / decay2)

rt= 4
rt2 = 20

zdep= 0.6
fb = 0.5

hp = 0
hpz = 0
lp = 0
lpz = 0

osc = new( voices)
for ( $v = 0; $v < voices; $v +1){
osc[ $v ] = new( 3, 1, FLOAT32)
clean( osc[ $v ] )
set_prop( osc[ $v ], "w", 326.96)
set_prop( osc[ $v ], "w2", 326.96 * ratios[rt])
set_prop( osc[ $v ], "w3", 326.96 * ratios[rt2])
set_prop( osc[ $v ], "ph", 0.0)
set_prop( osc[ $v ], "ph2", M_PI)
set_prop( osc[ $v ], "ph3", M_PI)
set_prop( osc[ $v ], "r", 0.0)
set_prop( osc[ $v ], "zdep", 0.5)
set_prop( osc[ $v ], "fb", 0.0 )
set_prop( osc[ $v ], "fb2", 0.0 )
set_prop( osc[ $v ], "state", 1)
set_prop( osc[ $v ], "rt", ratios[rt])
set_prop( osc[ $v ], "rt2", ratios[rt2])
set_prop( osc[ $v ], "vec", 0.0)
}


fn set_oscf( $v, $f, $zdep){
	set_prop( osc[ $v ], "w",  $f * pi2 / sample_rate )
	set_prop( osc[ $v ], "w2",  $f * ratios[rt] * pi2 / sample_rate ) 
	set_prop( osc[ $v ], "w3",  $f * ratios[rt2] * pi2 / sample_rate ) 
    set_prop( osc[ $v ], "zdep",$zdep)
	set_prop( osc[ $v ], "state", 0 ) 
ret
}


fn set_oscrt( $rt, $rt2){   
	for ( $v = 0; $v< voices; $v +1){
	set_prop( osc[ $v ], "rt", ratios[rt])
	set_prop( osc[ $v ], "rt2", ratios[rt2])
	}
ret
}

// ######## below is the oscillator, $v = voice, $scal = decay per tick
// r = radius / amplitude
// w ..2,3 = omega, normalized frequency
// ph..2,3 = phase x, y, z
// rt, rt2 = frequency ratio y, z
// fb = feedback
// zdep = 2D / 3D z scaling, 0...1
//

fn tick_osc( $v, $scal){ 
if get_prop( osc[ $v ], "state" ) ==0 { 

	set_prop( osc[ $v ], "r", 1 ) //M_SQRT1_2 )

$sn = osc[ $v ][1]
$phn = atan2( abs($sn), sqrt( 1 - $sn * $sn ))
$phn = $phn 
	set_prop( osc[ $v ], "ph", $phn) 
$cs = osc[ $v ][0]
$phn = atan2( sqrt( 1 - $cs * $cs ), abs($cs))
$phn = $phn 
	set_prop( osc[ $v ], "ph2", $phn )
	set_prop( osc[ $v ], "rt", ratios[rt])
	set_prop( osc[ $v ], "rt2", ratios[rt2])
set_prop( osc[ $v ], "state", 1 )
}

    $r = get_prop( osc[ $v ], "r") * $scal + denorm
	$zdep= get_prop( osc[ $v ], "zdep" )
	
$ph = get_prop( osc[ $v ], "ph" ) + get_prop( osc[ $v ], "w" ) 
$ph2 = get_prop( osc[ $v ], "ph2" ) + get_prop( osc[ $v ], "w2" ) 
$ph3 = get_prop( osc[ $v ], "ph3" ) + get_prop( osc[ $v ], "w3" ) 


set_prop( osc[ $v ], "fb", (osc[ $v ][0] + get_prop( osc[ $v ], "fb"))* 0.5)
$ph = $ph + get_prop( osc[ $v ], "fb") * feedback2
//set_prop( osc[ $v ], "fb2", (osc[ $v ][1] + get_prop( osc[ $v ], "fb2"))* 0.5)
//$ph2 = $ph2 + get_prop( osc[ $v ], "fb2") * feedback2

$ph = mod( $ph, pi2) 
$ph2 = mod( $ph2, pi2) 
$ph3 = mod( $ph3, pi2) 


	osc[ $v ][0] =(1 + (cos($ph3) -1 ) *$zdep)* cos($ph2) *$r
	osc[ $v ][1] =(1 + (sin($ph3) -1 ) *$zdep)* sin($ph) *$r
$vec = osc[ $v ][0]*osc[ $v ][0] + osc[ $v ][1]*osc[ $v ][1]
$vec = sqrt ($vec + denorm)  
	set_prop( osc[ $v ], "vec", $vec)
	set_prop( osc[ $v ], "ph", $ph ) 
	set_prop( osc[ $v ], "ph2",$ph2 )
	set_prop( osc[ $v ], "ph3",$ph3 )
	set_prop( osc[ $v ], "r", $r )  

ret( $vec)
}
// ########### end of oscillator code



//######### ui and audio render, slightly buggy.. ###########№##
fn audio_callback(
    $stream, 
    $userdata, 
    $channels, 
    $frames, 
    $output_time_in_system_ticks, 
    $in_channels, 
    $latency_in_frames )
{
    clean( $channels[ 0 ] )
	clean( $channels[ 1 ] )
if frameptrr + $frames < 8191{
	op_cc( OP_COPY, $channels[ 0 ], buf, 0, frameptrr, $frames )
	op_cc( OP_COPY, $channels[ 1 ], buf, 0, frameptrr, $frames )
frameptrr + $frames
frameptrr & 8191

}else{
$range2 = (frameptrr + $frames ) & 8191
$range1 = $frames - $range2
	op_cc( OP_COPY, $channels[ 0 ], buf, 0, frameptrr, $range1 )
	op_cc( OP_COPY, $channels[ 0 ], buf, $range1, 0, $range2 )
	op_cc( OP_COPY, $channels[ 1 ], buf, 0, frameptrr, $range1 )
	op_cc( OP_COPY, $channels[ 1 ], buf, $range1, 0, $range2 )
frameptrr + $frames
frameptrr & 8191
}


    
ret( 1 )
}



set_audio_callback( audio_callback, 0, 44100, FLOAT32, 2 )


start_timer( 1 )
//######### main loop #############

while( 1 ){
    
	clear()
    $x = (note -36)/ 36 * xsize - xsize/2
    line( $x, ysize/2, $x, (1-zdep)*ysize/2, uicolor)
	line( -xsize/2, 0, xsize/2, 0, uicolor)
	fbox( -xsize/2 + rt* xsize/24, -ysize/2, xsize/24, ysize/8, uicolor)
	fbox( -xsize/2 + rt2* xsize/24, -ysize*0.375, xsize/24, ysize/8, uicolor)
	fbox( -xsize/2, -ysize*0.225, feedback* xsize, ysize/16, uicolor)
	fbox( -xsize/2, -ysize*0.1, decay* xsize, ysize/16, uicolor)
num_to_str(test, len) // LOOP DURATION SAMPLES
    print( test, xsize / 2 -24 , -ysize / 2 + 8, WHITE, RIGHT | TOP )




// #№########################### synth
dur = get_timer(1)   
start_timer( 1 )
len = dur * sample_rate / 1000
len = floor( len )
$ti = frameptrw 
$frameend = frameptrw + len
frameptrw = ($frameend ) & 8191
$x= -xsize/2
while $ti < $frameend {
	$ptr = $ti & 8191
	buf[ $ptr ] = 0

if uiclock < uirate {uiclock +1} else {uiclock = 0 ui()}

		$v = 0 while $v < voices {
			buf[ $ptr ] + pckp(tick_osc( $v, decay2) * 0.4 )
		$v +1
		}

	//dc removal
	hp = buf[ $ptr ]
	hp - lpz + denorm
    lp = lpz + hp   * 0.999287
    lpz = lp
	lp2 = lp2z + ( hp - lp2z )  * 0.9943 + denorm
	lp2z = lp2

	buf[ $ptr ] = lp2 + echofx( lp2 *0.6, 0.6)
 
$ti +1
}	

frame()

    
}

fn ui(){    while ( get_event() ) {
		if EVT[ EVT_TYPE ] == EVT_QUIT { breakall } 
		if EVT[ EVT_TYPE ] == EVT_MOUSEBUTTONDOWN {
			$x = EVT[ EVT_X ]
			$y = EVT[ EVT_Y ]
if $y > 0 {
mode = -1
            voicyc + unis
			voicyc % voices
			note = 36 + floor(($x + xsize/2) / xsize * 36 ) 
			if note > 35 {
				$f = pow( 2, (note-69)/12 ) * 440 				
				zdep = 1- $y / hysize
				zdep = zdep * zdep
				set_oscf( voicyc, $f, zdep) 
				}
			break
	} else { 
if $y < 0 {
					
mode=floor((-4 * $y / hysize))
if mode == 3
{ 
			$rt = rt
			$rt2 = rt2
			$rtnew = floor(($x + xsize/2) / xsize * 24 ) 
			rt = $rtnew rt2 = $rt2 
			set_oscrt( rt, rt2)
			break
			}
if mode == 2
{ 
			$rt = rt
			$rt2 = rt2
			$rtnew = floor(($x + xsize/2) / xsize * 24 ) 
			rt = $rt rt2 = $rtnew 
			set_oscrt( rt, rt2)
			break
			}
if mode == 1
{		   feedback = ($x + xsize/2) / xsize
 		   feedback2 = feedback * feedback  
 		   break 
			}
if mode == 0
{		   decay = ($x + xsize/2) / xsize
		  decay2 = pow(10, decay * 2.3 + 2.9) 
 		       decay2 = pow(M_E, -  0.693147181 / decay2)
 		  	 break 
			}
}}
	
}
    break	
    }
ret
}

ainegil
Posts: 168
Joined: Thu Sep 22, 2022 11:37 pm

Re: organic 3D oscillator demo

Post by ainegil »

fixed it!

new ratios!

proper envelooe attack and decay times!

Stereo Echo!

No crackles !

Code: Select all


//################ 3D oscillator demo
// spins in 3d with different speeds of x,y,and z axis
// very similar to fm/am


set_pixel_size( WINDOW_XSIZE / 640 )
resize( get_screen(), WINDOW_XSIZE, WINDOW_YSIZE )

sample_rate = 44100
tausr = 1 / sample_rate

buf = new( 8192, 1, FLOAT32)
bufr = new( 8192, 1, FLOAT32)
clean(buf)
clean(bufr)
delay = 384 // internal latency
frameptrw = delay
frameptrr = 0

uirate = 64 // samples per UI tick
uiclock = 0
uicolor = get_color ( 255,191,64)
uicolor2 = get_color ( 128,95,32)
uicolor3 = get_color ( 64,46,16)
ptext = ""
pnumtext = ""

voices = 3
unis = 1
voicyc = 0

scr = get_screen()
xsize = get_xsize( scr )
ysize = get_ysize( scr )
hxsize = xsize / 2
hysize = ysize / 2

pi2 = 2 * M_PI
sqrt12_2 = pow(2, 1/12)

denorm = pow(10, -11)

test=""

echbufl = new( 65536, 1, FLOAT32)
echbufr = new( 65536, 1, FLOAT32)
clean(echbufl)
clean(echbufr)
echotl = 44100 *  250/ 1000
echotr = 44100 *  375/ 1000
echptrw = echotr
echptrl = echotr - echotl
echptrr = 0

fn echofx( $in, $fb ){
echptrw + 1
echptrw & 65535
echptrl + 1
echptrl & 65535
echptrr + 1
echptrr & 65535
$outl = echbufl[ echptrl ] 
$outr = echbufr[ echptrr ] 

lpel = lpelz + ( $in + $fb * $outl + denorm - lpelz )  * 0.893 + denorm
lpelz = lpel
lper = lperz + ( $in + $fb * $outr + denorm - lperz )  * 0.893 + denorm
lperz = lper

echbufl[ echptrw ] = lpel
echbufr[ echptrw ] = lper
ret
}

fn pckp( $x ){
$x = 0.25 / sqrt( $x*$x +0.0625)
ret( $x )
}


ratios = new( 36,1, FLOAT32)  // modulation ratios
ratios[ 8 ] = 1
ratios[ 9 ] = 6/5
ratios[ 10 ] = 5/4
ratios[ 11 ] = 4/3
ratios[ 12 ] = 1.5
ratios[ 13 ] = 5/3
ratios[ 14 ] = 9/5
ratios[ 15 ] = 15/8
for ( i = 16; i<36; i+1){
$dp = log2(ratios[ i % 8 + 8 ])/log2(sqrt12_2) 
ratios[ i ] = pow(sqrt12_2, $dp + 12 * ( i div 8 ) -12 )
}
for ( i = 0; i<8; i+1){
$dp = log2(ratios[ i % 8 + 8 ])/log2(sqrt12_2) 
ratios[ i ] = pow(sqrt12_2, $dp -12 )
}
notec = new( 12, 1, INT)
notec[ 0 ] = 0
notec[ 1 ] = 1
notec[ 2 ] = 0
notec[ 3 ] = 1
notec[ 4 ] = 0
notec[ 5 ] = 0
notec[ 6 ] = 1
notec[ 7 ] = 0
notec[ 8 ] = 1
notec[ 9 ] = 0
notec[ 10 ] = 1
notec[ 11 ] = 0



feedback = 0.0625
attack = 0.125
			attack2 = 6 + 54 * attack			
			attack2 = pow(10, attack2 / 20) * 0.001
			attack2 = pow(M_E, - tausr/ ( 0.693147181 * attack2) )
decay = 0.5
decay2 = 18 + 66 * decay
decay2 = pow(10, decay2 / 20) * 0.001
decay2 = pow(M_E, - tausr/ ( 0.693147181 * decay2) )

rt= 4
rt2 = 20

zdep= 0.6
fb = 0.5

hp = 0
hpz = 0
lp = 0
lpz = 0

osc = new( voices)
for ( $v = 0; $v < voices; $v +1){
osc[ $v ] = new( 3, 1, FLOAT32)
clean( osc[ $v ] )
set_prop( osc[ $v ], "w", 326.96)
set_prop( osc[ $v ], "w2", 326.96 * ratios[rt])
set_prop( osc[ $v ], "w3", 326.96 * ratios[rt2])
set_prop( osc[ $v ], "ph", 0.0)
set_prop( osc[ $v ], "ph2", M_PI)
set_prop( osc[ $v ], "ph3", M_PI)
set_prop( osc[ $v ], "r", 0.0)
set_prop( osc[ $v ], "zdep", 0.5)
set_prop( osc[ $v ], "fb", 0.0 )
set_prop( osc[ $v ], "fb2", 0.0 )
set_prop( osc[ $v ], "state", 2)
set_prop( osc[ $v ], "rt", ratios[rt])
set_prop( osc[ $v ], "rt2", ratios[rt2])
set_prop( osc[ $v ], "vec", 0.0)
}


fn set_oscf( $v, $f, $zdep){
	set_prop( osc[ $v ], "w",  $f * pi2 / sample_rate )
	set_prop( osc[ $v ], "w2",  $f * ratios[rt] * pi2 / sample_rate ) 
	set_prop( osc[ $v ], "w3",  $f * ratios[rt2] * pi2 / sample_rate ) 
    set_prop( osc[ $v ], "zdep",$zdep)
	set_prop( osc[ $v ], "state", 0 ) 
ret
}


fn set_oscrt( $rt, $rt2){   
	for ( $v = 0; $v< voices; $v +1){
	set_prop( osc[ $v ], "rt", ratios[rt])
	set_prop( osc[ $v ], "rt2", ratios[rt2])
	}
ret
}

// ######## below is the oscillator, $v = voice, $scal = decay per tick
// r = radius / amplitude
// w ..2,3 = omega, normalized frequency
// ph..2,3 = phase x, y, z
// rt, rt2 = frequency ratio y, z
// fb = feedback
// zdep = 2D / 3D z scaling, 0...1
//

fn tick_osc( $v ){ 
if get_prop( osc[ $v ], "state" ) == 0 { 
	 
	if get_prop( osc[ $v ], "r") < 0.008 {  
	set_prop( osc[ $v ], "r", 0.008 ) }

$sn = osc[ $v ][1]
$phn = atan2( abs($sn), sqrt( 1 - $sn * $sn ))
$phn = $phn 
	set_prop( osc[ $v ], "ph", $phn) 
$cs = osc[ $v ][0]
$phn = atan2( sqrt( 1 - $cs * $cs ), abs($cs))
$phn = $phn 
	set_prop( osc[ $v ], "ph2", $phn )
	set_prop( osc[ $v ], "rt", ratios[rt])
	set_prop( osc[ $v ], "rt2", ratios[rt2])
	set_prop( osc[ $v ], "state", 1 )
}
if get_prop( osc[ $v ], "state" ) == 1 { 
	$r = get_prop( osc[ $v ], "r")
	if $r < 0.008 { $r = 0.008 }
	$r = 1- (1- $r) * attack2
	if $r > 0.992{
		$r = 1 
		set_prop( osc[ $v ], "state", 2 ) 
	}
	set_prop( osc[ $v ], "r", $r )
}
if get_prop( osc[ $v ], "state" ) == 2 { 
		$r = get_prop( osc[ $v ], "r") * decay2 + denorm
		set_prop( osc[ $v ], "r", $r )	
}

    //$r = get_prop( osc[ $v ], "r") * $scal + denorm
	$zdep= get_prop( osc[ $v ], "zdep" )
	
$ph = get_prop( osc[ $v ], "ph" ) + get_prop( osc[ $v ], "w" ) 
$ph2 = get_prop( osc[ $v ], "ph2" ) + get_prop( osc[ $v ], "w2" ) 
$ph3 = get_prop( osc[ $v ], "ph3" ) + get_prop( osc[ $v ], "w3" ) 


set_prop( osc[ $v ], "fb", (osc[ $v ][0] + get_prop( osc[ $v ], "fb"))* 0.5)
$ph = $ph + get_prop( osc[ $v ], "fb") * feedback2
//set_prop( osc[ $v ], "fb2", (osc[ $v ][1] + get_prop( osc[ $v ], "fb2"))* 0.5)
//$ph2 = $ph2 + get_prop( osc[ $v ], "fb2") * feedback2

$ph = mod( $ph, pi2) 
$ph2 = mod( $ph2, pi2) 
$ph3 = mod( $ph3, pi2) 


	osc[ $v ][0] =(1 + (cos($ph3) -1 ) *$zdep)* cos($ph2) *$r
	osc[ $v ][1] =(1 + (sin($ph3) -1 ) *$zdep)* sin($ph) *$r
$vec = osc[ $v ][0]*osc[ $v ][0] + osc[ $v ][1]*osc[ $v ][1]
$vec = sqrt ($vec + denorm)  
	set_prop( osc[ $v ], "vec", $vec)
	set_prop( osc[ $v ], "ph", $ph ) 
	set_prop( osc[ $v ], "ph2",$ph2 )
	set_prop( osc[ $v ], "ph3",$ph3 )
	//set_prop( osc[ $v ], "r", $r )  

ret( $vec)
}
// ########### end of oscillator code



//######### ui and audio render, slightly buggy.. ###########№##
fn audio_callback(
    $stream, 
    $userdata, 
    $channels, 
    $frames, 
    $output_time_in_system_ticks, 
    $in_channels, 
    $latency_in_frames )
{
    clean( $channels[ 0 ] )
	clean( $channels[ 1 ] )
if frameptrr + $frames < 8191{
	op_cc( OP_COPY, $channels[ 0 ], buf, 0, frameptrr, $frames )
	op_cc( OP_COPY, $channels[ 1 ], bufr, 0, frameptrr, $frames )
frameptrr + $frames
frameptrr & 8191

}else{
$range2 = (frameptrr + $frames ) & 8191
$range1 = $frames - $range2
	op_cc( OP_COPY, $channels[ 0 ], buf, 0, frameptrr, $range1 )
	op_cc( OP_COPY, $channels[ 0 ], buf, $range1, 0, $range2 )
	op_cc( OP_COPY, $channels[ 1 ], bufr, 0, frameptrr, $range1 )
	op_cc( OP_COPY, $channels[ 1 ], bufr, $range1, 0, $range2 )
frameptrr + $frames
frameptrr & 8191
}  
ret( 1 )
}



set_audio_callback( audio_callback, 0, 44100, FLOAT32, 2 )


start_timer( 1 )
//######### main loop #############

while( 1 ){
    
	clear()
//line( -xsize/2, -ysize/2 + ysize/16, xsize/2, -ysize/2 + ysize/16, uicolor3)
//line( -xsize/2, -ysize/2 + ysize* 0.1875, xsize/2, -ysize/2 + ysize* 0.1875, uicolor3)
line( -xsize/2, -ysize/2 + ysize/8, xsize/2, -ysize/2 + ysize/8, uicolor3)
line( -xsize/2, -ysize/2 + ysize* 0.25, xsize/2, -ysize/2 + ysize* 0.25, uicolor3)
line( -xsize/2, -ysize/2 + ysize* 0.3125, xsize/2, -ysize/2 + ysize* 0.3125, uicolor3)
line( -xsize/2, -ysize/2 + ysize* 0.375, xsize/2, -ysize/2 + ysize* 0.375, uicolor3)
for ( i = 0 ; i < 36; i +1){
$x = i * xsize / 36 
$hk = xsize / 72
if  notec[ i % 12 ] {
line( -xsize/2 +$x, 0,- xsize/2 +$x, ysize / 2, uicolor3)

}else{
fbox( -xsize/2 + $x, 0, xsize / 36, ysize/2, uicolor3)

}

if i % 8 == 0 {
line( -xsize/2 +$x + $hk, -ysize/2,- xsize/2 +$x + $hk, -ysize / 4, uicolor2)
}else{ if i % 8 == 4 { 
line( -xsize/2 +$x + $hk, -ysize*0.4375,- xsize/2 +$x + $hk, -ysize *0.3125, uicolor3)
}}

}



    $x = (note -36)/ 36 * xsize - xsize/2 + xsize/72
    line( $x, ysize/2, $x, (1-zdep)*ysize/2, uicolor)
	//line( -xsize/2, 0, xsize/2, 0, uicolor)
	fbox( -xsize/2 + rt* xsize/36, -ysize/2, xsize/36, ysize/8, uicolor)
	fbox( -xsize/2 + rt2* xsize/36, -ysize*0.375, xsize/36, ysize/8, uicolor)
	fbox( -xsize/2, -ysize*0.25, feedback* xsize, ysize/16, uicolor)
	fbox( -xsize/2, -ysize*0.1875, attack* xsize, ysize/16, uicolor2)
	fbox( -xsize/2, -ysize*0.125, decay* xsize, ysize/16, uicolor2)

    print( pnumtext, xsize / 2 -24 , -ysize / 2 + 8, uicolor, RIGHT | TOP )
	print( ptext, xsize / 2 -24 , -ysize / 2 + 24, uicolor2, RIGHT | TOP )




// #№########################### synth
dur = get_timer(1)   
start_timer( 1 )
len = dur * sample_rate / 1000
len = floor( len )
$ti = frameptrw 
$frameend = frameptrw + len
frameptrw = ($frameend ) & 8191
$x= -xsize/2
while $ti < $frameend {
	$ptr = $ti & 8191
	$smp = 0

if uiclock < uirate {uiclock +1} else {uiclock = 0 ui() }

		$v = 0 while $v < voices {
			$smp = $smp + pckp(tick_osc( $v ) * 0.4 )
		$v +1
		}

	//dc removal
	hp = $smp
	hp - lpz 
    lp = lpz + hp   * 0.999287
    lpz = lp
	lp2 = lp2z + ( hp - lp2z )  * 0.9943 
	lp2z = lp2

echofx( lp2 *0.6, 0.6)
	buf[ $ptr ] = echbufl[ echptrw ]
    bufr[ $ptr ] = echbufr[ echptrw ]
 
$ti +1
}	

frame()

    
}

fn ui(){    while ( get_event() ) {
		if EVT[ EVT_TYPE ] == EVT_QUIT { breakall } 
		if EVT[ EVT_TYPE ] == EVT_MOUSEBUTTONDOWN {
			$x = EVT[ EVT_X ]
			$y = EVT[ EVT_Y ]
if $y > 0 {
mode = -1
            voicyc + unis
			voicyc % voices
			note = 36 + floor(($x + xsize/2) / xsize * 36 ) 
			if note > 35 {
				$f = pow( 2, (note-69)/12 ) * 440 				
				zdep = 1- $y / hysize
				zdep = zdep * zdep
				set_oscf( voicyc, $f, zdep) 
				}
			num_to_str(pnumtext, len) 
			ptext = "processing time"
			break
	} else { 
if $y < 0 {
					
mode=floor((0.25 - 8 * $y / hysize))
if mode == 7 | mode == 6
{ 
			$rt = rt
			$rt2 = rt2
			$rtnew = floor(($x + xsize/2) / xsize * 36 ) 
			rt = $rtnew rt2 = $rt2 
			set_oscrt( rt, rt2)
			num_to_str(pnumtext, ratios[rt]) 
			ptext = "ratio 1"
			break
			}
if mode == 5 | mode == 4
{ 
			$rt = rt
			$rt2 = rt2
			$rtnew = floor(($x + xsize/2) / xsize * 36 ) 
			rt = $rt rt2 = $rtnew 
			set_oscrt( rt, rt2)
			num_to_str(pnumtext, ratios[rt2]) 
			ptext = "ratio 2"
			break
			}
if mode == 3
{		   feedback = ($x + xsize/2) / xsize
 		   feedback2 = feedback * feedback
			num_to_str(pnumtext, feedback2) 
			ptext = "feedback"
 		   break 
			}
if mode == 2
{		   attack = ($x + xsize/2) / xsize
			attack2 = 6 + 54 * attack			
			attack2 = pow(10, attack2 / 20) * 0.001
			num_to_str(pnumtext, attack2)
			attack2 = pow(M_E, - tausr/ ( 0.693147181 * attack2) )
			ptext = "attack"
			break 
			}
if mode == 1
{		   decay = ($x + xsize/2) / xsize
			decay2 = 18 + 66 * decay	
		    decay2 = pow(10, decay2 / 20) * 0.001
			num_to_str(pnumtext, decay2) 
 		   decay2 = pow(M_E, - tausr/ ( 0.693147181 * decay2) )
			ptext = "decay"
 		   break 
			}
}}
	
}
    break	
    }
ret
}

ainegil
Posts: 168
Joined: Thu Sep 22, 2022 11:37 pm

Re: organic 3D oscillator demo

Post by ainegil »

ainegil wrote: Wed Nov 02, 2022 3:27 am
No crackles

it still crackles, also there is a mistake in the dc blocker
what I put there us just a hipass filter at Hz
I fixed this filter but bevore I post a new version I want to implement some MIDI
and voice logic
ainegil
Posts: 168
Joined: Thu Sep 22, 2022 11:37 pm

Re: organic 3D oscillator demo

Post by ainegil »

Ok so, Pixilang is a fantastic tool, but nit the right platform to develop this further.

Regardless I made some progress.
So below is cross post of what I posted on kvr today:

3D Spin Oscillator ("North Coast Synthesis")

I came up with a novelish synthesis concept.

Part of and one of 3 foundations of it is a "3D Spin Oscillator".

It arranges the spin of 3 phase ramp oscillators on 3D axis
and calculates the vector of the resulting motion as projection on
one plane.
The output is the length of the vector.

The principle and resulting sound is very sinilar and much related to AM/FM.

There are some further twists to it which I wont discuss right now,
instead here is a sound demo:

Parameters on screen:

x-Spin (ratio)
y-Spin (ratio)
xyz Feedback
Radius Attack Time
Radius Decay Time
- undisclosed parameter - (needs more lengthy explanation)
z-Spin (Keyboard Pitch)



Many more sounds are possible, and there are some more things
on the drawing board, this is about 1/3 of the envisioned synthesis concept.

I am now looking for someone who is interested to help to bring this to live.

If you are capable of coding VST, and for ARM Linux platform, and if you
are willing to open source results during development
(which does not necessarily imply a free final product)
and if you have basic understanding of DSP, you may want wo contact me
for further discussion, regardless if you are freelancer or run a company.

It will help much if you basically understand my previous concept layed out here:
Real Time Pulse Convolution With Generative Impulse Responses
https://www.kvraudio.com/forum/viewtopic.php?t=581125

although the concepts are not directly related.

If you are not capable of coding the above but looking for a topic for
a research paper instead, you may also want to contact me.

I do not have budget for paid work though, in fact I dont even own a PC anymore.
Post Reply