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)
32 //-----------------------------------------------------------------------------
37 #include "util_math.h"
42 int setenv( char *n
, char *v
, int i
)
44 return SetEnvironmentVariable(n
, v
);
50 //-----------------------------------------------------------------------------
51 // name: libstd_query()
52 // desc: query entry point
53 //-----------------------------------------------------------------------------
54 DLL_QUERY
libstd_query( Chuck_DL_Query
* QUERY
)
58 QUERY
->set_name( QUERY
, "std" );
61 std.rand2f( 100.0, 1000.0 ) => stdout;
65 QUERY
->add_export( QUERY
, "float", "abs", abs_impl
, TRUE
);
66 QUERY
->add_param( QUERY
, "float", "value" );
70 QUERY
->add_export( QUERY
, "int", "rand", rand_impl
, TRUE
); //! return int between 0 and RAND_MAX
72 QUERY
->add_export( QUERY
, "int", "rand2", rand2_impl
, TRUE
); //! integer between [min,max]
73 QUERY
->add_param( QUERY
, "int", "min" );
74 QUERY
->add_param( QUERY
, "int", "max" );
76 QUERY
->add_export( QUERY
, "float", "randf", randf_impl
, TRUE
); //! rand between -1.0,1.0
77 QUERY
->add_export( QUERY
, "float", "rand2f", rand2f_impl
, TRUE
); //! rand between min and max
78 QUERY
->add_param( QUERY
, "float", "min" );
79 QUERY
->add_param( QUERY
, "float", "max" );
82 QUERY
->add_export( QUERY
, "float", "sgn", sgn_impl
, TRUE
); //! return sign of value (-1, 0, 1)
83 QUERY
->add_param( QUERY
, "float", "value" );
86 //! see \example std.ck
87 QUERY
->add_export( QUERY
, "int", "system", system_impl
, TRUE
); //! issue system command
88 QUERY
->add_param( QUERY
, "string", "cmd" );
91 QUERY
->add_export( QUERY
, "int", "atoi", atoi_impl
, TRUE
); //! string to integer
92 QUERY
->add_param( QUERY
, "string", "value" );
95 QUERY
->add_export( QUERY
, "float", "atof", atof_impl
, TRUE
); //! string to float
96 QUERY
->add_param( QUERY
, "string", "value" );
99 QUERY
->add_export( QUERY
, "string", "getenv", getenv_impl
, TRUE
); //! fetch environment variable
100 QUERY
->add_param( QUERY
, "string", "value" );
103 QUERY
->add_export( QUERY
, "int", "setenv", setenv_impl
, TRUE
); //! set environment variable
104 QUERY
->add_param( QUERY
, "string", "key" );
105 QUERY
->add_param( QUERY
, "string", "value" );
108 srand( time( NULL
) );
111 //! see \example mand-o-matic.ck
112 QUERY
->add_export( QUERY
, "float", "mtof", mtof_impl
, TRUE
); //! midi note to frequency
113 QUERY
->add_param( QUERY
, "float", "value" );
116 QUERY
->add_export( QUERY
, "float", "ftom", ftom_impl
, TRUE
); //! frequency to midi note
117 QUERY
->add_param( QUERY
, "float", "value" );
120 QUERY
->add_export( QUERY
, "float", "powtodb", powtodb_impl
, TRUE
); //! linear power to decibel
121 QUERY
->add_param( QUERY
, "float", "value" );
124 QUERY
->add_export( QUERY
, "float", "rmstodb", rmstodb_impl
, TRUE
); //! rms to decibel
125 QUERY
->add_param( QUERY
, "float", "value" );
128 QUERY
->add_export( QUERY
, "float", "dbtopow", dbtopow_impl
, TRUE
); //! decibel to linear
129 QUERY
->add_param( QUERY
, "float", "value" );
132 QUERY
->add_export( QUERY
, "float", "dbtorms", dbtorms_impl
, TRUE
); //! decibel to rms
133 QUERY
->add_param( QUERY
, "float", "value" );
138 #define RAND_INV_RANGE(r) (RAND_MAX / (r))
140 int irand_exclusive ( int max
) {
143 while (x
>= max
* RAND_INV_RANGE (max
))
146 x
/= RAND_INV_RANGE (max
);
152 CK_DLL_FUNC( abs_impl
)
154 t_CKFLOAT v
= GET_CK_FLOAT(ARGS
);
155 RETURN
->v_float
= v
>= 0.0f
? v
: -v
;
159 CK_DLL_FUNC( fabs_impl
)
161 RETURN
->v_float
= ::fabs( GET_CK_FLOAT(ARGS
) );
165 CK_DLL_FUNC( rand_impl
)
167 RETURN
->v_int
= ::rand();
171 CK_DLL_FUNC( randf_impl
)
173 RETURN
->v_float
= ( 2.0 * ::rand() / (t_CKFLOAT
)RAND_MAX
- 1.0 );
177 CK_DLL_FUNC( rand2f_impl
)
179 t_CKFLOAT min
= GET_CK_FLOAT(ARGS
), max
= *((t_CKFLOAT
*)ARGS
+ 1);
180 RETURN
->v_float
= min
+ (max
-min
)*(::rand()/(t_CKFLOAT
)RAND_MAX
);
184 CK_DLL_FUNC( rand2_impl
) // inclusive.
186 int min
= *(int *)ARGS
, max
= *((int *)ARGS
+ 1);
187 int range
= max
- min
;
191 //else if ( range < RAND_MAX / 2 ) {
192 // RETURN->v_int = ( range > 0 ) ? min + irand_exclusive(1 + range) : max + irand_exclusive ( -range + 1 ) ;
196 RETURN
->v_int
= min
+ (int) ( (1.0 + range
) * ( ::rand()/(RAND_MAX
+1.0) ) );
199 RETURN
->v_int
= min
- (int) ( (-range
+ 1.0) * ( ::rand()/(RAND_MAX
+1.0) ) );
205 CK_DLL_FUNC( sgn_impl
)
207 t_CKFLOAT v
= GET_CK_FLOAT(ARGS
);
208 RETURN
->v_float
= v
== 0.0f
? 0.0f
: ( v
> 0.0f
? 1.0f
: -1.0f
);
212 CK_DLL_FUNC( system_impl
)
214 char * cmd
= *(char **)ARGS
;
215 RETURN
->v_int
= system( cmd
);
219 CK_DLL_FUNC( atoi_impl
)
221 char * v
= *(char **)ARGS
;
222 RETURN
->v_int
= atoi( v
);
226 CK_DLL_FUNC( atof_impl
)
228 char * v
= *(char **)ARGS
;
229 RETURN
->v_float
= atof( v
);
233 CK_DLL_FUNC( getenv_impl
)
235 char * v
= *(char **)ARGS
;
236 RETURN
->v_string
= getenv( v
);
240 CK_DLL_FUNC( setenv_impl
)
242 char * v1
= *(char **)ARGS
;
243 char * v2
= *( (char **)ARGS
+ 1 );
244 RETURN
->v_int
= setenv( v1
, v2
, 1 );
247 // the following 6 functions are
248 // lifted from PD source
249 // specifically x_acoustics.c
250 // http://puredata.info/downloads
252 #define LOGTEN 2.302585092994
254 double mtof(double f
)
256 if (f
<= -1500) return(0);
257 else if (f
> 1499) return(mtof(1499));
258 else return (float)(8.17579891564 * exp(.0577622650 * (double)f
));
261 CK_DLL_FUNC( mtof_impl
)
263 t_CKFLOAT v
= GET_CK_FLOAT(ARGS
);
264 RETURN
->v_float
= mtof(v
);
267 double ftom(double f
)
269 return (f
> 0 ? 17.3123405046 * log(.12231220585 * f
) : -1500);
272 CK_DLL_FUNC( ftom_impl
)
274 t_CKFLOAT v
= GET_CK_FLOAT(ARGS
);
275 RETURN
->v_float
= ftom(v
);
279 float powtodb(float f
)
281 if (f
<= 0) return (0);
284 float val
= 100 + 10./LOGTEN
* log(f
);
285 return (val
< 0 ? 0 : val
);
290 CK_DLL_FUNC( powtodb_impl
)
292 t_CKFLOAT v
= GET_CK_FLOAT(ARGS
);
293 RETURN
->v_float
= powtodb(v
);
297 float rmstodb(float f
)
299 if (f
<= 0) return (0);
302 float val
= 100 + 20./LOGTEN
* log(f
);
303 return (val
< 0 ? 0 : val
);
307 CK_DLL_FUNC( rmstodb_impl
)
309 t_CKFLOAT v
= GET_CK_FLOAT(ARGS
);
310 RETURN
->v_float
= rmstodb(v
);
314 float dbtopow(float f
)
322 return (exp((LOGTEN
* 0.1) * (f
-100.)));
326 CK_DLL_FUNC( dbtopow_impl
)
328 t_CKFLOAT v
= GET_CK_FLOAT(ARGS
);
329 RETURN
->v_float
= dbtopow(v
);
332 float dbtorms(float f
)
341 return (exp((LOGTEN
* 0.05) * (f
-100.)));
344 CK_DLL_FUNC( dbtorms_impl
)
346 t_CKFLOAT v
= GET_CK_FLOAT(ARGS
);
347 RETURN
->v_float
= dbtorms(v
);