Just started using ChucK and greatly enjoying myself. Not much music (or
even noise) as yet, just learning the language for now.
Not understanding the various `sync' options, I was setting a SinOsc's
phase explicitly and wasn't getting what I expected. On inspection of
the source there was a minor typo in CK_DLL_CTRL(osc_ctrl_phase), which
I fixed. While I was there I tidied up the range checking of input
parameters (including those used via `sync', which I now understand
*grin*), particularly so that negative frequencies are handled cleanly.
The original code contained snippets like "if( d->num <= 1.0 ) d->num +=
floor( d->num )" that can't of been doing what anyone wanted them to do.
The same sort of changes and range checking probably ought to be done
elsewhere in the code too, such as in the sndbuf ugen, but that's a job
for another day.
I'm also not convinced that the code to adjust the phase in
CK_DLL_CTRL(osc_ctrl_sync) can be correct. It certainly should only be
done if ugen->m_num_src is non-zero; but even then, I imagine pld's
comment there is correct. Again, for another day.
Attached is a diff patch against the current CVS version. I can't
imagine you'll need any form of assignment for so small a change, but
please use the attached code in anyway you want for any purpose you see
fit. It comes with no warranty, but it has been compiled and vaguely
tested on x86 Windows XP (under Cygwin) and PPC Mac OS X 10.4 (with a
recent copy of the developers tools).
Now, back to making some noise.
All the best and thanks for the great system,
Conrad
Index: ugen_osc.cpp
===================================================================
RCS file: /cvs/chuck_dev/v2/ugen_osc.cpp,v
retrieving revision 1.44
diff -c -3 -p -r1.44 ugen_osc.cpp
*** ugen_osc.cpp 22 Mar 2007 00:49:51 -0000 1.44
--- ugen_osc.cpp 8 Jul 2007 23:38:50 -0000
*************** CK_DLL_TICK( osc_tick )
*** 303,317 ****
d->freq = in;
// phase increment
d->num = d->freq / d->srate;
! // bound it
! if( d->num >= 1.0 ) d->num -= floor( d->num );
! else if( d->num <= 1.0 ) d->num += floor( d->num );
}
// synch phase to input
else if( d->sync == 1 )
{
// set phase
d->phase = in;
// no update
inc_phase = FALSE;
}
--- 303,318 ----
d->freq = in;
// phase increment
d->num = d->freq / d->srate;
! // bound it (-1 < d->num < 1)
! if( d->num <= -1 || d->num >= 1 ) d->num -= int(d->num);
}
// synch phase to input
else if( d->sync == 1 )
{
// set phase
d->phase = in;
+ // bound it (+0 <= d->phase < 1)
+ if( d->phase <= 0 || d->phase >= 1 ) d->phase -= floor( d->phase );
// no update
inc_phase = FALSE;
}
*************** CK_DLL_TICK( osc_tick )
*** 322,330 ****
t_CKFLOAT freq = d->freq + in;
// phase increment
d->num = freq / d->srate;
! // bound it
! if( d->num >= 1.0 ) d->num -= floor( d->num );
! else if( d->num <= 1.0 ) d->num += floor( d->num );
}
// sync to now
// else if( d->sync == 3 )
--- 323,330 ----
t_CKFLOAT freq = d->freq + in;
// phase increment
d->num = freq / d->srate;
! // bound it (-1 < d->num < 1)
! if( d->num <= -1 || d->num >= 1 ) d->num -= int(d->num);
}
// sync to now
// else if( d->sync == 3 )
*************** CK_DLL_TICK( osc_tick )
*** 337,349 ****
// set output to current phase
*out = (SAMPLE)d->phase;
! // check
if( inc_phase )
{
- // step the phase.
d->phase += d->num;
! // keep the phase between 0 and 1
! if( d->phase > 1.0 ) d->phase -= 1.0;
}
return TRUE;
--- 337,349 ----
// set output to current phase
*out = (SAMPLE)d->phase;
! // advance internal phase
if( inc_phase )
{
d->phase += d->num;
! // bound it (+0 <= d->phase <= 1)
! if( d->phase < 0 ) d->phase += 1;
! else if( d->phase >= 1 ) d->phase -= 1;
}
return TRUE;
*************** CK_DLL_TICK( sinosc_tick )
*** 373,387 ****
d->freq = in;
// phase increment
d->num = d->freq / d->srate;
! // bound it
! if( d->num >= 1.0 ) d->num -= floor( d->num );
! else if( d->num <= 1.0 ) d->num += floor( d->num );
}
// sync phase to input
else if( d->sync == 1 )
{
// set freq
d->phase = in;
inc_phase = FALSE;
}
// FM synthesis
--- 373,389 ----
d->freq = in;
// phase increment
d->num = d->freq / d->srate;
! // bound it (-1 < d->num < 1)
! if( d->num <= -1 || d->num >= 1 ) d->num -= int(d->num);
}
// sync phase to input
else if( d->sync == 1 )
{
// set freq
d->phase = in;
+ // bound it (+0 <= d->phase < 1)
+ if( d->phase <= 0 || d->phase >= 1 ) d->phase -= floor( d->phase );
+ // no update
inc_phase = FALSE;
}
// FM synthesis
*************** CK_DLL_TICK( sinosc_tick )
*** 391,399 ****
t_CKFLOAT freq = d->freq + in;
// phase increment
d->num = freq / d->srate;
! // bound it
! if( d->num >= 1.0 ) d->num -= floor( d->num );
! else if( d->num <= 1.0 ) d->num += floor( d->num );
}
// sync phase to now
// else if( d->sync == 3 )
--- 393,400 ----
t_CKFLOAT freq = d->freq + in;
// phase increment
d->num = freq / d->srate;
! // bound it (-1 < d->num < 1)
! if( d->num <= -1 || d->num >= 1 ) d->num -= int(d->num);
}
// sync phase to now
// else if( d->sync == 3 )
*************** CK_DLL_TICK( sinosc_tick )
*** 406,417 ****
// set output
*out = (SAMPLE) ::sin( d->phase * TWO_PI );
if( inc_phase )
{
- // next phase
d->phase += d->num;
! // keep the phase between 0 and 1
! if( d->phase > 1.0 ) d->phase -= 1.0;
}
return TRUE;
--- 407,419 ----
// set output
*out = (SAMPLE) ::sin( d->phase * TWO_PI );
+ // advance internal phase
if( inc_phase )
{
d->phase += d->num;
! // bound it (+0 <= d->phase <= 1)
! if( d->phase < 0 ) d->phase += 1;
! else if( d->phase >= 1 ) d->phase -= 1;
}
return TRUE;
*************** CK_DLL_TICK( triosc_tick )
*** 441,455 ****
d->freq = in;
// phase increment
d->num = d->freq / d->srate;
! // bound it
! if( d->num >= 1.0 ) d->num -= floor( d->num );
! else if( d->num <= 1.0 ) d->num += floor( d->num );
}
// sync phase to input
else if( d->sync == 1 )
{
// set freq
d->phase = in;
inc_phase = FALSE;
}
// FM synthesis
--- 443,459 ----
d->freq = in;
// phase increment
d->num = d->freq / d->srate;
! // bound it (-1 < d->num < 1)
! if( d->num <= -1 || d->num >= 1 ) d->num -= int(d->num);
}
// sync phase to input
else if( d->sync == 1 )
{
// set freq
d->phase = in;
+ // bound it (+0 <= d->phase < 1)
+ if( d->phase <= 0 || d->phase >= 1 ) d->phase -= floor( d->phase );
+ // no update
inc_phase = FALSE;
}
// FM synthesis
*************** CK_DLL_TICK( triosc_tick )
*** 459,467 ****
t_CKFLOAT freq = d->freq + in;
// phase increment
d->num = freq / d->srate;
! // bound it
! if( d->num >= 1.0 ) d->num -= floor( d->num );
! else if( d->num <= 1.0 ) d->num += floor( d->num );
}
// sync to now
// if( d->sync == 3 )
--- 463,470 ----
t_CKFLOAT freq = d->freq + in;
// phase increment
d->num = freq / d->srate;
! // bound it (-1 < d->num < 1)
! if( d->num <= -1 || d->num >= 1 ) d->num -= int(d->num);
}
// sync to now
// if( d->sync == 3 )
*************** CK_DLL_TICK( triosc_tick )
*** 480,487 ****
if( inc_phase )
{
d->phase += d->num;
! // keep the phase between 0 and 1
! if( d->phase > 1.0 ) d->phase -= 1.0;
}
return TRUE;
--- 483,491 ----
if( inc_phase )
{
d->phase += d->num;
! // bound it (+0 <= d->phase <= 1)
! if( d->phase < 0 ) d->phase += 1;
! else if( d->phase >= 1 ) d->phase -= 1;
}
return TRUE;
*************** CK_DLL_TICK( pulseosc_tick )
*** 512,526 ****
d->freq = in;
// phase increment
d->num = d->freq / d->srate;
! // bound it
! if( d->num >= 1.0 ) d->num -= floor( d->num );
! else if( d->num <= 1.0 ) d->num += floor( d->num );
}
// sync phase to input
else if( d->sync == 1 )
{
// set freq
d->phase = in;
inc_phase = FALSE;
}
// FM synthesis
--- 516,532 ----
d->freq = in;
// phase increment
d->num = d->freq / d->srate;
! // bound it (-1 < d->num < 1)
! if( d->num <= -1 || d->num >= 1 ) d->num -= int(d->num);
}
// sync phase to input
else if( d->sync == 1 )
{
// set freq
d->phase = in;
+ // bound it (+0 <= d->phase < 1)
+ if( d->phase <= 0 || d->phase >= 1 ) d->phase -= floor( d->phase );
+ // no update
inc_phase = FALSE;
}
// FM synthesis
*************** CK_DLL_TICK( pulseosc_tick )
*** 530,538 ****
t_CKFLOAT freq = d->freq + in;
// phase increment
d->num = freq / d->srate;
! // bound it
! if( d->num >= 1.0 ) d->num -= floor( d->num );
! else if( d->num <= 1.0 ) d->num += floor( d->num );
}
// sync to now
// if( d->sync == 3 )
--- 536,543 ----
t_CKFLOAT freq = d->freq + in;
// phase increment
d->num = freq / d->srate;
! // bound it (-1 < d->num < 1)
! if( d->num <= -1 || d->num >= 1 ) d->num -= int(d->num);
}
// sync to now
// if( d->sync == 3 )
*************** CK_DLL_TICK( pulseosc_tick )
*** 545,556 ****
// compute
*out = (SAMPLE) (d->phase < d->width) ? 1.0 : -1.0;
! // move phase
if( inc_phase )
{
d->phase += d->num;
! // keep the phase between 0 and 1
! if( d->phase > 1.0 ) d->phase -= 1.0;
}
return TRUE;
--- 550,562 ----
// compute
*out = (SAMPLE) (d->phase < d->width) ? 1.0 : -1.0;
! // advance internal phase
if( inc_phase )
{
d->phase += d->num;
! // bound it (+0 <= d->phase <= 1)
! if( d->phase < 0 ) d->phase += 1;
! else if( d->phase >= 1 ) d->phase -= 1;
}
return TRUE;
*************** CK_DLL_CTRL( osc_ctrl_freq )
*** 572,579 ****
d->freq = GET_CK_FLOAT(ARGS);
// phase increment
d->num = d->freq / d->srate;
! // bound it
! if( d->num >= 1.0 ) d->num -= ::floor( d->num );
// return
RETURN->v_float = (t_CKFLOAT)d->freq;
}
--- 578,585 ----
d->freq = GET_CK_FLOAT(ARGS);
// phase increment
d->num = d->freq / d->srate;
! // bound it (-1 < d->num < 1)
! if( d->num <= -1 || d->num >= 1 ) d->num -= int(d->num);
// return
RETURN->v_float = (t_CKFLOAT)d->freq;
}
*************** CK_DLL_CTRL( osc_ctrl_period )
*** 610,617 ****
// set freq
else d->freq = 1 / (period / d->srate);
d->num = d->freq / d->srate;
! // bound it
! if( d->num >= 1.0 ) d->num -= ::floor( d->num );
// return
RETURN->v_dur = period;
}
--- 616,623 ----
// set freq
else d->freq = 1 / (period / d->srate);
d->num = d->freq / d->srate;
! // bound it (-1 < d->num < 1)
! if( d->num <= -1 || d->num >= 1 ) d->num -= int(d->num);
// return
RETURN->v_dur = period;
}
*************** CK_DLL_CTRL( osc_ctrl_phase )
*** 649,656 ****
Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data );
// set freq
d->phase = GET_CK_FLOAT(ARGS);
! //bound ( this could be set arbitrarily high or low )
! if ( d->phase >= 1.0 || d->phase < 0.0 ) d->phase -= floor( d->num );
// return
RETURN->v_float = (t_CKFLOAT)d->phase;
}
--- 655,662 ----
Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data );
// set freq
d->phase = GET_CK_FLOAT(ARGS);
! // bound it (+0 <= d->phase < 1)
! if( d->phase <= 0 || d->phase >= 1 ) d->phase -= floor( d->phase );
// return
RETURN->v_float = (t_CKFLOAT)d->phase;
}
*************** CK_DLL_CTRL( osc_ctrl_width )
*** 683,689 ****
Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data );
// set freq
d->width = GET_CK_FLOAT(ARGS);
! //bound ( this could be set arbitrarily high or low )
d->width = ck_max( 0.0, ck_min( 1.0, d->width ) );
// return
RETURN->v_float = (t_CKFLOAT)d->width;
--- 689,695 ----
Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data );
// set freq
d->width = GET_CK_FLOAT(ARGS);
! // bound ( this could be set arbitrarily high or low )
d->width = ck_max( 0.0, ck_min( 1.0, d->width ) );
// return
RETURN->v_float = (t_CKFLOAT)d->width;
*************** CK_DLL_CTRL( sawosc_ctrl_width )
*** 762,768 ****
Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data );
// set freq
d->width = GET_CK_FLOAT(ARGS);
! //bound ( this could be set arbitrarily high or low )
d->width = ( d->width < 0.5 ) ? 0.0 : 1.0; //rising or falling
// return
RETURN->v_float = (t_CKFLOAT)d->width;
--- 768,774 ----
Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data );
// set freq
d->width = GET_CK_FLOAT(ARGS);
! // bound ( this could be set arbitrarily high or low )
d->width = ( d->width < 0.5 ) ? 0.0 : 1.0; //rising or falling
// return
RETURN->v_float = (t_CKFLOAT)d->width;
*************** CK_DLL_CTRL( osc_ctrl_sync )
*** 793,800 ****
// we need to pre-advance the phase...
// this is probably stupid. -pld
d->phase += d->num;
! // keep the phase between 0 and 1
! if( d->phase > 1.0 ) d->phase -= 1.0;
}
// return
RETURN->v_int = (t_CKINT)d->sync;
--- 799,807 ----
// we need to pre-advance the phase...
// this is probably stupid. -pld
d->phase += d->num;
! // bound it (0 <= phase < 1)
! if( d->phase < 0 ) d->phase += 1;
! else if( d->phase >= 1 ) d->phase -= 1;
}
// return
RETURN->v_int = (t_CKINT)d->sync;