1 /*----------------------------------------------------------------------------
2 ChucK Concurrent, On-the-fly Audio Programming Language
3 Compiler and Virtual Machine
5 Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6 http://chuck.cs.princeton.edu/
7 http://soundlab.cs.princeton.edu/
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
31 // Philip L. Davidson (philipd@alumni.princeton.edu)
33 //-----------------------------------------------------------------------------
35 #include "chuck_type.h"
36 #include "chuck_ugen.h"
40 static t_CKUINT g_srate
= 0;
41 // for member data offset
42 static t_CKUINT osc_offset_data
= 0;
45 //-----------------------------------------------------------------------------
48 //-----------------------------------------------------------------------------
49 DLL_QUERY
osc_query( Chuck_DL_Query
* QUERY
)
52 g_srate
= QUERY
->srate
;
54 Chuck_Env
* env
= Chuck_Env::instance();
56 Chuck_DL_Func
* func
= NULL
;
59 type_engine_register_deprecate( env
, "osc", "Osc" );
60 type_engine_register_deprecate( env
, "phasor", "Phasor" );
61 type_engine_register_deprecate( env
, "sinosc", "SinOsc" );
62 type_engine_register_deprecate( env
, "triosc", "TriOsc" );
63 type_engine_register_deprecate( env
, "sawosc", "SawOsc" );
64 type_engine_register_deprecate( env
, "pulseosc", "PulseOsc" );
65 type_engine_register_deprecate( env
, "sqrosc", "SqrOsc" );
67 //---------------------------------------------------------------------
68 // init as base class: osc
69 //---------------------------------------------------------------------
70 if( !type_engine_import_ugen_begin( env
, "Osc", "UGen", env
->global(),
71 osc_ctor
, osc_dtor
, osc_tick
, osc_pmsg
) )
74 // add member variable
75 osc_offset_data
= type_engine_import_mvar( env
, "int", "@osc_data", FALSE
);
76 if( osc_offset_data
== CK_INVALID_OFFSET
) goto error
;
79 func
= make_new_mfun( "float", "freq", osc_ctrl_freq
);
80 func
->add_arg( "float", "hz" );
81 if( !type_engine_import_mfun( env
, func
) ) goto error
;
82 func
= make_new_mfun( "float", "freq", osc_cget_freq
);
83 if( !type_engine_import_mfun( env
, func
) ) goto error
;
86 func
= make_new_mfun( "dur", "period", osc_ctrl_period
);
87 func
->add_arg( "dur", "value" );
88 if( !type_engine_import_mfun( env
, func
) ) goto error
;
89 func
= make_new_mfun( "dur", "period", osc_cget_period
);
90 if( !type_engine_import_mfun( env
, func
) ) goto error
;
92 // add ctrl: sfreq ( == freq )
93 func
= make_new_mfun( "float", "sfreq", osc_ctrl_freq
);
94 func
->add_arg( "float", "hz" );
95 if( !type_engine_import_mfun( env
, func
) ) goto error
;
98 func
= make_new_mfun( "float", "phase", osc_ctrl_phase
);
99 func
->add_arg( "float", "phase" );
100 if( !type_engine_import_mfun( env
, func
) ) goto error
;
101 func
= make_new_mfun( "float", "phase", osc_cget_phase
);
102 if( !type_engine_import_mfun( env
, func
) ) goto error
;
105 func
= make_new_mfun( "int", "sync", osc_ctrl_sync
);
106 func
->add_arg( "int", "type" );
107 if( !type_engine_import_mfun( env
, func
) ) goto error
;
108 func
= make_new_mfun( "int", "sync", osc_cget_sync
);
109 if( !type_engine_import_mfun( env
, func
) ) goto error
;
111 // end the class import
112 type_engine_import_class_end( env
);
115 //---------------------------------------------------------------------
117 //---------------------------------------------------------------------
118 if( !type_engine_import_ugen_begin( env
, "Phasor", "Osc", env
->global(),
119 NULL
, NULL
, osc_tick
, NULL
) )
122 // end the class import
123 type_engine_import_class_end( env
);
125 //---------------------------------------------------------------------
127 //---------------------------------------------------------------------
128 if( !type_engine_import_ugen_begin( env
, "SinOsc", "Osc", env
->global(),
129 NULL
, NULL
, sinosc_tick
, NULL
) )
132 // end the class import
133 type_engine_import_class_end( env
);
136 //---------------------------------------------------------------------
137 // triosc - triangle oscillator
138 //---------------------------------------------------------------------
139 if( !type_engine_import_ugen_begin( env
, "TriOsc", "Osc", env
->global(),
140 NULL
, NULL
, triosc_tick
, NULL
) )
143 func
= make_new_mfun( "float", "width", osc_ctrl_width
);
144 func
->add_arg( "float", "width" );
145 if( !type_engine_import_mfun( env
, func
) ) goto error
;
147 // end the class import
148 type_engine_import_class_end( env
);
151 //---------------------------------------------------------------------
152 // sawosc - sawtooth oscillator ( 0 | 1 triangle wave )
153 //---------------------------------------------------------------------
154 if( !type_engine_import_ugen_begin( env
, "SawOsc", "TriOsc", env
->global(),
155 sawosc_ctor
, NULL
, NULL
, NULL
) )
158 func
= make_new_mfun( "float", "width", sawosc_ctrl_width
);
159 func
->add_arg( "float", "width" );
160 if( !type_engine_import_mfun( env
, func
) ) goto error
;
162 // end the class import
163 type_engine_import_class_end( env
);
166 //---------------------------------------------------------------------
167 // pulseosc - pulse-width oscillator
168 //---------------------------------------------------------------------
169 if( !type_engine_import_ugen_begin( env
, "PulseOsc", "Osc", env
->global(),
170 NULL
, NULL
, pulseosc_tick
, NULL
) )
173 func
= make_new_mfun( "float", "width", osc_ctrl_width
);
174 func
->add_arg( "float", "width" );
175 if( !type_engine_import_mfun( env
, func
) ) goto error
;
177 // end the class import
178 type_engine_import_class_end( env
);
181 //---------------------------------------------------------------------
182 // sqrosc - square_wave oscillator ( 0.5 pulse )
183 //---------------------------------------------------------------------
184 if( !type_engine_import_ugen_begin( env
, "SqrOsc", "PulseOsc", env
->global(),
185 sqrosc_ctor
, NULL
, NULL
, NULL
) )
188 func
= make_new_mfun( "float", "width", sqrosc_ctrl_width
);
189 func
->add_arg( "float", "width" );
190 if( !type_engine_import_mfun( env
, func
) ) goto error
;
192 // end the class import
193 type_engine_import_class_end( env
);
196 if( !genX_query( QUERY
) )
203 // end the class import
204 type_engine_import_class_end( env
);
212 //-----------------------------------------------------------------------------
213 // name: struct Osc_Data
215 //-----------------------------------------------------------------------------
230 sync
= 0; // internal
240 //-----------------------------------------------------------------------------
243 //-----------------------------------------------------------------------------
244 CK_DLL_CTOR( osc_ctor
)
246 Osc_Data
* d
= new Osc_Data
;
248 // return data to be used later
249 OBJ_MEMBER_UINT(SELF
, osc_offset_data
) = (t_CKUINT
)d
;
250 osc_ctrl_freq( SELF
, &(d
->freq
), &r
, SHRED
);
256 //-----------------------------------------------------------------------------
259 //-----------------------------------------------------------------------------
260 CK_DLL_DTOR( osc_dtor
)
263 Osc_Data
* data
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
267 OBJ_MEMBER_UINT(SELF
, osc_offset_data
) = 0;
273 //-----------------------------------------------------------------------------
277 // basic osx is a phasor...
278 // we use a duty-cycle rep ( 0 - 1 ) rather than angular ( 0 - TWOPI )
279 // sinusoidal oscillators are special
281 // (maybe) as a rule, we store external phase control values
282 // so that we can have a smooth change back to internal control -pld
284 // technically this should happen even with external phase control
285 // that we'd be in the right place when translating back to internal...
286 // this was decidely inefficient and nit-picky. -pld
288 //-----------------------------------------------------------------------------
289 CK_DLL_TICK( osc_tick
)
292 Osc_Data
* d
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
293 Chuck_UGen
* ugen
= (Chuck_UGen
*)SELF
;
294 t_CKBOOL inc_phase
= TRUE
;
297 if( ugen
->m_num_src
)
299 // sync frequency to input
305 d
->num
= d
->freq
/ d
->srate
;
307 if( d
->num
>= 1.0 ) d
->num
-= floor( d
->num
);
308 else if( d
->num
<= 1.0 ) d
->num
+= floor( d
->num
);
310 // synch phase to input
311 else if( d
->sync
== 1 )
319 else if( d
->sync
== 2 )
322 t_CKFLOAT freq
= d
->freq
+ in
;
324 d
->num
= freq
/ d
->srate
;
326 if( d
->num
>= 1.0 ) d
->num
-= floor( d
->num
);
327 else if( d
->num
<= 1.0 ) d
->num
+= floor( d
->num
);
330 // else if( d->sync == 3 )
332 // d->phase = now * d->num;
333 // inc_phase = FALSE;
337 // set output to current phase
338 *out
= (SAMPLE
)d
->phase
;
345 // keep the phase between 0 and 1
346 if( d
->phase
> 1.0 ) d
->phase
-= 1.0;
355 //-----------------------------------------------------------------------------
356 // name: sinosc_tick()
358 //-----------------------------------------------------------------------------
359 CK_DLL_TICK( sinosc_tick
)
362 Osc_Data
* d
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
363 Chuck_UGen
* ugen
= (Chuck_UGen
*)SELF
;
364 t_CKBOOL inc_phase
= TRUE
;
367 if( ugen
->m_num_src
)
369 // sync frequency to input
375 d
->num
= d
->freq
/ d
->srate
;
377 if( d
->num
>= 1.0 ) d
->num
-= floor( d
->num
);
378 else if( d
->num
<= 1.0 ) d
->num
+= floor( d
->num
);
380 // sync phase to input
381 else if( d
->sync
== 1 )
388 else if( d
->sync
== 2 )
391 t_CKFLOAT freq
= d
->freq
+ in
;
393 d
->num
= freq
/ d
->srate
;
395 if( d
->num
>= 1.0 ) d
->num
-= floor( d
->num
);
396 else if( d
->num
<= 1.0 ) d
->num
+= floor( d
->num
);
399 // else if( d->sync == 3 )
401 // d->phase = now * d->num;
402 // inc_phase = FALSE;
407 *out
= (SAMPLE
) ::sin( d
->phase
* TWO_PI
);
413 // keep the phase between 0 and 1
414 if( d
->phase
> 1.0 ) d
->phase
-= 1.0;
423 //-----------------------------------------------------------------------------
424 // name: triosc_tick()
426 //-----------------------------------------------------------------------------
427 CK_DLL_TICK( triosc_tick
)
430 Osc_Data
* d
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
431 Chuck_UGen
* ugen
= (Chuck_UGen
*)SELF
;
432 t_CKBOOL inc_phase
= TRUE
;
435 if( ugen
->m_num_src
)
437 // sync frequency to input
443 d
->num
= d
->freq
/ d
->srate
;
445 if( d
->num
>= 1.0 ) d
->num
-= floor( d
->num
);
446 else if( d
->num
<= 1.0 ) d
->num
+= floor( d
->num
);
448 // sync phase to input
449 else if( d
->sync
== 1 )
456 else if( d
->sync
== 2 )
459 t_CKFLOAT freq
= d
->freq
+ in
;
461 d
->num
= freq
/ d
->srate
;
463 if( d
->num
>= 1.0 ) d
->num
-= floor( d
->num
);
464 else if( d
->num
<= 1.0 ) d
->num
+= floor( d
->num
);
467 // if( d->sync == 3 )
469 // d->phase = now * d->num;
470 // inc_phase = FALSE;
475 t_CKFLOAT phase
= d
->phase
+ .25; if( phase
> 1.0 ) phase
-= 1.0;
476 if( phase
< d
->width
) *out
= (SAMPLE
) (d
->width
== 0.0) ? 1.0 : -1.0 + 2.0 * phase
/ d
->width
;
477 else *out
= (SAMPLE
) (d
->width
== 1.0) ? 0 : 1.0 - 2.0 * (phase
- d
->width
) / (1.0 - d
->width
);
479 // advance internal phase
483 // keep the phase between 0 and 1
484 if( d
->phase
> 1.0 ) d
->phase
-= 1.0;
491 // sawosc_tick is tri_osc tick with width=0.0 or width=1.0 -pld
494 //-----------------------------------------------------------------------------
495 // name: pulseosc_tick()
497 //-----------------------------------------------------------------------------
498 CK_DLL_TICK( pulseosc_tick
)
501 Osc_Data
* d
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
502 Chuck_UGen
* ugen
= (Chuck_UGen
*)SELF
;
503 t_CKBOOL inc_phase
= TRUE
;
506 if( ugen
->m_num_src
)
508 // sync frequency to input
514 d
->num
= d
->freq
/ d
->srate
;
516 if( d
->num
>= 1.0 ) d
->num
-= floor( d
->num
);
517 else if( d
->num
<= 1.0 ) d
->num
+= floor( d
->num
);
519 // sync phase to input
520 else if( d
->sync
== 1 )
527 else if( d
->sync
== 2 )
530 t_CKFLOAT freq
= d
->freq
+ in
;
532 d
->num
= freq
/ d
->srate
;
534 if( d
->num
>= 1.0 ) d
->num
-= floor( d
->num
);
535 else if( d
->num
<= 1.0 ) d
->num
+= floor( d
->num
);
538 // if( d->sync == 3 )
540 // d->phase = now * d->num;
541 // inc_phase = FALSE;
546 *out
= (SAMPLE
) (d
->phase
< d
->width
) ? 1.0 : -1.0;
552 // keep the phase between 0 and 1
553 if( d
->phase
> 1.0 ) d
->phase
-= 1.0;
560 // sqrosc_tick is pulseosc_tick at width=0.5 -pld;
563 //-----------------------------------------------------------------------------
564 // name: osc_ctrl_freq()
565 // desc: set oscillator frequency
566 //-----------------------------------------------------------------------------
567 CK_DLL_CTRL( osc_ctrl_freq
)
570 Osc_Data
* d
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
572 d
->freq
= GET_CK_FLOAT(ARGS
);
574 d
->num
= d
->freq
/ d
->srate
;
576 if( d
->num
>= 1.0 ) d
->num
-= ::floor( d
->num
);
578 RETURN
->v_float
= (t_CKFLOAT
)d
->freq
;
584 //-----------------------------------------------------------------------------
585 // name: osc_cget_freq()
586 // desc: get oscillator frequency
587 //-----------------------------------------------------------------------------
588 CK_DLL_CGET( osc_cget_freq
)
591 Osc_Data
* d
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
593 RETURN
->v_float
= (t_CKFLOAT
)d
->freq
;
599 //-----------------------------------------------------------------------------
600 // name: osc_ctrl_period()
601 // desc: set oscillator period
602 //-----------------------------------------------------------------------------
603 CK_DLL_CTRL( osc_ctrl_period
)
606 Osc_Data
* d
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
607 t_CKDUR period
= GET_CK_DUR(ARGS
);
609 if( period
== 0.0 ) d
->freq
= 0.0;
611 else d
->freq
= 1 / (period
/ d
->srate
);
612 d
->num
= d
->freq
/ d
->srate
;
614 if( d
->num
>= 1.0 ) d
->num
-= ::floor( d
->num
);
616 RETURN
->v_dur
= period
;
622 //-----------------------------------------------------------------------------
623 // name: osc_cget_period()
624 // desc: get oscillator period
625 //-----------------------------------------------------------------------------
626 CK_DLL_CGET( osc_cget_period
)
629 Osc_Data
* d
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
633 if( d
->freq
!= 0.0 ) period
= 1 / d
->freq
* d
->srate
;
636 RETURN
->v_dur
= period
;
642 //-----------------------------------------------------------------------------
643 // name: osc_ctrl_phase()
644 // desc: set oscillator phase wrapped to ( 0 - 1 )
645 //-----------------------------------------------------------------------------
646 CK_DLL_CTRL( osc_ctrl_phase
)
649 Osc_Data
* d
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
651 d
->phase
= GET_CK_FLOAT(ARGS
);
652 //bound ( this could be set arbitrarily high or low )
653 if ( d
->phase
>= 1.0 || d
->phase
< 0.0 ) d
->phase
-= floor( d
->num
);
655 RETURN
->v_float
= (t_CKFLOAT
)d
->phase
;
661 //-----------------------------------------------------------------------------
662 // name: osc_cget_phase()
663 // desc: get oscillator phase wrapped to ( 0 - 1 )
664 //-----------------------------------------------------------------------------
665 CK_DLL_CGET( osc_cget_phase
)
668 Osc_Data
* d
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
670 RETURN
->v_float
= (t_CKFLOAT
)d
->phase
;
676 //-----------------------------------------------------------------------------
677 // name: osc_ctrl_width()
678 // desc: set width of active phase ( bound 0.0 - 1.0 );
679 //-----------------------------------------------------------------------------
680 CK_DLL_CTRL( osc_ctrl_width
)
683 Osc_Data
* d
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
685 d
->width
= GET_CK_FLOAT(ARGS
);
686 //bound ( this could be set arbitrarily high or low )
687 d
->width
= ck_max( 0.0, ck_min( 1.0, d
->width
) );
689 RETURN
->v_float
= (t_CKFLOAT
)d
->width
;
695 //-----------------------------------------------------------------------------
696 // name: osc_cget_width()
697 // desc: get width of active phase ( bound 0.0 - 1.0 );
698 //-----------------------------------------------------------------------------
699 CK_DLL_CGET( osc_cget_width
)
702 Osc_Data
* d
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
704 RETURN
->v_float
= (t_CKFLOAT
)d
->width
;
710 //-----------------------------------------------------------------------------
711 // name: sqrosc_ctor()
713 //-----------------------------------------------------------------------------
714 CK_DLL_CTOR( sqrosc_ctor
)
716 Osc_Data
* d
= new Osc_Data
;
718 sqrosc_ctrl_width( SELF
, &(d
->width
), &r
, SHRED
);
724 //-----------------------------------------------------------------------------
725 // name: sqrosc_ctrl_width()
726 // desc: force width to 0.5;
727 //-----------------------------------------------------------------------------
728 CK_DLL_CTRL( sqrosc_ctrl_width
)
731 Osc_Data
* d
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
735 RETURN
->v_float
= (t_CKFLOAT
)d
->width
;
741 //-----------------------------------------------------------------------------
742 // name: sawosc_ctor()
744 //-----------------------------------------------------------------------------
745 CK_DLL_CTOR( sawosc_ctor
)
747 Osc_Data
* d
= new Osc_Data
;
749 sawosc_ctrl_width( SELF
, &(d
->width
), &r
, SHRED
);
755 //-----------------------------------------------------------------------------
756 // name: sawosc_ctrl_width()
757 // force width to 0.0 ( falling ) or 1.0 ( rising )
758 //-----------------------------------------------------------------------------
759 CK_DLL_CTRL( sawosc_ctrl_width
)
762 Osc_Data
* d
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
764 d
->width
= GET_CK_FLOAT(ARGS
);
765 //bound ( this could be set arbitrarily high or low )
766 d
->width
= ( d
->width
< 0.5 ) ? 0.0 : 1.0; //rising or falling
768 RETURN
->v_float
= (t_CKFLOAT
)d
->width
;
774 //-----------------------------------------------------------------------------
775 // name: osc_ctrl_sync()
776 // desc: select sync mode for oscillator
777 //-----------------------------------------------------------------------------
778 CK_DLL_CTRL( osc_ctrl_sync
)
781 Osc_Data
* d
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
783 t_CKINT psync
= d
->sync
;
784 d
->sync
= GET_CK_INT(ARGS
);
786 // bound ( this could be set arbitrarily high or low )
787 if( d
->sync
< 0 || d
->sync
> 2 )
790 if( d
->sync
== 0 && psync
!= d
->sync
)
792 // if we are switching to internal tick
793 // we need to pre-advance the phase...
794 // this is probably stupid. -pld
796 // keep the phase between 0 and 1
797 if( d
->phase
> 1.0 ) d
->phase
-= 1.0;
800 RETURN
->v_int
= (t_CKINT
)d
->sync
;
806 //-----------------------------------------------------------------------------
807 // name: osc_cget_sync()
808 // desc: get sync mode for oscillator
809 //-----------------------------------------------------------------------------
810 CK_DLL_CGET( osc_cget_sync
)
813 Osc_Data
* d
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
815 RETURN
->v_int
= (t_CKINT
)d
->sync
;
821 //-----------------------------------------------------------------------------
824 //-----------------------------------------------------------------------------
825 CK_DLL_PMSG( osc_pmsg
)
827 Osc_Data
* d
= (Osc_Data
*)OBJ_MEMBER_UINT(SELF
, osc_offset_data
);
828 if( !strcmp( MSG
, "print" ) )
830 fprintf( stdout
, "SinOsc: (freq=%f)", d
->freq
);
841 //-----------------------------------------------------------------------------
842 // file: ugen_genX.cpp
843 // desc: thought it would be a good way to learn the fascinating innards of
844 // ChucK by porting some of the classic lookup table functions and adding
845 // a few new ones that might be of use.
846 // mostly ported from RTcmix (all by WarpTable)
848 // author: Dan Trueman (dtrueman.princeton.edu)
850 //-----------------------------------------------------------------------------
851 // for member data offset
852 static t_CKUINT genX_offset_data
= 0;
853 // for internal usage
854 static void _transition( t_CKDOUBLE a
, t_CKDOUBLE alpha
, t_CKDOUBLE b
,
855 t_CKINT n
, t_CKDOUBLE
* output
);
859 //-----------------------------------------------------------------------------
860 // name: genX_query()
862 //-----------------------------------------------------------------------------
863 DLL_QUERY
genX_query( Chuck_DL_Query
* QUERY
)
866 g_srate
= QUERY
->srate
;
868 Chuck_Env
* env
= Chuck_Env::instance();
870 Chuck_DL_Func
* func
= NULL
;
872 //---------------------------------------------------------------------
873 // init as base class: genX
874 //---------------------------------------------------------------------
875 if( !type_engine_import_ugen_begin( env
, "GenX", "UGen", env
->global(),
876 genX_ctor
, genX_dtor
, genX_tick
, genX_pmsg
) )
879 // add member variable
880 genX_offset_data
= type_engine_import_mvar( env
, "int", "@GenX_data", FALSE
);
881 if( genX_offset_data
== CK_INVALID_OFFSET
) goto error
;
883 func
= make_new_mfun( "float", "lookup", genX_lookup
); //lookup table value
884 func
->add_arg( "float", "which" );
885 if( !type_engine_import_mfun( env
, func
) ) goto error
;
887 func
= make_new_mfun( "float[]", "coefs", genX_coeffs
); //load table
888 func
->add_arg( "float", "v[]" );
889 if( !type_engine_import_mfun( env
, func
) ) goto error
;
891 // end the class import
892 type_engine_import_class_end( env
);
895 //---------------------------------------------------------------------
897 //---------------------------------------------------------------------
898 if( !type_engine_import_ugen_begin( env
, "Gen5", "GenX", env
->global(),
899 NULL
, NULL
, genX_tick
, NULL
) )
902 func
= make_new_mfun( "float[]", "coefs", gen5_coeffs
); //load table
903 func
->add_arg( "float", "v[]" );
904 if( !type_engine_import_mfun( env
, func
) ) goto error
;
906 // end the class import
907 type_engine_import_class_end( env
);
911 //---------------------------------------------------------------------
913 //---------------------------------------------------------------------
914 if( !type_engine_import_ugen_begin( env
, "Gen7", "GenX", env
->global(),
915 NULL
, NULL
, genX_tick
, NULL
) )
918 func
= make_new_mfun( "float[]", "coefs", gen7_coeffs
); //load table
919 func
->add_arg( "float", "v[]" );
920 if( !type_engine_import_mfun( env
, func
) ) goto error
;
922 // end the class import
923 type_engine_import_class_end( env
);
926 //---------------------------------------------------------------------
928 //---------------------------------------------------------------------
929 if( !type_engine_import_ugen_begin( env
, "Gen9", "GenX", env
->global(),
930 NULL
, NULL
, genX_tick
, NULL
) )
933 func
= make_new_mfun( "float[]", "coefs", gen9_coeffs
); //load table
934 func
->add_arg( "float", "v[]" );
935 if( !type_engine_import_mfun( env
, func
) ) goto error
;
937 // end the class import
938 type_engine_import_class_end( env
);
942 //---------------------------------------------------------------------
944 //---------------------------------------------------------------------
945 if( !type_engine_import_ugen_begin( env
, "Gen10", "GenX", env
->global(),
946 NULL
, NULL
, genX_tick
, NULL
) )
949 func
= make_new_mfun( "float[]", "coefs", gen10_coeffs
); //load table
950 func
->add_arg( "float", "v[]" );
951 if( !type_engine_import_mfun( env
, func
) ) goto error
;
953 // end the class import
954 type_engine_import_class_end( env
);
957 //---------------------------------------------------------------------
959 //---------------------------------------------------------------------
960 if( !type_engine_import_ugen_begin( env
, "Gen17", "GenX", env
->global(),
961 NULL
, NULL
, genX_tick
, NULL
) )
964 func
= make_new_mfun( "float[]", "coefs", gen17_coeffs
); //load table
965 func
->add_arg( "float", "v[]" );
966 if( !type_engine_import_mfun( env
, func
) ) goto error
;
968 // end the class import
969 type_engine_import_class_end( env
);
971 //---------------------------------------------------------------------
973 //---------------------------------------------------------------------
974 if( !type_engine_import_ugen_begin( env
, "CurveTable", "GenX", env
->global(),
975 NULL
, NULL
, genX_tick
, NULL
) )
978 func
= make_new_mfun( "float[]", "coefs", curve_coeffs
); //load table
979 func
->add_arg( "float", "v[]" );
980 if( !type_engine_import_mfun( env
, func
) ) goto error
;
982 // end the class import
983 type_engine_import_class_end( env
);
985 //---------------------------------------------------------------------
987 //---------------------------------------------------------------------
988 if( !type_engine_import_ugen_begin( env
, "WarpTable", "GenX", env
->global(),
989 NULL
, NULL
, genX_tick
, NULL
) )
992 func
= make_new_mfun( "float[]", "coefs", warp_coeffs
); //load table
993 func
->add_arg( "float", "v[]" );
994 if( !type_engine_import_mfun( env
, func
) ) goto error
;
997 func = make_new_mfun( "float", "coefs", warp_coeffs ); //load table
998 func->add_arg( "float", "asym" );
999 func->add_arg( "float", "sym" );
1000 if( !type_engine_import_mfun( env, func ) ) goto error;
1003 // end the class import
1004 type_engine_import_class_end( env
);
1011 // end the class import
1012 type_engine_import_class_end( env
);
1020 //-----------------------------------------------------------------------------
1021 // name: struct genX_Data
1023 //-----------------------------------------------------------------------------
1024 #define genX_tableSize 4096
1025 #define genX_MAX_COEFFS 100
1030 t_CKDOUBLE genX_table
[genX_tableSize
];
1035 t_CKDOUBLE coeffs
[genX_MAX_COEFFS
];
1039 //initialize data here
1044 for( i
=0; i
<genX_MAX_COEFFS
; i
++ ) coeffs
[i
] = 0.;
1045 for( i
=0; i
<genX_tableSize
; i
++ ) genX_table
[i
] = 0.;
1052 //-----------------------------------------------------------------------------
1053 // name: genX_ctor()
1055 //-----------------------------------------------------------------------------
1056 CK_DLL_CTOR( genX_ctor
)
1058 genX_Data
* d
= new genX_Data
;
1060 // return data to be used later
1061 OBJ_MEMBER_UINT(SELF
, genX_offset_data
) = (t_CKUINT
)d
;
1062 //gen10_coeffs( SELF, &(d->xtemp), &r );
1068 //-----------------------------------------------------------------------------
1069 // name: genX_dtor()
1071 //-----------------------------------------------------------------------------
1072 CK_DLL_DTOR( genX_dtor
)
1075 genX_Data
* data
= (genX_Data
*)OBJ_MEMBER_UINT(SELF
, genX_offset_data
);
1079 OBJ_MEMBER_UINT(SELF
, genX_offset_data
) = 0;
1085 //-----------------------------------------------------------------------------
1086 // name: genX_tick()
1088 //-----------------------------------------------------------------------------
1089 CK_DLL_TICK( genX_tick
)
1092 genX_Data
* d
= (genX_Data
*)OBJ_MEMBER_UINT(SELF
, genX_offset_data
);
1093 Chuck_UGen
* ugen
= (Chuck_UGen
*)SELF
;
1094 t_CKBOOL inc_phase
= TRUE
;
1096 t_CKDOUBLE in_index
= 0.0;
1097 t_CKDOUBLE scaled_index
= 0.0;
1098 t_CKDOUBLE alpha
= 0.0, omAlpha
= 0.0;
1099 t_CKUINT lowIndex
= 0, hiIndex
= 0;
1100 t_CKDOUBLE outvalue
= 0.0;
1103 if( ugen
->m_num_src
) {
1105 // gewang: moved this to here
1106 if( in_index
< 0. ) in_index
= -in_index
;
1107 //scaled_index = (in_index + 1.) * 0.5 * genX_tableSize; //drive with oscillator, [-1, 1]
1108 scaled_index
= in_index
* genX_tableSize
; //drive with phasor [0, 1]
1113 // set up interpolation parameters
1114 lowIndex
= (t_CKUINT
)scaled_index
;
1115 hiIndex
= lowIndex
+ 1;
1116 alpha
= scaled_index
- lowIndex
;
1117 omAlpha
= 1. - alpha
;
1119 // check table index ranges
1120 while(lowIndex
>= genX_tableSize
) lowIndex
-= genX_tableSize
;
1121 while(hiIndex
>= genX_tableSize
) hiIndex
-= genX_tableSize
;
1124 // outvalue = genX_lookup(in_index);?
1126 // calculate output value with linear interpolation
1127 outvalue
= d
->genX_table
[lowIndex
]*omAlpha
+ d
->genX_table
[hiIndex
]*alpha
;
1130 *out
= (SAMPLE
)outvalue
;
1136 //-----------------------------------------------------------------------------
1137 // name: genX_lookup()
1138 // desc: lookup call for all gens
1139 //-----------------------------------------------------------------------------
1140 CK_DLL_CTRL( genX_lookup
)
1143 genX_Data
* d
= (genX_Data
*)OBJ_MEMBER_UINT(SELF
, genX_offset_data
);
1146 t_CKFLOAT scaled_index
;
1147 t_CKFLOAT alpha
, omAlpha
;
1148 t_CKUINT lowIndex
, hiIndex
;
1151 in_index
= GET_NEXT_FLOAT(ARGS
);
1153 // gewang: moved to here
1154 if (in_index
< 0.) in_index
= -in_index
;
1155 scaled_index
= in_index
* (genX_tableSize
- 1); //drive with phasor [0, 1]
1157 //set up interpolation parameters
1158 lowIndex
= (t_CKUINT
)scaled_index
;
1159 hiIndex
= lowIndex
+ 1;
1160 alpha
= scaled_index
- lowIndex
;
1161 omAlpha
= 1. - alpha
;
1163 //check table index ranges
1164 while(lowIndex
>= genX_tableSize
) lowIndex
-= genX_tableSize
;
1165 while(hiIndex
>= genX_tableSize
) hiIndex
-= genX_tableSize
;
1167 //calculate output value with linear interpolation
1168 outvalue
= d
->genX_table
[lowIndex
]*omAlpha
+ d
->genX_table
[hiIndex
]*alpha
;
1170 RETURN
->v_float
= (t_CKFLOAT
)outvalue
;
1175 //-----------------------------------------------------------------------------
1176 // name: gen5_coeffs()
1177 // desc: setup table for gen5
1178 //-----------------------------------------------------------------------------
1179 CK_DLL_CTRL( gen5_coeffs
)
1182 genX_Data
* d
= (genX_Data
*)OBJ_MEMBER_UINT(SELF
, genX_offset_data
);
1183 t_CKINT i
= 0, j
, k
, l
, size
;
1184 t_CKFLOAT wmax
, xmax
=0.0, c
, amp2
, amp1
, coeffs
[genX_MAX_COEFFS
];
1186 Chuck_Array8
* in_args
= (Chuck_Array8
*)GET_CK_OBJECT(ARGS
);
1188 // fprintf(stdout, "calling gen10coeffs, %d\n", weights);
1189 if(in_args
<0) return;
1190 size
= in_args
->size();
1191 if(size
>= genX_MAX_COEFFS
) size
= genX_MAX_COEFFS
- 1;
1194 for(t_CKUINT ii
= 0; ii
<size
; ii
++) {
1195 in_args
->get(ii
, &v
);
1196 // fprintf( stdout, "weight %d = %f...\n", ii, v );
1201 if (amp2
<= 0.0) amp2
= 0.000001;
1202 for(k
= 1; k
< size
; k
+= 2) {
1205 if (amp2
<= 0.0) amp2
= 0.000001;
1207 d
->genX_table
[i
] = amp1
;
1208 c
= (t_CKFLOAT
) pow((amp2
/amp1
),(1./(coeffs
[k
]*genX_tableSize
)));
1209 i
= (t_CKINT
)((j
- 1) + coeffs
[k
]*genX_tableSize
);
1210 for(l
= j
; l
< i
; l
++) {
1211 if(l
< genX_tableSize
)
1212 d
->genX_table
[l
] = d
->genX_table
[l
-1] * c
;
1216 for(j
= 0; j
< genX_tableSize
; j
++) {
1217 if ((wmax
= fabs(d
->genX_table
[j
])) > xmax
) xmax
= wmax
;
1218 // fprintf( stdout, "table current = %f\n", wmax);
1220 // fprintf( stdout, "table max = %f\n", xmax);
1221 for(j
= 0; j
< genX_tableSize
; j
++) {
1222 d
->genX_table
[j
] /= xmax
;
1226 RETURN
->v_object
= in_args
;
1230 //-----------------------------------------------------------------------------
1231 // name: gen7_coeffs()
1232 // desc: setup table for gen7
1233 //-----------------------------------------------------------------------------
1234 CK_DLL_CTRL( gen7_coeffs
)
1237 genX_Data
* d
= (genX_Data
*)OBJ_MEMBER_UINT(SELF
, genX_offset_data
);
1238 t_CKINT i
=0, j
, k
, l
, size
;
1239 t_CKFLOAT wmax
, xmax
= 0.0, amp2
, amp1
, coeffs
[genX_MAX_COEFFS
];
1241 Chuck_Array8
* in_args
= (Chuck_Array8
*)GET_CK_OBJECT(ARGS
);
1243 // fprintf(stdout, "calling gen10coeffs, %d\n", weights);
1244 if(in_args
<0) return;
1245 size
= in_args
->size();
1246 if(size
>= genX_MAX_COEFFS
) size
= genX_MAX_COEFFS
- 1;
1249 for(t_CKUINT ii
= 0; ii
<size
; ii
++) {
1250 in_args
->get(ii
, &v
);
1251 // fprintf( stdout, "weight %d = %f...\n", ii, v );
1256 for (k
= 1; k
< size
; k
+= 2) {
1258 amp2
= coeffs
[k
+ 1];
1260 i
= (t_CKINT
)(j
+ coeffs
[k
]*genX_tableSize
- 1);
1261 for (l
= j
; l
<= i
; l
++) {
1262 if (l
<= genX_tableSize
)
1263 d
->genX_table
[l
- 1] = amp1
+
1264 (amp2
- amp1
) * (double) (l
- j
) / (i
- j
+ 1);
1268 for(j
= 0; j
< genX_tableSize
; j
++) {
1269 if ((wmax
= fabs(d
->genX_table
[j
])) > xmax
) xmax
= wmax
;
1270 // fprintf( stdout, "table current = %f\n", wmax);
1272 // fprintf( stdout, "table max = %f\n", xmax);
1273 for(j
= 0; j
< genX_tableSize
; j
++) {
1274 d
->genX_table
[j
] /= xmax
;
1278 RETURN
->v_object
= in_args
;
1282 //-----------------------------------------------------------------------------
1283 // name: gen9_coeffs()
1284 // desc: setup table for gen9
1285 //-----------------------------------------------------------------------------
1286 CK_DLL_CTRL( gen9_coeffs
)
1289 genX_Data
* d
= (genX_Data
*)OBJ_MEMBER_UINT(SELF
, genX_offset_data
);
1291 t_CKDOUBLE wmax
, xmax
=0.0;
1292 t_CKFLOAT coeffs
[genX_MAX_COEFFS
];
1294 Chuck_Array8
* weights
= (Chuck_Array8
*)GET_CK_OBJECT(ARGS
);
1296 // fprintf(stdout, "calling gen10coeffs, %d\n", weights);
1297 if(weights
<0) return;
1298 size
= weights
->size();
1299 if(size
>= genX_MAX_COEFFS
) size
= genX_MAX_COEFFS
- 1;
1303 for(t_CKUINT ii
= 0; ii
<size
; ii
++) {
1304 weights
->get(ii
, &v
);
1305 // fprintf( stdout, "weight %d = %f...\n", ii, v );
1309 for(j
= size
- 1; j
> 0; j
-= 3) {
1310 if(coeffs
[j
- 1] != 0) {
1311 for(i
= 0; i
< genX_tableSize
; i
++) {
1312 t_CKDOUBLE val
= sin(TWO_PI
* ((t_CKDOUBLE
) i
/ ((t_CKDOUBLE
) (genX_tableSize
)
1313 / coeffs
[j
- 2]) + coeffs
[j
] / 360.));
1314 d
->genX_table
[i
] += val
* coeffs
[j
- 1];
1319 for(j
= 0; j
< genX_tableSize
; j
++) {
1320 if ((wmax
= fabs(d
->genX_table
[j
])) > xmax
) xmax
= wmax
;
1321 // fprintf( stdout, "table current = %f\n", wmax);
1323 // fprintf( stdout, "table max = %f\n", xmax);
1324 for(j
= 0; j
< genX_tableSize
; j
++) {
1325 d
->genX_table
[j
] /= xmax
;
1329 RETURN
->v_object
= weights
;
1333 //-----------------------------------------------------------------------------
1334 // name: gen10_coeffs()
1335 // desc: setup table for gen10
1336 //-----------------------------------------------------------------------------
1337 CK_DLL_CTRL( gen10_coeffs
)
1340 genX_Data
* d
= (genX_Data
*)OBJ_MEMBER_UINT(SELF
, genX_offset_data
);
1342 t_CKDOUBLE wmax
, xmax
=0.0;
1344 Chuck_Array8
* weights
= (Chuck_Array8
*)GET_CK_OBJECT(ARGS
);
1346 // fprintf(stdout, "calling gen10coeffs, %d\n", weights);
1347 if(weights
<0) return;
1348 size
= weights
->size();
1349 if(size
>= genX_MAX_COEFFS
) size
= genX_MAX_COEFFS
- 1;
1352 for(t_CKUINT ii
= 0; ii
<size
; ii
++) {
1353 weights
->get(ii
, &v
);
1354 // fprintf( stdout, "weight %d = %f...\n", ii, v );
1358 j
= genX_MAX_COEFFS
;
1360 if (d
->coeffs
[j
] != 0) {
1361 for (i
= 0; i
< genX_tableSize
; i
++) {
1362 t_CKDOUBLE val
= (t_CKDOUBLE
) (TWO_PI
* (t_CKDOUBLE
) i
/ (genX_tableSize
/ (j
+ 1)));
1363 d
->genX_table
[i
] += sin(val
) * d
->coeffs
[j
];
1368 for(j
= 0; j
< genX_tableSize
; j
++) {
1369 if ((wmax
= fabs(d
->genX_table
[j
])) > xmax
) xmax
= wmax
;
1370 // fprintf( stdout, "table current = %f\n", wmax);
1373 // fprintf( stdout, "table max = %f\n", xmax);
1374 for(j
= 0; j
< genX_tableSize
; j
++) {
1375 d
->genX_table
[j
] /= xmax
;
1379 RETURN
->v_object
= weights
;
1383 //-----------------------------------------------------------------------------
1384 // name: gen17_coeffs()
1385 // desc: setup table for gen17
1386 //-----------------------------------------------------------------------------
1387 CK_DLL_CTRL( gen17_coeffs
)
1390 genX_Data
* d
= (genX_Data
*)OBJ_MEMBER_UINT(SELF
, genX_offset_data
);
1392 t_CKDOUBLE Tn
, Tn1
, Tn2
, dg
, x
, wmax
= 0.0, xmax
= 0.0;
1393 t_CKFLOAT coeffs
[genX_MAX_COEFFS
];
1395 Chuck_Array8
* weights
= (Chuck_Array8
*)GET_CK_OBJECT(ARGS
);
1397 // fprintf(stdout, "calling gen17coeffs, %d\n", weights);
1398 if(weights
<0) return;
1399 size
= weights
->size();
1400 if(size
>= genX_MAX_COEFFS
) size
= genX_MAX_COEFFS
- 1;
1402 dg
= (t_CKDOUBLE
) (genX_tableSize
/ 2. - .5);
1405 for(t_CKUINT ii
= 0; ii
<size
; ii
++) {
1406 weights
->get(ii
, &v
);
1407 // fprintf( stdout, "weight %d = %f...\n", ii, v );
1411 for (i
= 0; i
< genX_tableSize
; i
++) {
1412 x
= (t_CKDOUBLE
)(i
/ dg
- 1.);
1413 d
->genX_table
[i
] = 0.0;
1416 for (j
= 0; j
< size
; j
++) {
1417 d
->genX_table
[i
] = coeffs
[j
] * Tn
+ d
->genX_table
[i
];
1420 Tn
= 2.0 * x
* Tn1
- Tn2
;
1424 for(j
= 0; j
< genX_tableSize
; j
++) {
1425 if ((wmax
= fabs(d
->genX_table
[j
])) > xmax
) xmax
= wmax
;
1426 // fprintf( stdout, "table current = %f\n", wmax);
1428 // fprintf( stdout, "table max = %f\n", xmax);
1429 for(j
= 0; j
< genX_tableSize
; j
++) {
1430 d
->genX_table
[j
] /= xmax
;
1431 // fprintf( stdout, "table current = %f\n", d->genX_table[j]);
1435 RETURN
->v_object
= weights
;
1439 //-----------------------------------------------------------------------------
1440 // name: curve_coeffs()
1441 // desc: setup table for Curve
1442 // ported from RTcmix
1443 //-----------------------------------------------------------------------------
1444 #define MAX_CURVE_PTS 256
1445 CK_DLL_CTRL( curve_coeffs
)
1448 genX_Data
* d
= (genX_Data
*)OBJ_MEMBER_UINT(SELF
, genX_offset_data
);
1449 t_CKINT i
, points
, nargs
, seglen
= 0, len
= genX_tableSize
;
1450 t_CKDOUBLE factor
, *ptr
, xmax
=0.0;
1451 t_CKDOUBLE time
[MAX_CURVE_PTS
], value
[MAX_CURVE_PTS
], alpha
[MAX_CURVE_PTS
];
1452 t_CKFLOAT coeffs
[genX_MAX_COEFFS
];
1456 Chuck_Array8
* weights
= (Chuck_Array8
*)GET_CK_OBJECT(ARGS
);
1458 // fprintf(stdout, "calling gen17coeffs, %d\n", weights);
1459 if(weights
<0) goto done
;
1461 nargs
= weights
->size();
1462 if (nargs
< 5 || (nargs
% 3) != 2) { // check number of args
1463 fprintf( stderr
, "[chuck](via CurveTable): usage: \n size, time1, value1, curvature1, [ timeN-1, valueN-1, curvatureN-1, ] timeN, valueN)\n" );
1466 if ((nargs
/ 3) + 1 > MAX_CURVE_PTS
) {
1467 fprintf(stderr
, ("[chuck](via CurveTable): too many arguments.\n"));
1471 for(ii
= 0; ii
<nargs
; ii
++) {
1472 weights
->get(ii
, &v
);
1473 // fprintf( stdout, "weight %d = %f...\n", ii, v );
1477 if (coeffs
[0] != 0.0) {
1478 fprintf(stderr
, "[chuck](via CurveTable): first time must be zero.\n");
1482 for (i
= points
= 0; i
< nargs
; points
++) {
1483 time
[points
] = (t_CKDOUBLE
) coeffs
[i
++];
1484 if (points
> 0 && time
[points
] < time
[points
- 1])
1486 value
[points
] = (t_CKDOUBLE
) coeffs
[i
++];
1488 alpha
[points
] = (t_CKDOUBLE
) coeffs
[i
++];
1491 factor
= (t_CKDOUBLE
) (len
- 1) / time
[points
- 1];
1492 for (i
= 0; i
< points
; i
++)
1495 ptr
= d
->genX_table
;
1496 for (i
= 0; i
< points
- 1; i
++) {
1497 seglen
= (t_CKINT
) (floor(time
[i
+ 1] + 0.5) - floor(time
[i
] + 0.5)) + 1;
1498 _transition(value
[i
], alpha
[i
], value
[i
+ 1], seglen
, ptr
);
1504 RETURN
->v_object
= weights
;
1509 fprintf(stderr
, "[chuck](via CurveTable): times must be in ascending order.\n");
1512 RETURN
->v_object
= weights
;
1518 static void _transition(t_CKDOUBLE a
, t_CKDOUBLE alpha
, t_CKDOUBLE b
, t_CKINT n
, t_CKDOUBLE
*output
)
1521 t_CKDOUBLE delta
, interval
= 0.0;
1526 //warn("maketable (curve)", "Trying to transition over 1 array slot; "
1527 // "time between points is too short");
1531 interval
= 1.0 / (n
- 1.0);
1534 t_CKDOUBLE denom
= 1.0 / (1.0 - exp(alpha
));
1535 for (i
= 0; i
< n
; i
++)
1536 *output
++ = (a
+ delta
1537 * (1.0 - exp((double) i
* alpha
* interval
)) * denom
);
1540 for (i
= 0; i
< n
; i
++)
1541 *output
++ = a
+ delta
* i
* interval
;
1545 //-----------------------------------------------------------------------------
1546 // name: warp_coeffs()
1547 // desc: setup table for warp
1548 //-----------------------------------------------------------------------------
1549 CK_DLL_CTRL( warp_coeffs
)
1552 genX_Data
* d
= (genX_Data
*)OBJ_MEMBER_UINT(SELF
, genX_offset_data
);
1555 t_CKFLOAT k_asym
= 1.;
1556 t_CKFLOAT k_sym
= 1.;
1559 Chuck_Array8
* weights
= (Chuck_Array8
*)GET_CK_OBJECT(ARGS
);
1561 if( weights
->size() != 2 )
1564 fprintf( stderr
, "[chuck](via WarpTable): expects array of exactly 2 elements.\n" );
1568 weights
->get( 0, &k_asym
); // (t_CKDOUBLE) GET_NEXT_FLOAT(ARGS);
1569 weights
->get( 1, &k_sym
); // (t_CKDOUBLE) GET_NEXT_FLOAT(ARGS);
1571 for (i
= 0; i
< genX_tableSize
; i
++) {
1572 t_CKDOUBLE inval
= (t_CKDOUBLE
) i
/(genX_tableSize
- 1);
1573 if(k_asym
== 1 && k_sym
== 1) {
1574 d
->genX_table
[i
] = inval
;
1575 } else if(k_sym
== 1) {
1576 d
->genX_table
[i
] = _asymwarp(inval
, k_asym
);
1577 } else if(k_asym
== 1) {
1578 d
->genX_table
[i
] = _symwarp(inval
, k_sym
);
1580 inval
= _asymwarp(inval
, k_asym
);
1581 d
->genX_table
[i
] = _symwarp(inval
, k_sym
);
1583 // fprintf(stdout, "table %d = %f\n", i, d->genX_table[i]);
1589 RETURN
->v_object
= weights
;
1593 t_CKDOUBLE
_asymwarp(t_CKDOUBLE inval
, t_CKDOUBLE k
)
1595 return (pow(k
, inval
) - 1.) / (k
- 1.);
1599 t_CKDOUBLE
_symwarp(t_CKDOUBLE inval
, t_CKDOUBLE k
)
1601 t_CKDOUBLE sym_warped
;
1603 sym_warped
= pow(2.*inval
- 1., 1./k
);
1604 return (sym_warped
+ 1.) * 0.5;
1607 inval
= 1. - inval
; // for S curve
1608 sym_warped
= pow(2.*inval
- 1., 1./k
);
1609 sym_warped
= (sym_warped
+ 1.) * 0.5;
1611 return 1. - sym_warped
;
1615 // also do RTcmix "spline" on a rainy day
1618 //-----------------------------------------------------------------------------
1619 // name: genX_pmsg()
1621 //-----------------------------------------------------------------------------
1622 CK_DLL_PMSG( genX_pmsg
)
1624 genX_Data
* d
= (genX_Data
*)OBJ_MEMBER_UINT(SELF
, genX_offset_data
);
1625 if( !strcmp( MSG
, "print" ) )
1627 // fprintf( stdout, "genX:" );
1636 //-----------------------------------------------------------------------------
1637 // name: genX_coeffs()
1639 //-----------------------------------------------------------------------------
1640 CK_DLL_CTRL( genX_coeffs
)
1643 fprintf( stderr
, "[chuck](via GenX): .coeffs called on abstract base class!\n" );
1646 RETURN
->v_object
= GET_NEXT_OBJECT(ARGS
);