*** empty log message ***
[chuck-blob.git] / v1 / ulib_std.cpp
blob8c6395c426e2127e5061907cc579e4440dd039c3
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
22 U.S.A.
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
26 // file: ulib_std.cpp
27 // desc: ...
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
31 // date: Spring 2004
32 //-----------------------------------------------------------------------------
33 #include "ulib_std.h"
34 #include <stdlib.h>
35 #include <time.h>
36 #include <math.h>
37 #include "util_math.h"
39 #if __WINDOWS_DS__
40 #include <windows.h>
42 int setenv( char *n, char *v, int i )
44 return SetEnvironmentVariable(n, v);
47 #endif
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" );
60 /*! \example
61 std.rand2f( 100.0, 1000.0 ) => stdout;
62 */
64 // add abs
65 QUERY->add_export( QUERY, "float", "abs", abs_impl, TRUE );
66 QUERY->add_param( QUERY, "float", "value" );
68 // add rand
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" );
81 // add sgn
82 QUERY->add_export( QUERY, "float", "sgn", sgn_impl, TRUE ); //! return sign of value (-1, 0, 1)
83 QUERY->add_param( QUERY, "float", "value" );
85 // add system
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" );
90 // add atoi
91 QUERY->add_export( QUERY, "int", "atoi", atoi_impl, TRUE ); //! string to integer
92 QUERY->add_param( QUERY, "string", "value" );
94 // add atof
95 QUERY->add_export( QUERY, "float", "atof", atof_impl, TRUE ); //! string to float
96 QUERY->add_param( QUERY, "string", "value" );
98 // add getenv
99 QUERY->add_export( QUERY, "string", "getenv", getenv_impl, TRUE ); //! fetch environment variable
100 QUERY->add_param( QUERY, "string", "value" );
102 // add setenv
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" );
107 // seed the rand
108 srand( time( NULL ) );
110 // add mtof
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" );
115 // add ftom
116 QUERY->add_export( QUERY, "float", "ftom", ftom_impl, TRUE ); //! frequency to midi note
117 QUERY->add_param( QUERY, "float", "value" );
119 // add powtodb
120 QUERY->add_export( QUERY, "float", "powtodb", powtodb_impl, TRUE ); //! linear power to decibel
121 QUERY->add_param( QUERY, "float", "value" );
123 // add rmstodb
124 QUERY->add_export( QUERY, "float", "rmstodb", rmstodb_impl, TRUE ); //! rms to decibel
125 QUERY->add_param( QUERY, "float", "value" );
127 // add dbtopow
128 QUERY->add_export( QUERY, "float", "dbtopow", dbtopow_impl, TRUE ); //! decibel to linear
129 QUERY->add_param( QUERY, "float", "value" );
131 // add dbtorms
132 QUERY->add_export( QUERY, "float", "dbtorms", dbtorms_impl, TRUE ); //! decibel to rms
133 QUERY->add_param( QUERY, "float", "value" );
135 return TRUE;
138 #define RAND_INV_RANGE(r) (RAND_MAX / (r))
140 int irand_exclusive ( int max ) {
141 int x = ::rand();
143 while (x >= max * RAND_INV_RANGE (max))
144 x = ::rand();
146 x /= RAND_INV_RANGE (max);
147 return x;
151 // abs
152 CK_DLL_FUNC( abs_impl )
154 t_CKFLOAT v = GET_CK_FLOAT(ARGS);
155 RETURN->v_float = v >= 0.0f ? v : -v;
158 // fabs
159 CK_DLL_FUNC( fabs_impl )
161 RETURN->v_float = ::fabs( GET_CK_FLOAT(ARGS) );
164 // rand
165 CK_DLL_FUNC( rand_impl )
167 RETURN->v_int = ::rand();
170 // randf
171 CK_DLL_FUNC( randf_impl )
173 RETURN->v_float = ( 2.0 * ::rand() / (t_CKFLOAT)RAND_MAX - 1.0 );
176 // randf
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);
183 // randi
184 CK_DLL_FUNC( rand2_impl ) // inclusive.
186 int min = *(int *)ARGS, max = *((int *)ARGS + 1);
187 int range = max - min;
188 if ( range == 0 ) {
189 RETURN->v_int = min;
191 //else if ( range < RAND_MAX / 2 ) {
192 // RETURN->v_int = ( range > 0 ) ? min + irand_exclusive(1 + range) : max + irand_exclusive ( -range + 1 ) ;
194 else {
195 if ( range > 0 ) {
196 RETURN->v_int = min + (int) ( (1.0 + range) * ( ::rand()/(RAND_MAX+1.0) ) );
198 else {
199 RETURN->v_int = min - (int) ( (-range + 1.0) * ( ::rand()/(RAND_MAX+1.0) ) );
204 // sgn
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 );
211 // system
212 CK_DLL_FUNC( system_impl )
214 char * cmd = *(char **)ARGS;
215 RETURN->v_int = system( cmd );
218 // aoti
219 CK_DLL_FUNC( atoi_impl )
221 char * v = *(char **)ARGS;
222 RETURN->v_int = atoi( v );
225 // atof
226 CK_DLL_FUNC( atof_impl )
228 char * v = *(char **)ARGS;
229 RETURN->v_float = atof( v );
232 // getenv
233 CK_DLL_FUNC( getenv_impl )
235 char * v = *(char **)ARGS;
236 RETURN->v_string = getenv( v );
239 // setenv
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);
282 else
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);
300 else
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)
316 if (f <= 0)
317 return(0);
318 else
320 if (f > 870)
321 f = 870;
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)
334 if (f <= 0)
335 return(0);
336 else
338 if (f > 485)
339 f = 485;
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);