*** empty log message ***
[chuck-blob.git] / v2 / ugen_xxx.cpp
blob11b57d6acbde41aede15c7dd52b73263c0dd26cc
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: ugen_xxx.cpp
27 // desc: ...
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
31 // Ananya Misra (amisra@cs.princeton.edu)
32 // date: Spring 2004
33 // Summer 2005 - updated
34 //-----------------------------------------------------------------------------
35 #include <math.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/stat.h>
40 #include <limits.h>
42 #if defined(__CK_SNDFILE_NATIVE__)
43 #include <sndfile.h>
44 #else
45 #include "util_sndfile.h"
46 #endif
48 #include "ugen_xxx.h"
49 #include "chuck_type.h"
50 #include "chuck_ugen.h"
51 #include "chuck_vm.h"
52 #include "chuck_globals.h"
54 #include <fstream>
55 using namespace std;
58 // LiSa query
59 DLL_QUERY lisa_query( Chuck_DL_Query * query );
62 t_CKUINT g_srate;
64 // offset
65 static t_CKUINT stereo_offset_left = 0;
66 static t_CKUINT stereo_offset_right = 0;
67 static t_CKUINT stereo_offset_pan = 0;
68 static t_CKUINT cnoise_offset_data = 0;
69 static t_CKUINT impulse_offset_data = 0;
70 static t_CKUINT step_offset_data = 0;
71 static t_CKUINT zerox_offset_data = 0;
72 static t_CKUINT delayp_offset_data = 0;
73 static t_CKUINT sndbuf_offset_data = 0;
74 static t_CKUINT dyno_offset_data = 0;
76 Chuck_Type * g_t_dac = NULL;
77 Chuck_Type * g_t_adc = NULL;
80 //-----------------------------------------------------------------------------
81 // name: xxx_query()
82 // desc: ...
83 //-----------------------------------------------------------------------------
84 DLL_QUERY xxx_query( Chuck_DL_Query * QUERY )
86 g_srate = QUERY->srate;
87 // get the env
88 Chuck_Env * env = Chuck_Env::instance();
90 Chuck_DL_Func * func = NULL;
92 // deprecate
93 type_engine_register_deprecate( env, "dac", "DAC" );
94 type_engine_register_deprecate( env, "adc", "ADC" );
95 type_engine_register_deprecate( env, "pan2", "Pan2" );
96 type_engine_register_deprecate( env, "mix2", "Mix2" );
97 type_engine_register_deprecate( env, "gain", "Gain" );
98 type_engine_register_deprecate( env, "noise", "Noise" );
99 type_engine_register_deprecate( env, "cnoise", "CNoise" );
100 type_engine_register_deprecate( env, "impulse", "Impulse" );
101 type_engine_register_deprecate( env, "step", "Step" );
102 type_engine_register_deprecate( env, "halfrect", "HalfRect" );
103 type_engine_register_deprecate( env, "fullrect", "FullRect" );
104 type_engine_register_deprecate( env, "zerox", "ZeroX" );
105 type_engine_register_deprecate( env, "delayp", "DelayP" );
106 type_engine_register_deprecate( env, "sndbuf", "SndBuf" );
108 //! \section audio output
110 //-------------------------------------------------------------------------
111 // init as base class: UGen_Multi
112 //-------------------------------------------------------------------------
113 if( !type_engine_import_ugen_begin( env, "UGen_Multi", "UGen", env->global(),
114 multi_ctor, NULL, NULL, 0, 0 ) )
115 return FALSE;
117 // add chan
118 func = make_new_mfun( "UGen", "chan", multi_cget_chan );
119 func->add_arg( "int", "which" );
120 if( !type_engine_import_mfun( env, func ) ) goto error;
122 // add pan
123 /* func = make_new_mfun( "float", "pan", multi_ctrl_pan );
124 func->add_arg( "float", "val" );
125 if( !type_engine_import_mfun( env, func ) ) goto error;
126 func = make_new_mfun( "float", "pan", multi_cget_pan );
127 if( !type_engine_import_mfun( env, func ) ) goto error; */
130 //---------------------------------------------------------------------
131 // init as base class: UGen_Stereo
132 //---------------------------------------------------------------------
133 if( !type_engine_import_ugen_begin( env, "UGen_Stereo", "UGen_Multi", env->global(),
134 stereo_ctor, NULL, NULL, NULL, 2, 2 ) )
135 return FALSE;
137 // add left
138 stereo_offset_left = type_engine_import_mvar( env, "UGen", "left", FALSE );
139 if( stereo_offset_left == CK_INVALID_OFFSET ) goto error;
141 // add right
142 stereo_offset_right = type_engine_import_mvar( env, "UGen", "right", FALSE );
143 if( stereo_offset_right == CK_INVALID_OFFSET ) goto error;
145 // add pan
146 stereo_offset_pan = type_engine_import_mvar( env, "float", "@pan", FALSE );
147 if( stereo_offset_pan == CK_INVALID_OFFSET ) goto error;
149 // add pan
150 func = make_new_mfun( "float", "pan", stereo_ctrl_pan );
151 func->add_arg( "float", "val" );
152 if( !type_engine_import_mfun( env, func ) ) goto error;
153 func = make_new_mfun( "float", "pan", stereo_cget_pan );
154 if( !type_engine_import_mfun( env, func ) ) goto error;
156 // end import
157 if( !type_engine_import_class_end( env ) )
158 return FALSE;
160 // add dac
161 //! digital/analog converter
162 //! abstraction for underlying audio output device
163 //---------------------------------------------------------------------
164 // init as base class: dac
165 //---------------------------------------------------------------------
166 if( !(g_t_dac = type_engine_import_ugen_begin( env, "DAC", "UGen_Stereo", env->global(),
167 NULL, NULL, NULL, NULL, 2, 2 )) )
168 return FALSE;
170 // end import
171 if( !type_engine_import_class_end( env ) )
172 return FALSE;
174 // add adc
175 //! analog/digital converter
176 //! abstraction for underlying audio input device
177 //---------------------------------------------------------------------
178 // init as base class: adc
179 //---------------------------------------------------------------------
180 if( !(g_t_adc = type_engine_import_ugen_begin( env, "ADC", "UGen_Stereo", env->global(),
181 NULL, NULL, NULL, NULL, 0, 2 )) )
182 return FALSE;
184 // end import
185 if( !type_engine_import_class_end( env ) )
186 return FALSE;
188 //---------------------------------------------------------------------
189 // init as base class: pan2
190 //---------------------------------------------------------------------
191 if( !type_engine_import_ugen_begin( env, "Pan2", "UGen_Stereo", env->global(),
192 NULL, NULL, NULL, NULL, 2, 2 ) )
193 return FALSE;
195 // end import
196 if( !type_engine_import_class_end( env ) )
197 return FALSE;
199 //---------------------------------------------------------------------
200 // init as base class: mix2
201 //---------------------------------------------------------------------
202 if( !type_engine_import_ugen_begin( env, "Mix2", "UGen_Stereo", env->global(),
203 NULL, NULL, NULL, NULL, 2, 2 ) )
204 return FALSE;
206 // end import
207 if( !type_engine_import_class_end( env ) )
208 return FALSE;
210 // add blackhole
211 //! sample rate sample sucker
212 //! ( like dac, ticks ugens, but no more )
213 //! see \example pwm.ck
214 //QUERY->ugen_add( QUERY, "blackhole", NULL );
215 // set funcs
216 //QUERY->ugen_func( QUERY, NULL, NULL, bunghole_tick, NULL );
218 // add bunghole
219 //! sample rate sample sucker
220 //! ( like dac, ticks ugens, but no more )
221 //QUERY->ugen_add( QUERY, "bunghole", NULL );
222 // set funcs
223 //QUERY->ugen_func( QUERY, NULL, NULL, bunghole_tick, NULL );
225 // add gain
226 //! gain control
227 //! (NOTE - all unit generators can themselves change their gain)
228 //! (this is a way to add N outputs together and scale them)
229 //! used in \example i-robot.ck
230 //---------------------------------------------------------------------
231 // init as base class: gain
232 //---------------------------------------------------------------------
233 if( !type_engine_import_ugen_begin( env, "Gain", "UGen", env->global(),
234 NULL, NULL, NULL, NULL ) )
235 return FALSE;
236 // end import
237 if( !type_engine_import_class_end( env ) )
238 return FALSE;
239 /*! \example
240 noise n => gain g => dac;
241 sinosc s => g;
242 .3 => g.gain;
243 while( true ) { 100::ms => now; }
246 //! \section wave forms
248 // add noise
249 //! white noise generator
250 //! see \example noise.ck \example powerup.ck
251 //---------------------------------------------------------------------
252 // init as base class: noise
253 //---------------------------------------------------------------------
254 if( !type_engine_import_ugen_begin( env, "Noise", "UGen", env->global(),
255 NULL, NULL, noise_tick, NULL ) )
256 return FALSE;
258 // end import
259 if( !type_engine_import_class_end( env ) )
260 return FALSE;
261 //zzz
263 // add cnoise
264 /*QUERY->ugen_add( QUERY, "cnoise", NULL );
265 QUERY->ugen_func( QUERY, cnoise_ctor, cnoise_dtor, cnoise_tick, NULL );
266 QUERY->ugen_ctrl( QUERY, cnoise_ctrl_mode, NULL, "string", "mode" );
267 QUERY->ugen_ctrl( QUERY, cnoise_ctrl_fprob, NULL, "float", "fprob" );*/
269 //---------------------------------------------------------------------
270 // init as base class: cnoise
271 //---------------------------------------------------------------------
272 if( !type_engine_import_ugen_begin( env, "CNoise", "UGen", env->global(),
273 cnoise_ctor, cnoise_dtor, cnoise_tick, NULL ) )
274 return FALSE;
276 // add member variable
277 cnoise_offset_data = type_engine_import_mvar( env, "int", "@cnoise_data", FALSE );
278 if( cnoise_offset_data == CK_INVALID_OFFSET ) goto error;
280 // add ctrl: mode
281 func = make_new_mfun( "string", "mode", cnoise_ctrl_mode );
282 func->add_arg( "string", "mode" );
283 if( !type_engine_import_mfun( env, func ) ) goto error;
284 // add cget: mode
285 //func = make_new_mfun( "string", "mode", cnoise_cget_mode );
286 //if( !type_engine_import_mfun( env, func ) ) goto error;
288 // add ctrl: fprob
289 func = make_new_mfun( "float", "fprob", cnoise_ctrl_fprob );
290 func->add_arg( "float", "fprob" );
291 if( !type_engine_import_mfun( env, func ) ) goto error;
292 // add cget: fprob
293 //func = make_new_mfun( "float", "fprob", cnoise_cget_fprob );
294 //if( !type_engine_import_mfun( env, func ) ) goto error;
296 // end import
297 if( !type_engine_import_class_end( env ) )
298 return FALSE;
301 // add impulse
302 //! pulse generator - can set the value of the current sample
303 //! default for each sample is 0 if not set
304 //QUERY->ugen_add( QUERY, "impulse", NULL );
305 // set funcs
306 //QUERY->ugen_func( QUERY, impulse_ctor, impulse_dtor, impulse_tick, NULL );
307 // ctrl func
308 //QUERY->ugen_ctrl( QUERY, impulse_ctrl_value, impulse_cget_value, "float", "value" );
309 //QUERY->ugen_ctrl( QUERY, impulse_ctrl_value, impulse_cget_value, "float", "next" ); //! set value of next sample
310 /*! \example
311 impulse i => dac;
313 while( true ) {
314 1.0 => i.next;
315 100::ms => now;
318 //---------------------------------------------------------------------
319 // init as base class: impulse
320 //---------------------------------------------------------------------
321 if( !type_engine_import_ugen_begin( env, "Impulse", "UGen", env->global(),
322 impulse_ctor, impulse_dtor, impulse_tick, NULL ) )
323 return FALSE;
325 // add ctrl: value
326 //func = make_new_mfun( "float", "value", impulse_ctrl_value );
327 //func->add_arg( "float", "value" );
328 //if( !type_engine_import_mfun( env, func ) ) goto error;
329 // add cget: value
330 //func = make_new_mfun( "float", "value", impulse_cget_value );
331 //if( !type_engine_import_mfun( env, func ) ) goto error;
333 // add member variable
334 impulse_offset_data = type_engine_import_mvar( env, "int", "@impulse_data", FALSE );
335 if( impulse_offset_data == CK_INVALID_OFFSET ) goto error;
337 // add ctrl: next
338 func = make_new_mfun( "float", "next", impulse_ctrl_next );
339 func->add_arg( "float", "next" );
340 if( !type_engine_import_mfun( env, func ) ) goto error;
341 // add cget: next
342 func = make_new_mfun( "float", "next", impulse_cget_next );
343 if( !type_engine_import_mfun( env, func ) ) goto error;
345 // end import
346 if( !type_engine_import_class_end( env ) )
347 return FALSE;
349 // add step
350 //! step generator - like impulse, but once a value is set,
351 //! it is held for all following samples, until value is set again
352 //! see \example step.ck
353 //QUERY->ugen_add( QUERY, "step", NULL );
354 // set funcs
355 //QUERY->ugen_func( QUERY, step_ctor, step_dtor, step_tick, NULL );
356 // ctrl func
357 //QUERY->ugen_ctrl( QUERY, step_ctrl_value, step_cget_value, "float", "value" );
358 //QUERY->ugen_ctrl( QUERY, step_ctrl_value, step_cget_value, "float", "next" ); //! set the step value
359 /*! \example
360 step s => dac;
361 -1.0 => float amp;
363 // square wave using step
364 while( true ) {
365 -amp => amp => s.next;
366 800::samp => now;
369 //---------------------------------------------------------------------
370 // init as base class: step
371 //---------------------------------------------------------------------
372 if( !type_engine_import_ugen_begin( env, "Step", "UGen", env->global(),
373 step_ctor, step_dtor, step_tick, NULL ) )
374 return FALSE;
376 // add ctrl: value
377 //func = make_new_mfun( "float", "value", step_ctrl_value );
378 //func->add_arg( "float", "value" );
379 //if( !type_engine_import_mfun( env, func ) ) goto error;
380 // add cget: value
381 //func = make_new_mfun( "float", "value", step_cget_value );
382 //if( !type_engine_import_mfun( env, func ) ) goto error;
384 // add member variable
385 step_offset_data = type_engine_import_mvar( env, "int", "@step_data", FALSE );
386 if( step_offset_data == CK_INVALID_OFFSET ) goto error;
388 // add ctrl: next
389 func = make_new_mfun( "float", "next", step_ctrl_next );
390 func->add_arg( "float", "next" );
391 if( !type_engine_import_mfun( env, func ) ) goto error;
392 // add cget: next
393 func = make_new_mfun( "float", "next", step_cget_next );
394 if( !type_engine_import_mfun( env, func ) ) goto error;
396 // end import
397 if( !type_engine_import_class_end( env ) )
398 return FALSE;
400 // add halfrect
401 //! half wave rectifier
402 //! for half-wave rectification.
403 //QUERY->ugen_add( QUERY, "halfrect", NULL );
404 // set funcs
405 //QUERY->ugen_func( QUERY, NULL, NULL, halfrect_tick, NULL );
406 //---------------------------------------------------------------------
407 // init as base class: halfrect
408 //---------------------------------------------------------------------
409 if( !type_engine_import_ugen_begin( env, "HalfRect", "UGen", env->global(),
410 NULL, NULL, halfrect_tick, NULL ) )
411 return FALSE;
413 // end import
414 if( !type_engine_import_class_end( env ) )
415 return FALSE;
418 // add fullrect
419 //! full wave rectifier
420 //QUERY->ugen_add( QUERY, "fullrect", NULL );
421 // set funcs
422 //QUERY->ugen_func( QUERY, NULL, NULL, fullrect_tick, NULL );
423 //---------------------------------------------------------------------
424 // init as base class: fullrect
425 //---------------------------------------------------------------------
426 if( !type_engine_import_ugen_begin( env, "FullRect", "UGen", env->global(),
427 NULL, NULL, fullrect_tick, NULL ) )
428 return FALSE;
430 // end import
431 if( !type_engine_import_class_end( env ) )
432 return FALSE;
435 // add zerox
436 //! zero crossing detector
437 //! emits a single pulse at the the zero crossing in the direction of the zero crossing.
438 //! (see \example zerox.ck)
439 //QUERY->ugen_add( QUERY, "zerox", NULL );
440 // set funcs
441 //QUERY->ugen_func( QUERY, zerox_ctor, zerox_dtor, zerox_tick, NULL );
442 //---------------------------------------------------------------------
443 // init as base class: zerox
444 //---------------------------------------------------------------------
445 if( !type_engine_import_ugen_begin( env, "ZeroX", "UGen", env->global(),
446 zerox_ctor, zerox_dtor, zerox_tick, NULL ) )
447 return FALSE;
449 // add member variable
450 zerox_offset_data = type_engine_import_mvar( env, "int", "@zerox_data", FALSE );
451 if( zerox_offset_data == CK_INVALID_OFFSET ) goto error;
453 // end import
454 if( !type_engine_import_class_end( env ) )
455 return FALSE;
458 //! \section delay lines
460 //! delay with varying write position ( instead of read position )
461 //! change to delay length will not affect the delay of samples already in
462 //! the buffer.
463 //! see \example delayp.ck
465 //QUERY->ugen_add( QUERY, "delayp" , NULL);
466 //QUERY->ugen_func ( QUERY, delayp_ctor, delayp_dtor, delayp_tick, delayp_pmsg);
467 //QUERY->ugen_ctrl( QUERY, delayp_ctrl_delay, delayp_cget_delay , "dur", "delay" ); //! delay before subsequent values emerge
468 //QUERY->ugen_ctrl( QUERY, delayp_ctrl_window, delayp_cget_window , "dur", "window" ); //! time for 'write head' to move
469 //QUERY->ugen_ctrl( QUERY, delayp_ctrl_max, delayp_cget_max , "dur", "max" ); //! max delay possible. trashes buffer, so do it first!
471 //---------------------------------------------------------------------
472 // init as base class: delayp
473 //---------------------------------------------------------------------
474 if( !type_engine_import_ugen_begin( env, "DelayP", "UGen", env->global(),
475 delayp_ctor, delayp_dtor,
476 delayp_tick, delayp_pmsg ) )
477 return FALSE;
479 // add member variable
480 delayp_offset_data = type_engine_import_mvar( env, "int", "@delayp_data", FALSE );
481 if( delayp_offset_data == CK_INVALID_OFFSET ) goto error;
483 // add ctrl: delay
484 func = make_new_mfun( "dur", "delay", delayp_ctrl_delay );
485 func->add_arg( "dur", "delay" );
486 if( !type_engine_import_mfun( env, func ) ) goto error;
487 // add cget: delay
488 func = make_new_mfun( "dur", "delay", delayp_cget_delay );
489 if( !type_engine_import_mfun( env, func ) ) goto error;
491 // add ctrl: window
492 func = make_new_mfun( "dur", "window", delayp_ctrl_window );
493 func->add_arg( "dur", "window" );
494 if( !type_engine_import_mfun( env, func ) ) goto error;
495 // add cget: window
496 func = make_new_mfun( "dur", "window", delayp_cget_window );
497 if( !type_engine_import_mfun( env, func ) ) goto error;
499 // add ctrl: max
500 func = make_new_mfun( "dur", "max", delayp_ctrl_max );
501 func->add_arg( "dur", "max" );
502 if( !type_engine_import_mfun( env, func ) ) goto error;
503 // add cget: max
504 func = make_new_mfun( "dur", "max", delayp_cget_max );
505 if( !type_engine_import_mfun( env, func ) ) goto error;
507 // end import
508 if( !type_engine_import_class_end( env ) )
509 return FALSE;
511 //! \section sound files
513 // add sndbuf
514 //! sound buffer ( now interpolating )
515 //! reads from a variety of file formats
516 //! see \example sndbuf.ck
517 //QUERY->ugen_add( QUERY, "sndbuf", NULL );
518 // set funcs
519 //QUERY->ugen_func( QUERY, sndbuf_ctor, sndbuf_dtor, sndbuf_tick, NULL );
520 // set ctrl
521 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_read, NULL, "string", "read" ); //! loads file for reading
522 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_write, NULL, "string", "write" ); //! loads a file for writing ( or not )
523 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_pos, sndbuf_cget_pos, "int", "pos" ); //! set position ( 0 < p < .samples )
524 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_loop, sndbuf_cget_loop, "int", "loop" ); //! toggle looping
525 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_interp, sndbuf_cget_interp, "int", "interp" ); //! set interpolation ( 0=drop, 1=linear, 2=sinc )
526 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_rate, sndbuf_cget_rate, "float", "rate" ); //! playback rate ( relative to file's natural speed )
527 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_rate, sndbuf_cget_rate, "float", "play" ); //! play (same as rate)
528 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_freq, sndbuf_cget_freq, "float", "freq" ); //! playback rate ( file loops / second )
529 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_phase, sndbuf_cget_phase, "float", "phase" ); //! set phase position ( 0-1 )
530 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_channel, sndbuf_cget_channel, "int", "channel" ); //! select channel ( 0 < p < .channels )
531 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_phase_offset, sndbuf_cget_phase, "float", "phase_offset" ); //! set a phase offset
532 //QUERY->ugen_ctrl( QUERY, NULL, sndbuf_cget_samples, "int", "samples" ); //! fetch number of samples
533 //QUERY->ugen_ctrl( QUERY, NULL, sndbuf_cget_length, "dur", "length" ); //! fetch length
534 //QUERY->ugen_ctrl( QUERY, NULL, sndbuf_cget_channels, "int", "channels" ); //! fetch number of channels
536 //---------------------------------------------------------------------
537 // init as base class: sndbuf
538 //---------------------------------------------------------------------
539 if( !type_engine_import_ugen_begin( env, "SndBuf", "UGen", env->global(),
540 sndbuf_ctor, sndbuf_dtor,
541 sndbuf_tick, NULL ) )
542 return FALSE;
544 // add member variable
545 sndbuf_offset_data = type_engine_import_mvar( env, "int", "@sndbuf_data", FALSE );
546 if( sndbuf_offset_data == CK_INVALID_OFFSET ) goto error;
548 // add ctrl: read
549 func = make_new_mfun( "string", "read", sndbuf_ctrl_read );
550 func->add_arg( "string", "read" );
551 if( !type_engine_import_mfun( env, func ) ) goto error;
552 // add cget: read // area
553 //func = make_new_mfun( "string", "read", sndbuf_cget_read );
554 //if( !type_engine_import_mfun( env, func ) ) goto error;
556 // add ctrl: write
557 func = make_new_mfun( "string", "write", sndbuf_ctrl_write );
558 func->add_arg( "string", "read" );
559 if( !type_engine_import_mfun( env, func ) ) goto error;
560 // add cget: write
561 //func = make_new_mfun( "string", "write", sndbuf_cget_write );
562 //if( !type_engine_import_mfun( env, func ) ) goto error;
564 // add ctrl: pos
565 func = make_new_mfun( "int", "pos", sndbuf_ctrl_pos );
566 func->add_arg( "int", "pos" );
567 if( !type_engine_import_mfun( env, func ) ) goto error;
568 // add cget: pos
569 func = make_new_mfun( "int", "pos", sndbuf_cget_pos );
570 if( !type_engine_import_mfun( env, func ) ) goto error;
572 // add ctrl: loop
573 func = make_new_mfun( "int", "loop", sndbuf_ctrl_loop );
574 func->add_arg( "int", "loop" );
575 if( !type_engine_import_mfun( env, func ) ) goto error;
576 // add cget: loop
577 func = make_new_mfun( "int", "loop", sndbuf_cget_loop );
578 if( !type_engine_import_mfun( env, func ) ) goto error;
580 // add ctrl: interp
581 func = make_new_mfun( "int", "interp", sndbuf_ctrl_interp );
582 func->add_arg( "int", "interp" );
583 if( !type_engine_import_mfun( env, func ) ) goto error;
584 // add cget: interp
585 func = make_new_mfun( "int", "interp", sndbuf_cget_interp );
586 if( !type_engine_import_mfun( env, func ) ) goto error;
588 // add ctrl: rate
589 func = make_new_mfun( "float", "rate", sndbuf_ctrl_rate );
590 func->add_arg( "float", "rate" );
591 if( !type_engine_import_mfun( env, func ) ) goto error;
592 // add cget: rate
593 func = make_new_mfun( "float", "rate", sndbuf_cget_rate );
594 if( !type_engine_import_mfun( env, func ) ) goto error;
596 // add ctrl: play
597 func = make_new_mfun( "float", "play", sndbuf_ctrl_rate );
598 func->add_arg( "float", "play" );
599 if( !type_engine_import_mfun( env, func ) ) goto error;
600 // add cget: play // good
601 func = make_new_mfun( "float", "play", sndbuf_cget_rate );
602 if( !type_engine_import_mfun( env, func ) ) goto error;
604 // add ctrl: freq
605 func = make_new_mfun( "float", "freq", sndbuf_ctrl_freq );
606 func->add_arg( "float", "freq" );
607 if( !type_engine_import_mfun( env, func ) ) goto error;
608 // add cget: freq
609 func = make_new_mfun( "float", "freq", sndbuf_cget_freq );
610 if( !type_engine_import_mfun( env, func ) ) goto error;
612 // add ctrl: phase
613 func = make_new_mfun( "float", "phase", sndbuf_ctrl_phase );
614 func->add_arg( "float", "phase" );
615 if( !type_engine_import_mfun( env, func ) ) goto error;
616 // add cget: phase
617 func = make_new_mfun( "float", "phase", sndbuf_cget_phase );
618 if( !type_engine_import_mfun( env, func ) ) goto error;
620 // add ctrl: channel
621 func = make_new_mfun( "int", "channel", sndbuf_ctrl_channel );
622 func->add_arg( "int", "channel" );
623 if( !type_engine_import_mfun( env, func ) ) goto error;
624 // add cget: channel
625 func = make_new_mfun( "int", "channel", sndbuf_cget_channel );
626 if( !type_engine_import_mfun( env, func ) ) goto error;
628 // add ctrl: phase_offset
629 func = make_new_mfun( "float", "phaseOffset", sndbuf_ctrl_phase_offset );
630 func->add_arg( "float", "value" );
631 if( !type_engine_import_mfun( env, func ) ) goto error;
632 // add cget: phase_offset
633 // func = make_new_mfun( "float", "phaseOffset", sndbuf_cget_phase_offset );
634 // if( !type_engine_import_mfun( env, func ) ) goto error;
636 // add ctrl: chunks
637 func = make_new_mfun( "int", "chunks", sndbuf_ctrl_chunks );
638 func->add_arg( "int", "frames" );
639 if( !type_engine_import_mfun( env, func ) ) goto error;
640 // add cget: chunks
641 func = make_new_mfun( "int", "chunks", sndbuf_cget_chunks );
642 if( !type_engine_import_mfun( env, func ) ) goto error;
644 // add cget: samples
645 func = make_new_mfun( "int", "samples", sndbuf_cget_samples );
646 if( !type_engine_import_mfun( env, func ) ) goto error;
648 // add cget: length
649 func = make_new_mfun( "dur", "length", sndbuf_cget_length );
650 if( !type_engine_import_mfun( env, func ) ) goto error;
652 // add cget: channels
653 func = make_new_mfun( "int", "channels", sndbuf_cget_channels );
654 if( !type_engine_import_mfun( env, func ) ) goto error;
656 // add cget: valueAt
657 func = make_new_mfun( "float", "valueAt", sndbuf_cget_valueAt );
658 func->add_arg( "int", "pos" );
659 if( !type_engine_import_mfun( env, func ) ) goto error;
661 // end import
662 if( !type_engine_import_class_end( env ) )
663 return FALSE;
665 //---------------------------------------------------------------------
666 // init as base class: Dyno
667 //---------------------------------------------------------------------
668 if( !type_engine_import_ugen_begin( env, "Dyno", "UGen", env->global(),
669 dyno_ctor, dyno_dtor, dyno_tick, NULL ) )
670 return FALSE;
672 // add member variable
673 dyno_offset_data = type_engine_import_mvar( env, "int", "@dyno_data", FALSE );
674 if( dyno_offset_data == CK_INVALID_OFFSET ) goto error;
676 // add ctrl: limit
677 func = make_new_mfun( "void", "limit", dyno_ctrl_limit );
678 //func->add_arg( "string", "mode" );
679 if( !type_engine_import_mfun( env, func ) ) goto error;
681 // add ctrl: compress
682 func = make_new_mfun( "void", "compress", dyno_ctrl_compress );
683 //func->add_arg( "string", "mode" );
684 if( !type_engine_import_mfun( env, func ) ) goto error;
686 // add ctrl: gate
687 func = make_new_mfun( "void", "gate", dyno_ctrl_gate );
688 //func->add_arg( "string", "mode" );
689 if( !type_engine_import_mfun( env, func ) ) goto error;
691 // add ctrl: expand
692 func = make_new_mfun( "void", "expand", dyno_ctrl_expand );
693 //func->add_arg( "string", "mode" );
694 if( !type_engine_import_mfun( env, func ) ) goto error;
696 // add ctrl: duck
697 func = make_new_mfun( "void", "duck", dyno_ctrl_duck );
698 //func->add_arg( "string", "mode" );
699 if( !type_engine_import_mfun( env, func ) ) goto error;
701 //add ctrl: thresh
702 func = make_new_mfun( "float", "thresh", dyno_ctrl_thresh );
703 func->add_arg( "float", "thresh" );
704 if( !type_engine_import_mfun( env, func ) ) goto error;
706 // add cget: thresh
707 func = make_new_mfun( "float", "thresh", dyno_cget_thresh );
708 if( !type_engine_import_mfun( env, func ) ) goto error;
710 //add ctrl: attackTime
711 func = make_new_mfun( "dur", "attackTime", dyno_ctrl_attackTime );
712 func->add_arg( "dur", "aTime" );
713 if( !type_engine_import_mfun( env, func ) ) goto error;
715 //add cget: attackTime
716 func = make_new_mfun( "dur", "attackTime", dyno_ctrl_attackTime );
717 if( !type_engine_import_mfun( env, func ) ) goto error;
719 //add ctrl: releaseTime
720 func = make_new_mfun( "dur", "releaseTime", dyno_ctrl_releaseTime );
721 func->add_arg( "dur", "rTime" );
722 if( !type_engine_import_mfun( env, func ) ) goto error;
724 //add ctrl: releaseTime
725 func = make_new_mfun( "dur", "releaseTime", dyno_ctrl_releaseTime );
726 if( !type_engine_import_mfun( env, func ) ) goto error;
728 //add ctrl: ratio
729 func = make_new_mfun( "float", "ratio", dyno_ctrl_ratio );
730 func->add_arg( "float", "ratio" );
731 if( !type_engine_import_mfun( env, func ) ) goto error;
733 //add cget: ratio
734 func = make_new_mfun( "float", "ratio", dyno_cget_ratio );
735 if( !type_engine_import_mfun( env, func ) ) goto error;
737 //add ctrl: slopeBelow
738 func = make_new_mfun( "float", "slopeBelow", dyno_ctrl_slopeBelow );
739 func->add_arg( "float", "slopeBelow" );
740 if( !type_engine_import_mfun( env, func ) ) goto error;
742 //add cget: slopeBelow
743 func = make_new_mfun( "float", "slopeBelow", dyno_cget_slopeBelow );
744 if( !type_engine_import_mfun( env, func ) ) goto error;
746 //add ctrl: slopeAbove
747 func = make_new_mfun( "float", "slopeAbove", dyno_ctrl_slopeAbove );
748 func->add_arg( "float", "slopeAbove" );
749 if( !type_engine_import_mfun( env, func ) ) goto error;
751 //add cget: slopeAbove
752 func = make_new_mfun( "float", "slopeAbove", dyno_cget_slopeAbove );
753 if( !type_engine_import_mfun( env, func ) ) goto error;
755 //add ctrl: sideInput
756 func = make_new_mfun( "float", "sideInput", dyno_ctrl_sideInput );
757 func->add_arg( "float", "sideInput" );
758 if( !type_engine_import_mfun( env, func ) ) goto error;
760 //add cget: sideInput
761 func = make_new_mfun( "float", "sideInput", dyno_cget_sideInput );
762 if( !type_engine_import_mfun( env, func ) ) goto error;
764 //add ctrl: externalSideInput
765 func = make_new_mfun( "int", "externalSideInput", dyno_ctrl_externalSideInput );
766 func->add_arg( "int", "externalSideInput" );
767 if( !type_engine_import_mfun( env, func ) ) goto error;
769 //add cget: externalSideInput
770 func = make_new_mfun( "int", "externalSideInput", dyno_cget_externalSideInput );
771 if( !type_engine_import_mfun( env, func ) ) goto error;
773 // end import
774 if( !type_engine_import_class_end( env ) )
775 return FALSE;
777 // import LiSa!
778 if( !lisa_query( QUERY ) )
779 return FALSE;
781 return TRUE;
783 error:
785 // end the class import
786 type_engine_import_class_end( env );
788 return FALSE;
794 // LiSa (live sampling data offset)
795 static t_CKUINT LiSaBasic_offset_data = 0;
796 static t_CKUINT LiSaMulti_offset_data = 0;
798 //-----------------------------------------------------------------------------
799 // name: lisa_query()
800 // desc: ...
801 //-----------------------------------------------------------------------------
802 DLL_QUERY lisa_query( Chuck_DL_Query * QUERY )
804 Chuck_Env * env = Chuck_Env::instance();
805 Chuck_DL_Func * func = NULL;
807 //---------------------------------------------------------------------
808 // init class: LiSa; overloaded class for both LiSaBasic and LiSaMulti
809 // - probably don't need the others anymore....
810 // author: Dan Trueman (dan /at/ music.princeton.edu)
811 //---------------------------------------------------------------------
812 if( !type_engine_import_ugen_begin( env, "LiSa", "UGen", env->global(),
813 LiSaMulti_ctor, LiSaMulti_dtor,
814 LiSaMulti_tick, LiSaMulti_pmsg ) )
815 return FALSE;
817 // set/get buffer size
818 func = make_new_mfun( "dur", "duration", LiSaMulti_size );
819 func->add_arg( "dur", "val" );
820 if( !type_engine_import_mfun( env, func ) ) goto error;
821 func = make_new_mfun( "dur", "duration", LiSaMulti_cget_size );
822 if( !type_engine_import_mfun( env, func ) ) goto error;
824 // start/stop recording
825 func = make_new_mfun( "int", "record", LiSaMulti_start_record );
826 func->add_arg( "int", "toggle" );
827 if( !type_engine_import_mfun( env, func ) ) goto error;
829 // start/stop playing
830 func = make_new_mfun( "int", "play", LiSaMulti_start_play );
831 func->add_arg( "int", "voice" );
832 func->add_arg( "int", "toggle" );
833 if( !type_engine_import_mfun( env, func ) ) goto error;
834 func = make_new_mfun( "int", "play", LiSaMulti_start_play0 );
835 func->add_arg( "int", "toggle" );
836 if( !type_engine_import_mfun( env, func ) ) goto error;
838 // set/get playback rate
839 func = make_new_mfun( "float", "rate", LiSaMulti_ctrl_rate );
840 func->add_arg( "int", "voice" );
841 func->add_arg( "float", "val" );
842 if( !type_engine_import_mfun( env, func ) ) goto error;
843 func = make_new_mfun( "float", "rate", LiSaMulti_cget_rate );
844 func->add_arg( "int", "voice" );
845 if( !type_engine_import_mfun( env, func ) ) goto error;
846 func = make_new_mfun( "float", "rate", LiSaMulti_ctrl_rate0 );
847 func->add_arg( "float", "val" );
848 if( !type_engine_import_mfun( env, func ) ) goto error;
849 func = make_new_mfun( "float", "rate", LiSaMulti_cget_rate0 );
850 if( !type_engine_import_mfun( env, func ) ) goto error;
852 // playback position
853 func = make_new_mfun( "dur", "playPos", LiSaMulti_ctrl_pindex );
854 func->add_arg( "int", "voice" );
855 func->add_arg( "dur", "val" );
856 if( !type_engine_import_mfun( env, func ) ) goto error;
857 func = make_new_mfun( "dur", "playPos", LiSaMulti_cget_pindex );
858 func->add_arg( "int", "voice" );
859 if( !type_engine_import_mfun( env, func ) ) goto error;
860 func = make_new_mfun( "dur", "playPos", LiSaMulti_ctrl_pindex0 );
861 func->add_arg( "dur", "val" );
862 if( !type_engine_import_mfun( env, func ) ) goto error;
863 func = make_new_mfun( "dur", "playPos", LiSaMulti_cget_pindex0 );
864 if( !type_engine_import_mfun( env, func ) ) goto error;
866 // record position
867 func = make_new_mfun( "dur", "recPos", LiSaMulti_ctrl_rindex );
868 func->add_arg( "dur", "val" );
869 if( !type_engine_import_mfun( env, func ) ) goto error;
870 func = make_new_mfun( "dur", "recPos", LiSaMulti_cget_rindex );
871 if( !type_engine_import_mfun( env, func ) ) goto error;
873 // loopstart position
874 func = make_new_mfun( "dur", "loopStart", LiSaMulti_ctrl_lstart );
875 func->add_arg( "int", "voice" );
876 func->add_arg( "dur", "val" );
877 if( !type_engine_import_mfun( env, func ) ) goto error;
878 func = make_new_mfun( "dur", "loopStart", LiSaMulti_cget_lstart );
879 func->add_arg( "int", "voice" );
880 if( !type_engine_import_mfun( env, func ) ) goto error;
881 func = make_new_mfun( "dur", "loopStart", LiSaMulti_ctrl_lstart0 );
882 func->add_arg( "dur", "val" );
883 if( !type_engine_import_mfun( env, func ) ) goto error;
884 func = make_new_mfun( "dur", "loopStart", LiSaMulti_cget_lstart0 );
885 if( !type_engine_import_mfun( env, func ) ) goto error;
887 // loopend position
888 func = make_new_mfun( "dur", "loopEnd", LiSaMulti_ctrl_lend );
889 func->add_arg( "int", "voice" );
890 func->add_arg( "dur", "val" );
891 if( !type_engine_import_mfun( env, func ) ) goto error;
892 func = make_new_mfun( "dur", "loopEnd", LiSaMulti_cget_lend);
893 func->add_arg( "int", "voice" );
894 if( !type_engine_import_mfun( env, func ) ) goto error;
895 func = make_new_mfun( "dur", "loopEnd", LiSaMulti_ctrl_lend0 );
896 func->add_arg( "dur", "val" );
897 if( !type_engine_import_mfun( env, func ) ) goto error;
898 func = make_new_mfun( "dur", "loopEnd", LiSaMulti_cget_lend0);
899 if( !type_engine_import_mfun( env, func ) ) goto error;
901 // loop
902 func = make_new_mfun( "int", "loop", LiSaMulti_ctrl_loop );
903 func->add_arg( "int", "voice" );
904 func->add_arg( "int", "val" );
905 if( !type_engine_import_mfun( env, func ) ) goto error;
906 func = make_new_mfun( "int", "loop", LiSaMulti_cget_loop);
907 func->add_arg( "int", "voice" );
908 if( !type_engine_import_mfun( env, func ) ) goto error;
909 func = make_new_mfun( "int", "loop", LiSaMulti_ctrl_loop0 );
910 func->add_arg( "int", "val" );
911 if( !type_engine_import_mfun( env, func ) ) goto error;
912 func = make_new_mfun( "int", "loop", LiSaMulti_cget_loop0);
913 if( !type_engine_import_mfun( env, func ) ) goto error;
915 // bidirectional looping
916 func = make_new_mfun( "int", "bi", LiSaMulti_ctrl_bi );
917 func->add_arg( "int", "voice" );
918 func->add_arg( "int", "val" );
919 if( !type_engine_import_mfun( env, func ) ) goto error;
920 func = make_new_mfun( "int", "bi", LiSaMulti_cget_bi);
921 func->add_arg( "int", "voice" );
922 if( !type_engine_import_mfun( env, func ) ) goto error;
923 func = make_new_mfun( "int", "bi", LiSaMulti_ctrl_bi0 );
924 func->add_arg( "int", "val" );
925 if( !type_engine_import_mfun( env, func ) ) goto error;
926 func = make_new_mfun( "int", "bi", LiSaMulti_cget_bi0);
927 if( !type_engine_import_mfun( env, func ) ) goto error;
929 // loopend_rec position
930 func = make_new_mfun( "dur", "loopEndRec", LiSaMulti_ctrl_loop_end_rec );
931 func->add_arg( "dur", "val" );
932 if( !type_engine_import_mfun( env, func ) ) goto error;
933 func = make_new_mfun( "dur", "loopEndRec", LiSaMulti_cget_loop_end_rec);
934 if( !type_engine_import_mfun( env, func ) ) goto error;
936 // loop_rec toggle set; for turning on/off loop recording
937 func = make_new_mfun( "int", "loopRec", LiSaMulti_ctrl_loop_rec );
938 func->add_arg( "int", "val" );
939 if( !type_engine_import_mfun( env, func ) ) goto error;
940 func = make_new_mfun( "int", "loopRec", LiSaMulti_cget_loop_rec);
941 if( !type_engine_import_mfun( env, func ) ) goto error;
943 // look at or put sample directly in record buffer, do not pass go
944 func = make_new_mfun( "float", "valueAt", LiSaMulti_ctrl_sample );
945 func->add_arg( "float", "val" );
946 func->add_arg( "dur", "index" );
947 if( !type_engine_import_mfun( env, func ) ) goto error;
948 func = make_new_mfun( "float", "valueAt", LiSaMulti_cget_sample);
949 func->add_arg( "dur", "index" );
950 if( !type_engine_import_mfun( env, func ) ) goto error;
952 // set/get voiceGain
953 func = make_new_mfun( "float", "voiceGain", LiSaMulti_ctrl_voicegain );
954 func->add_arg( "int", "voice" );
955 func->add_arg( "float", "val" );
956 if( !type_engine_import_mfun( env, func ) ) goto error;
957 func = make_new_mfun( "float", "voiceGain", LiSaMulti_cget_voicegain);
958 func->add_arg( "int", "voice" );
960 // set record feedback coefficient
961 func = make_new_mfun( "float", "feedback", LiSaMulti_ctrl_coeff );
962 func->add_arg( "float", "val" );
963 if( !type_engine_import_mfun( env, func ) ) goto error;
964 func = make_new_mfun( "float", "feedback", LiSaMulti_cget_coeff);
965 if( !type_engine_import_mfun( env, func ) ) goto error;
967 // clear buffer
968 func = make_new_mfun( "void", "clear", LiSaMulti_ctrl_clear );
969 if( !type_engine_import_mfun( env, func ) ) goto error;
971 // get free voice
972 func = make_new_mfun( "int", "getVoice", LiSaMulti_cget_voice );
973 if( !type_engine_import_mfun( env, func ) ) goto error;
975 // set maxvoices
976 func = make_new_mfun( "int", "maxVoices", LiSaMulti_ctrl_maxvoices );
977 func->add_arg( "int", "val" );
978 if( !type_engine_import_mfun( env, func ) ) goto error;
979 func = make_new_mfun( "int", "maxVoices", LiSaMulti_cget_maxvoices);
980 if( !type_engine_import_mfun( env, func ) ) goto error;
982 // ramp stuff
983 func = make_new_mfun( "void", "rampUp", LiSaMulti_ctrl_rampup );
984 func->add_arg( "int", "voice" );
985 func->add_arg( "dur", "val" );
986 if( !type_engine_import_mfun( env, func ) ) goto error;
988 func = make_new_mfun( "void", "rampDown", LiSaMulti_ctrl_rampdown );
989 func->add_arg( "int", "voice" );
990 func->add_arg( "dur", "val" );
991 if( !type_engine_import_mfun( env, func ) ) goto error;
993 func = make_new_mfun( "dur", "recRamp", LiSaMulti_ctrl_rec_ramplen );
994 func->add_arg( "dur", "val" );
995 if( !type_engine_import_mfun( env, func ) ) goto error;
997 func = make_new_mfun( "void", "rampUp", LiSaMulti_ctrl_rampup0 );
998 func->add_arg( "dur", "val" );
999 if( !type_engine_import_mfun( env, func ) ) goto error;
1001 func = make_new_mfun( "void", "rampDown", LiSaMulti_ctrl_rampdown0 );
1002 func->add_arg( "dur", "val" );
1003 if( !type_engine_import_mfun( env, func ) ) goto error;
1005 // get value
1006 func = make_new_mfun( "dur", "value", LiSaMulti_cget_value );
1007 func->add_arg( "int", "voice" );
1008 func->add_arg( "dur", "val" );
1009 if( !type_engine_import_mfun( env, func ) ) goto error;
1010 func = make_new_mfun( "dur", "value", LiSaMulti_cget_value0 );
1011 func->add_arg( "dur", "val" );
1012 if( !type_engine_import_mfun( env, func ) ) goto error;
1014 // track
1015 func = make_new_mfun( "int", "track", LiSaMulti_ctrl_track );
1016 func->add_arg( "int", "val" );
1017 if( !type_engine_import_mfun( env, func ) ) goto error;
1018 func = make_new_mfun( "int", "track", LiSaMulti_cget_track);
1019 if( !type_engine_import_mfun( env, func ) ) goto error;
1021 // sync = track
1022 func = make_new_mfun( "int", "sync", LiSaMulti_ctrl_track );
1023 func->add_arg( "int", "val" );
1024 if( !type_engine_import_mfun( env, func ) ) goto error;
1025 func = make_new_mfun( "int", "sync", LiSaMulti_cget_track);
1026 if( !type_engine_import_mfun( env, func ) ) goto error;
1028 // sync = track
1029 func = make_new_mfun( "int", "sync", LiSaMulti_ctrl_track );
1030 func->add_arg( "int", "val" );
1031 if( !type_engine_import_mfun( env, func ) ) goto error;
1032 func = make_new_mfun( "int", "sync", LiSaMulti_cget_track);
1033 if( !type_engine_import_mfun( env, func ) ) goto error;
1035 // end the class import
1036 type_engine_import_class_end( env );
1038 return TRUE;
1040 error:
1042 // end the class import
1043 type_engine_import_class_end( env );
1045 return FALSE;
1051 //-----------------------------------------------------------------------------
1052 // name: multi_ctor()
1053 // desc: ...
1054 //-----------------------------------------------------------------------------
1055 CK_DLL_CTOR( multi_ctor )
1057 // do nothing
1063 //-----------------------------------------------------------------------------
1064 // name: multi_cget_chan()
1065 // desc: ...
1066 //-----------------------------------------------------------------------------
1067 CK_DLL_CGET( multi_cget_chan )
1069 // get ugen
1070 Chuck_UGen * ugen = (Chuck_UGen *)SELF;
1071 // value
1072 t_CKINT index = GET_NEXT_INT( ARGS );
1073 // return
1074 RETURN->v_object = index >= 0 && index < ugen->m_multi_chan_size ?
1075 ugen->m_multi_chan[index] : NULL ;
1081 //-----------------------------------------------------------------------------
1082 // name: stereo_ctor()
1083 // desc: ...
1084 //-----------------------------------------------------------------------------
1085 CK_DLL_CTOR( stereo_ctor )
1087 // get ugen
1088 Chuck_UGen * ugen = (Chuck_UGen *)SELF;
1090 // multi
1091 if( ugen->m_multi_chan_size )
1093 // set left
1094 OBJ_MEMBER_UINT(SELF, stereo_offset_left) = (t_CKUINT)(ugen->m_multi_chan[0]);
1095 // set right
1096 OBJ_MEMBER_UINT(SELF, stereo_offset_right) = (t_CKUINT)(ugen->m_multi_chan[1]);
1098 else // mono
1100 // set left and right to self
1101 OBJ_MEMBER_UINT(SELF, stereo_offset_left) = (t_CKUINT)ugen;
1102 OBJ_MEMBER_UINT(SELF, stereo_offset_right) = (t_CKUINT)ugen;
1109 //-----------------------------------------------------------------------------
1110 // name: stereo_ctrl_pan()
1111 // desc: ...
1112 //-----------------------------------------------------------------------------
1113 CK_DLL_CTRL( stereo_ctrl_pan )
1115 Chuck_UGen * ugen = (Chuck_UGen * )SELF;
1116 Chuck_UGen * left = ugen->m_multi_chan[0];
1117 Chuck_UGen * right = ugen->m_multi_chan[1];
1118 // get arg
1119 t_CKFLOAT pan = GET_CK_FLOAT(ARGS);
1120 // clip it
1121 if( pan < -1.0 ) pan = -1.0;
1122 else if( pan > 1.0 ) pan = 1.0;
1123 // set it
1124 OBJ_MEMBER_FLOAT(SELF, stereo_offset_pan) = pan;
1125 // pan it
1126 left->m_pan = pan < 0.0 ? 1.0 : 1.0 - pan;
1127 right->m_pan = pan > 0.0 ? 1.0 : 1.0 + pan;
1129 RETURN->v_float = pan;
1135 //-----------------------------------------------------------------------------
1136 // name: stereo_cget_pan()
1137 // desc: ...
1138 //-----------------------------------------------------------------------------
1139 CK_DLL_CGET( stereo_cget_pan )
1141 RETURN->v_float = OBJ_MEMBER_FLOAT(SELF, stereo_offset_pan);
1147 //-----------------------------------------------------------------------------
1148 // name: dac_tick()
1149 // desc: ...
1150 //-----------------------------------------------------------------------------
1151 CK_DLL_TICK( dac_tick )
1153 *out = in; return TRUE;
1159 //-----------------------------------------------------------------------------
1160 // name: bunghole_tick
1161 // desc: ...
1162 //-----------------------------------------------------------------------------
1163 CK_DLL_TICK( bunghole_tick )
1165 *out = 0.0f; return 0;
1171 //-----------------------------------------------------------------------------
1172 // name: noise_tick()
1173 // desc: ...
1174 //-----------------------------------------------------------------------------
1175 CK_DLL_TICK( noise_tick )
1177 *out = -1.0 + 2.0 * (SAMPLE)rand() / RAND_MAX;
1178 return TRUE;
1182 enum { NOISE_WHITE=0, NOISE_PINK, NOISE_BROWN, NOISE_FBM, NOISE_FLIP, NOISE_XOR };
1184 class CNoise_Data
1186 private:
1187 SAMPLE value;
1189 t_CKFLOAT fbmH;
1190 t_CKINT counter;
1191 t_CKINT * pink_array;
1192 t_CKINT pink_depth;
1193 bool pink_rand;
1194 t_CKINT rand_bits;
1195 double scale;
1196 double bias;
1198 t_CKINT last;
1200 public:
1201 CNoise_Data() {
1202 value = 0;
1203 mode = NOISE_PINK;
1204 pink_depth = 24;
1205 pink_array = NULL;
1206 counter = 1;
1207 scale = 2.0 / (double) RAND_MAX ;
1208 bias = -1.0;
1209 pink_rand = false;
1210 t_CKINT randt = RAND_MAX;
1211 rand_bits = 0;
1212 fprob = (t_CKINT)( (double)RAND_MAX * 1.0 / 32.0 );
1213 while ( randt > 0 ) {
1214 rand_bits++;
1215 randt = randt >> 1;
1217 // fprintf(stderr, "random bits - %d", rand_bits );
1218 setMode ( "pink" );
1220 ~CNoise_Data() {}
1222 t_CKINT fprob;
1223 t_CKUINT mode;
1224 void tick( t_CKTIME now, SAMPLE * out );
1225 void setMode(char * c);
1227 t_CKINT pink_tick( SAMPLE * out);
1228 t_CKINT brown_tick( SAMPLE * out);
1229 t_CKINT xor_tick( SAMPLE * out);
1230 t_CKINT flip_tick( SAMPLE * out);
1231 t_CKINT fbm_tick( SAMPLE * out);
1235 CK_DLL_CTOR( cnoise_ctor )
1237 OBJ_MEMBER_UINT(SELF, cnoise_offset_data) = (t_CKUINT)new CNoise_Data;
1240 CK_DLL_DTOR( cnoise_dtor )
1242 delete (CNoise_Data *)OBJ_MEMBER_UINT(SELF, cnoise_offset_data);
1243 OBJ_MEMBER_UINT(SELF, cnoise_offset_data) = 0;
1246 CK_DLL_TICK( cnoise_tick )
1248 CNoise_Data * d = ( CNoise_Data * )OBJ_MEMBER_UINT(SELF, cnoise_offset_data);
1249 switch( d->mode ) {
1250 case NOISE_WHITE:
1251 return noise_tick(SELF,in,out,SHRED);
1252 break;
1253 case NOISE_PINK:
1254 return d->pink_tick(out);
1255 break;
1256 case NOISE_BROWN:
1257 return d->brown_tick(out);
1258 break;
1259 case NOISE_XOR:
1260 return d->xor_tick(out);
1261 break;
1262 case NOISE_FLIP:
1263 return d->flip_tick(out);
1264 break;
1265 case NOISE_FBM:
1266 return d->fbm_tick(out);
1267 break;
1269 return TRUE;
1272 t_CKINT CNoise_Data::pink_tick( SAMPLE * out )
1274 //based on Voss-McCartney
1276 if ( pink_array == NULL ) {
1277 pink_array = (t_CKINT *) malloc ( sizeof ( t_CKINT ) * pink_depth );
1278 last = 0;
1279 for ( t_CKINT i = 0 ; i < pink_depth ; i++ ) { pink_array[i] = rand(); last += pink_array[i]; }
1280 scale = 2.0 / ((double)RAND_MAX * ( pink_depth + 1.0 ) );
1281 bias = 0.0;
1282 // fprintf( stderr, "scale %f %f %d %d \n", scale, bias, RAND_MAX, pink_depth + 1 );
1285 t_CKINT pind = 0;
1287 //count trailing zeroes
1288 while ( pind < pink_depth && ! (counter & ( 1 << pind ) ) ) pind++;
1290 // fprintf (stderr, "counter %d pink - %d \n", counter, pind );
1292 if ( pind < pink_depth ) {
1293 t_CKINT diff = rand() - pink_array[pind];
1294 pink_array[pind] += diff;
1295 last += diff;
1298 *out = bias + scale * ( rand() + last );
1299 counter++;
1300 if ( pink_rand ) counter = rand();
1301 return TRUE;
1304 t_CKINT CNoise_Data::xor_tick( SAMPLE * out )
1306 t_CKINT mask = 0;
1307 for ( t_CKINT i = 0; i < rand_bits ; i++ )
1308 if ( rand() <= fprob )
1309 mask |= ( 1 << i );
1310 last = last ^ mask;
1311 *out = bias + scale * (SAMPLE)last;
1312 return TRUE;
1315 t_CKINT CNoise_Data::flip_tick( SAMPLE * out )
1317 t_CKINT ind = (t_CKINT) ( (double) rand_bits * rand() / ( RAND_MAX + 1.0 ) );
1319 last = last ^ ( 1 << ind );
1320 // fprintf ( stderr, "ind - %d %d %f %f", ind, last, bias, scale );
1321 *out = bias + scale * (SAMPLE)last;
1322 return TRUE;
1325 t_CKINT
1326 CNoise_Data::brown_tick( SAMPLE * out ) {
1327 //brownian noise function..later!
1328 *out = 0;
1329 return TRUE;
1332 t_CKINT
1333 CNoise_Data::fbm_tick( SAMPLE * out ) {
1334 //non-brownian noise function..later!
1335 *out = 0;
1336 return TRUE;
1339 void
1340 CNoise_Data::setMode( char * c ) {
1341 if ( strcmp ( c, "white" ) == 0 ) {
1342 // fprintf(stderr, "white noise\n");
1343 mode = NOISE_WHITE;
1344 scale = 2.0 / (t_CKFLOAT)RAND_MAX;
1345 bias = -1.0;
1347 if ( strcmp ( c, "pink" ) == 0 ) {
1348 // fprintf(stderr, "pink noise\n");
1349 mode = NOISE_PINK;
1350 scale = 2.0 / (double)(RAND_MAX * ( pink_depth + 1 ) );
1351 bias = -1.0;
1353 if ( strcmp ( c, "flip" ) == 0) {
1354 // fprintf(stderr, "bitflip noise\n");
1355 mode = NOISE_FLIP;
1356 scale = 2.0 / (t_CKFLOAT)RAND_MAX;
1357 bias = -1.0;
1359 if ( strcmp ( c, "xor" ) == 0) {
1360 // fprintf(stderr, "xor noise\n");
1361 mode = NOISE_XOR;
1362 scale = 2.0 / (t_CKFLOAT)RAND_MAX;
1363 bias = -1.0;
1365 if ( strcmp ( c, "brown" ) == 0) {
1366 // fprintf(stderr, "brownian noise\n");
1367 mode = NOISE_BROWN;
1368 scale = 2.0 / (t_CKFLOAT)RAND_MAX;
1369 bias = -1.0;
1371 if ( strcmp ( c, "fbm" ) == 0) {
1372 // fprintf(stderr, "fbm noise\n");
1373 mode = NOISE_FBM;
1374 scale = 2.0 / (t_CKFLOAT)RAND_MAX;
1375 bias = -1.0;
1380 CK_DLL_CTRL( cnoise_ctrl_mode )
1382 CNoise_Data * d = ( CNoise_Data * )OBJ_MEMBER_UINT(SELF, cnoise_offset_data);
1383 char * mode= *(char **)GET_CK_STRING(ARGS);
1384 d->setMode(mode);
1387 CK_DLL_CTRL( cnoise_ctrl_fprob )
1389 CNoise_Data * d = ( CNoise_Data * )OBJ_MEMBER_UINT(SELF, cnoise_offset_data);
1390 t_CKFLOAT p= GET_CK_FLOAT(ARGS);
1391 d->fprob = (t_CKINT) ( (double)RAND_MAX * p );
1396 //-----------------------------------------------------------------------------
1397 // name: struct Pulse_Data
1398 // desc: ...
1399 //-----------------------------------------------------------------------------
1400 struct Pulse_Data
1402 SAMPLE value;
1403 t_CKUINT when;
1404 Pulse_Data( ) { value = 1.0f; when = 0; }
1408 //-----------------------------------------------------------------------------
1409 // name: impulse_ctor()
1410 // desc: ...
1411 //-----------------------------------------------------------------------------
1412 CK_DLL_CTOR( impulse_ctor )
1414 // return data to be used later
1415 OBJ_MEMBER_UINT(SELF, impulse_offset_data) = (t_CKUINT)new Pulse_Data;
1421 //-----------------------------------------------------------------------------
1422 // name: impulse_dtor()
1423 // desc: ...
1424 //-----------------------------------------------------------------------------
1425 CK_DLL_DTOR( impulse_dtor )
1427 // delete
1428 delete (Pulse_Data *)OBJ_MEMBER_UINT(SELF, impulse_offset_data);
1429 OBJ_MEMBER_UINT(SELF, impulse_offset_data) = 0;
1435 //-----------------------------------------------------------------------------
1436 // name: impulse_tick()
1437 // desc: ...
1438 //-----------------------------------------------------------------------------
1439 CK_DLL_TICK( impulse_tick )
1441 Pulse_Data * d = (Pulse_Data *)OBJ_MEMBER_UINT(SELF, impulse_offset_data);
1442 if( d->when )
1444 *out = d->value;
1445 d->when = 0;
1447 else
1448 *out = 0.0f;
1450 return TRUE;
1455 //-----------------------------------------------------------------------------
1456 // name: impulse_ctrl_next()
1457 // desc: ...
1458 //-----------------------------------------------------------------------------
1459 CK_DLL_CTRL( impulse_ctrl_next )
1461 Pulse_Data * d = (Pulse_Data *)OBJ_MEMBER_UINT(SELF, impulse_offset_data);
1462 d->value = (SAMPLE)GET_CK_FLOAT(ARGS);
1463 d->when = 1;
1464 RETURN->v_float = (t_CKFLOAT)d->value;
1470 //-----------------------------------------------------------------------------
1471 // name: impulse_cget_next()
1472 // desc: ...
1473 //-----------------------------------------------------------------------------
1474 CK_DLL_CGET( impulse_cget_next )
1476 Pulse_Data * d = (Pulse_Data *)OBJ_MEMBER_UINT(SELF, impulse_offset_data);
1477 RETURN->v_float = (t_CKFLOAT)d->value;
1483 //-----------------------------------------------------------------------------
1484 // name: step_ctor()
1485 // desc: ...
1486 //-----------------------------------------------------------------------------
1487 CK_DLL_CTOR( step_ctor )
1489 // return data to be used later
1490 OBJ_MEMBER_UINT(SELF, step_offset_data) = (t_CKUINT)new SAMPLE( 1.0f );
1496 //-----------------------------------------------------------------------------
1497 // name: step_dtor()
1498 // desc: ...
1499 //-----------------------------------------------------------------------------
1500 CK_DLL_DTOR( step_dtor )
1502 // delete
1503 delete (SAMPLE *)OBJ_MEMBER_UINT(SELF, step_offset_data);
1504 OBJ_MEMBER_UINT(SELF, step_offset_data) = 0;
1508 //-----------------------------------------------------------------------------
1509 // name: step_tick()
1510 // desc: ...
1511 //-----------------------------------------------------------------------------
1512 CK_DLL_TICK( step_tick )
1514 SAMPLE * d = (SAMPLE *)OBJ_MEMBER_UINT(SELF, step_offset_data);
1515 *out = *d;
1517 return TRUE;
1521 //-----------------------------------------------------------------------------
1522 // name: step_ctrl_next()
1523 // desc: ...
1524 //-----------------------------------------------------------------------------
1525 CK_DLL_CTRL( step_ctrl_next )
1527 SAMPLE * d = (SAMPLE *)OBJ_MEMBER_UINT(SELF, step_offset_data);
1528 *d = (SAMPLE)GET_CK_FLOAT(ARGS);
1529 RETURN->v_float = (t_CKFLOAT)(*d);
1533 //-----------------------------------------------------------------------------
1534 // name: step_cget_next()
1535 // desc: ...
1536 //-----------------------------------------------------------------------------
1537 CK_DLL_CGET( step_cget_next )
1539 SAMPLE * d = (SAMPLE *)OBJ_MEMBER_UINT(SELF, step_offset_data);
1540 RETURN->v_float = (t_CKFLOAT)(*d);
1546 //-----------------------------------------------------------------------------
1547 // name: halfrect_tick()
1548 // desc: ...
1549 //-----------------------------------------------------------------------------
1550 CK_DLL_TICK( halfrect_tick )
1552 *out = in > 0.0f ? in : 0.0f;
1553 return TRUE;
1559 //-----------------------------------------------------------------------------
1560 // name: fullrect_tick()
1561 // desc: ...
1562 //-----------------------------------------------------------------------------
1563 CK_DLL_TICK( fullrect_tick )
1565 *out = in >= 0.0f ? in : -in;
1566 return TRUE;
1572 //-----------------------------------------------------------------------------
1573 // name: zerox_ctor()
1574 // desc: ...
1575 //-----------------------------------------------------------------------------
1576 CK_DLL_CTOR( zerox_ctor )
1578 OBJ_MEMBER_UINT(SELF, zerox_offset_data) = (t_CKUINT)new SAMPLE( 0.0f );
1582 //-----------------------------------------------------------------------------
1583 // name: zerox_dtor()
1584 // desc: ...
1585 //-----------------------------------------------------------------------------
1586 CK_DLL_DTOR( zerox_dtor )
1588 delete (SAMPLE *)OBJ_MEMBER_UINT(SELF, zerox_offset_data);
1589 OBJ_MEMBER_UINT(SELF, zerox_offset_data) = 0;
1593 #define __SGN(x) (x >= 0.0f ? 1.0f : -1.0f )
1594 //-----------------------------------------------------------------------------
1595 // name: zerox_tick()
1596 // desc: ...
1597 //-----------------------------------------------------------------------------
1598 CK_DLL_TICK( zerox_tick )
1600 SAMPLE * d = (SAMPLE *)OBJ_MEMBER_UINT(SELF, zerox_offset_data);
1601 *out = __SGN(in) != __SGN(*d);
1602 *out *= __SGN(in);
1603 *d = in;
1605 return TRUE;
1611 struct delayp_data
1614 SAMPLE * buffer;
1615 t_CKINT bufsize;
1617 t_CKTIME now;
1619 double readpos; //readpos ( moves at constant speed, sample per sample
1620 double writepos; // relative to read position
1622 t_CKTIME offset; // distance between read and write
1624 t_CKDUR offset_start;
1625 t_CKDUR offset_target;
1627 t_CKTIME move_end_time; //target time
1628 t_CKDUR move_duration; //time we started shift
1630 SAMPLE last_sample;
1631 t_CKDUR last_offset;
1633 #ifdef _DEBUG
1634 int lasti;
1635 #endif
1637 double acoeff[2];
1638 double bcoeff[2];
1639 SAMPLE outputs[3];
1640 SAMPLE inputs[3];
1642 delayp_data()
1644 bufsize = 2 * g_srate;
1645 buffer = ( SAMPLE * ) realloc ( NULL, sizeof ( SAMPLE ) * bufsize );
1646 t_CKINT i;
1648 for ( i = 0 ; i < bufsize ; i++ ) buffer[i] = 0;
1649 for ( i = 0 ; i < 3 ; i++ ) { acoeff[i] = 0; bcoeff[i] = 0; }
1651 acoeff[0] = 1.0;
1652 acoeff[1] = -.99;
1653 bcoeff[0] = 1.0;
1654 bcoeff[1] = -1.0;
1656 readpos = 0.0;
1658 now = 0.0;
1660 offset = 0.0;
1661 last_offset = 0.0;
1662 offset_start = 0.0;
1663 offset_target = 0.0;
1665 move_duration = 1.0;
1666 move_end_time = 0.0;
1668 #ifdef _DEBUG
1669 lasti = -1;
1670 #endif
1671 last_sample = 0;
1674 ~delayp_data()
1676 SAFE_DELETE_ARRAY( buffer );
1680 CK_DLL_CTOR( delayp_ctor )
1682 OBJ_MEMBER_UINT(SELF, delayp_offset_data) = (t_CKUINT)new delayp_data;
1685 CK_DLL_DTOR( delayp_dtor )
1687 delayp_data * d = (delayp_data *)OBJ_MEMBER_UINT(SELF, delayp_offset_data);
1688 SAFE_DELETE(d);
1689 OBJ_MEMBER_UINT(SELF, delayp_offset_data) = 0;
1692 CK_DLL_PMSG( delayp_pmsg )
1694 return TRUE;
1697 CK_DLL_TICK( delayp_tick )
1699 delayp_data * d = (delayp_data *)OBJ_MEMBER_UINT(SELF, delayp_offset_data);
1700 if ( !d->buffer ) return FALSE;
1702 // area
1703 d->now = ((Chuck_UGen*)SELF)->shred->vm_ref->shreduler()->now_system;
1705 //calculate new write-offset position ( we interpolate if we've been assigned a new write-offset )
1706 if ( d->now >= d->move_end_time || d->move_duration == 0 ) d->offset = d->offset_target;
1707 else {
1708 double dt = 1.0 + ( d->now - d->move_end_time ) / ( d->move_duration );
1709 d->offset = d->offset_start + dt * ( d->offset_target - d->offset_start );
1710 // fprintf (stderr, "dt %f, off %f , start %f target %f\n", dt, d->writeoff, d->writeoff_start, d->writeoff_target );
1713 //find locations in buffer...
1714 double write = (d->readpos ) + d->offset;
1715 double last_write = (d->readpos - 1.0) + d->last_offset ;
1717 //linear interpolation. will introduce some lowpass/aliasing.
1718 double write_delta = write - last_write;
1719 double sample_delta = in - d->last_sample;
1721 double duck_constant = 0.69;
1724 double gee = fabs(write_delta) - 1.0;
1726 if ( gee < 24.0 ) {
1727 double head_contact = ( gee > 0 ) ? exp ( - duck_constant * gee ) : 1.0;
1728 t_CKINT i, smin, smax, sampi;
1729 SAMPLE sampf = 0;
1730 if ( write_delta >= 0 ) { //forward.
1731 smin = (t_CKINT) floor ( last_write );
1732 smax = (t_CKINT) floor ( write );
1733 for ( i = smin+1 ; i <= smax ; i++ ) {
1734 sampf = d->last_sample + sample_delta * ( double(i) - last_write ) / write_delta;
1735 sampi = ( i + d->bufsize * 2 ) % d->bufsize;
1736 #ifdef _DEBUG
1737 if ( d->lasti == sampi ) {
1738 fprintf( stderr, "[chuck](via Curve): over!\n");
1740 d->lasti = sampi;
1741 #endif
1742 d->buffer[sampi] += sampf * head_contact ;
1745 else { //moving in reverse
1746 smin = (t_CKINT) floor ( write );
1747 smax = (t_CKINT) floor ( last_write );
1748 for ( i = smin+1 ; i <= smax ; i++ ) {
1749 sampf = d->last_sample + sample_delta * ( double(i) - last_write ) / write_delta;
1750 sampi = ( i + d->bufsize * 2 ) % d->bufsize;
1751 #ifdef _DEBUG
1752 if ( d->lasti == sampi ) {
1753 fprintf(stderr, "[chuck](via Curve): over!\n");
1755 d->lasti = sampi;
1756 #endif
1757 d->buffer[sampi] += sampf * head_contact;
1762 d->last_offset = d->offset;
1763 d->last_sample = in;
1766 //output should go through a dc blocking filter, for cases where
1767 //we are zipping around in the buffer leaving a fairly constant
1768 //trail of samples
1770 //output last sample
1772 t_CKINT rpos = (t_CKINT) fmod( d->readpos, d->bufsize ) ;
1774 // *out = d->buffer[rpos];
1777 // did i try to write a dc blocking filter?
1778 d->outputs[0] = 0.0;
1779 d->inputs [0] = d->buffer[rpos];
1781 d->outputs[0] += d->bcoeff[1] * d->inputs[1];
1782 d->inputs [1] = d->inputs[0];
1784 d->outputs[0] += d->bcoeff[0] * d->inputs[0];
1786 d->outputs[0] += -d->acoeff[1] * d->outputs[1];
1787 d->outputs[1] = d->outputs[0];
1789 //clear at readpos ( write doesn't !)
1790 *out = d->outputs[0];
1793 *out = d->buffer[rpos];
1795 d->buffer[rpos] = 0; //clear once it's been read
1796 d->readpos = fmod ( d->readpos + 1.0 , double( d->bufsize ) );
1798 return TRUE;
1802 CK_DLL_CTRL( delayp_ctrl_delay )
1804 delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data);
1805 t_CKDUR target = GET_CK_DUR(ARGS); // rate
1806 // area
1808 if ( target != d->offset_target ) {
1809 if ( target > d->bufsize ) {
1810 fprintf( stderr, "[chuck](via delayp): delay time %f over max! set max first!\n", target);
1811 return;
1813 d->offset_target = target;
1814 d->offset_start = d->last_offset;
1816 t_CKTIME snow = ((Chuck_UGen*)SELF)->shred->now;
1817 d->move_end_time = snow + d->move_duration;
1819 RETURN->v_dur = d->last_offset; // TODO:
1822 CK_DLL_CGET( delayp_cget_delay )
1824 delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data);
1825 //SET_NEXT_DUR( out, d->writeoff_last );
1826 RETURN->v_dur = d->last_offset; // TODO:
1829 CK_DLL_CTRL( delayp_ctrl_window )
1831 delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data);
1832 t_CKDUR window = GET_CK_DUR(ARGS); // rate
1833 if ( window >= 0 ) {
1834 d->move_duration = window;
1835 //fprintf ( stderr, "set window time %f , %f , %d \n", d->writeoff_window_time, d->writeoff, d->bufsize );
1837 RETURN->v_dur = d->move_duration; // TODO:
1840 CK_DLL_CGET( delayp_cget_window )
1842 delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data);
1843 RETURN->v_dur = d->move_duration; // TODO:
1847 CK_DLL_CTRL( delayp_ctrl_max )
1849 delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data);
1850 t_CKDUR nmax = GET_CK_DUR(ARGS); // rate
1851 if ( d->bufsize != (t_CKINT)nmax && nmax > 1.0 ) {
1852 d->bufsize = (t_CKINT)(nmax+.5);
1853 d->buffer = ( SAMPLE * ) realloc ( d->buffer, sizeof ( SAMPLE ) * d->bufsize );
1854 for ( t_CKINT i = 0; i < d->bufsize; i++ ) d->buffer[i] = 0;
1856 RETURN->v_dur = d->bufsize; // TODO??
1859 CK_DLL_CGET( delayp_cget_max )
1861 delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data);
1862 //SET_NEXT_DUR( out, (t_CKDUR) d->bufsize );
1863 RETURN->v_dur = d->bufsize;
1866 //-----------------------------------------------------------------------------
1867 // name: sndbuf
1868 // desc: ...
1869 //-----------------------------------------------------------------------------
1870 enum { SNDBUF_DROP = 0, SNDBUF_INTERP, SNDBUF_SINC};
1873 #define WIDTH 16 /* this controls the number of neighboring samples
1874 which are used to interpolate the new samples. The
1875 processing time is linearly related to this width */
1876 #define DELAY_SIZE 140
1878 #define USE_TABLE TRUE /* this controls whether a linearly interpolated lookup
1879 table is used for sinc function calculation, or the
1880 sinc is calculated by floating point trig function calls. */
1882 #define USE_INTERP TRUE /* this controls whether the table is linear
1883 interpolated or not. If you re not using the
1884 table, this has no effect */
1886 #define SAMPLES_PER_ZERO_CROSSING 32 /* this defines how finely the sinc function
1887 is sampled for storage in the table */
1889 #ifdef CK_SNDBUF_MEMORY_BUFFER
1890 //------------------------------------------------------------------------------
1891 // name: MultiBuffer
1892 // desc: presents multiple buffers in memory as a single sequential logical
1893 // buffer, for constant time reallocing. tries to be as discreet as possible,
1894 // so you can basically use it like a pointer. optimized for iterative access,
1895 // as random access has T = O(bufsize)
1896 //------------------------------------------------------------------------------
1897 template< class _type >
1898 class MultiBuffer
1901 public:
1902 MultiBuffer()
1904 m_size = 0;
1907 ~MultiBuffer()
1909 deallocate();
1912 size_t size()
1914 return m_size;
1917 void resize( size_t size )
1919 assert( size > m_size ); // for now
1920 size_t new_buffer_size = size - m_size;
1922 extent new_extent;
1923 new_extent.position = new _type[new_buffer_size];
1924 new_extent.length = new_buffer_size;
1925 m_bufs.push_back( new_extent );
1926 m_size = size;
1929 void deallocate()
1931 // delete everything
1932 size_t i, len = m_bufs.size();
1933 for( i = 0; i < len; i++ )
1934 delete[] m_bufs[i].position;
1935 m_size = 0;
1938 class Pointer
1940 public:
1941 Pointer()
1943 m_mb = NULL;
1944 m_lpos = 0;
1945 m_extent = 0;
1946 m_extpos = 0;
1949 Pointer( MultiBuffer * mb )
1951 m_mb = mb;
1952 m_lpos = 0;
1953 m_extent = 0;
1954 m_extpos = 0;
1957 Pointer( const Pointer & mbp )\v
1959 m_mb = mbp.m_mb;
1960 m_lpos = mbp.m_lpos;
1961 m_extent = mbp.m_extent;
1962 m_extpos = mbp.m_extpos;
1965 Pointer & operator=( MultiBuffer & mb )
1967 m_mb = &mb;
1968 m_lpos = 0;
1969 m_extent = 0;
1970 m_extpos = 0;
1972 return *this;
1975 Pointer & operator=( const Pointer & mbp )
1977 m_mb = mbp.m_mb;
1978 m_lpos = mbp.m_lpos;
1979 m_extent = mbp.m_extent;
1980 m_extpos = mbp.m_extpos;
1982 return *this;
1985 Pointer & operator=( size_t i )
1987 reset();
1988 increment( i );
1989 return *this;
1992 _type & operator*()
1994 return m_mb->m_bufs[m_extent].position[m_extpos];
1997 Pointer operator+( size_t i ) const
1999 Pointer mbp( *this );
2000 mbp.increment( i );
2001 return mbp;
2004 Pointer operator++( int )
2006 Pointer mbp = *this;
2007 this->increment( 1 );
2008 return mbp;
2011 bool operator>=( const Pointer & mbp ) const
2013 return ( m_lpos >= mbp.m_lpos );
2016 bool operator>=( const size_t i ) const
2018 return ( m_lpos >= i );
2021 void increment( size_t i )
2023 m_lpos += i;
2024 if( m_lpos >= (m_mb->m_size) )
2026 m_extent = m_mb->m_bufs.size();
2027 m_extpos = m_lpos - m_mb->m_size;
2028 return;
2031 extent ext_current = m_mb->m_bufs[m_extent];
2032 i += m_extpos;
2033 while( i >= ext_current.length )
2035 i -= ext_current.length;
2036 m_extent++;
2037 ext_current = m_mb->m_bufs[m_extent];
2040 m_extpos = i;
2043 void reset()
2045 m_lpos = 0;
2046 m_extent = 0;
2047 m_extpos = 0;
2050 protected:
2051 MultiBuffer * m_mb;
2053 size_t m_lpos; // position in logical buffer
2054 size_t m_extent; // current extent
2055 size_t m_extpos; // position within the extent
2058 protected:
2060 struct extent
2062 _type * position;
2063 size_t length;
2066 /* data shared by a set of MultiBuffers */
2067 vector< extent > m_bufs; // array of sequentially allocated buffers
2068 size_t m_size; // overall size of total memory represented
2070 #endif /* CK_SNDBUF_MEMORY_BUFFER */
2072 // data for each sndbuf
2073 struct sndbuf_data
2075 SAMPLE * buffer;
2076 t_CKUINT num_samples;
2077 t_CKUINT num_channels;
2078 t_CKUINT num_frames;
2079 t_CKUINT samplerate;
2080 t_CKUINT chan;
2081 t_CKUINT chunks;
2082 t_CKUINT chunks_read;
2083 t_CKUINT chunks_total;
2084 t_CKUINT chunks_size;
2085 bool * chunk_table;
2087 SAMPLE * eob;
2088 SAMPLE * curr;
2089 t_CKFLOAT sampleratio;
2090 t_CKFLOAT curf;
2091 t_CKFLOAT rate_factor;
2092 t_CKFLOAT rate;
2093 t_CKINT interp;
2094 t_CKBOOL loop;
2096 bool sinc_table_built;
2097 bool sinc_use_table;
2098 bool sinc_use_interp;
2099 t_CKINT sinc_samples_per_zero_crossing;
2100 t_CKINT sinc_width;
2101 double * sinc_table;
2103 #ifdef CK_SNDBUF_MEMORY_BUFFER
2104 MultiBuffer< SAMPLE > mb_buffer;
2105 t_CKUINT mb_max_samples;
2106 MultiBuffer< SAMPLE >::Pointer mb_record_position;
2107 MultiBuffer< SAMPLE >::Pointer mb_playback_position;
2108 #endif /* CK_SNDBUF_MEMORY_BUFFER */
2110 SNDFILE * fd;
2112 // constructor
2113 sndbuf_data()
2115 buffer = NULL;
2116 interp = SNDBUF_INTERP;
2117 num_channels = 0;
2118 num_frames = 0;
2119 num_samples = 0;
2120 chunks = 0;
2121 chunks_read = 0;
2122 chunks_total = 0;
2123 chunks_size = 0;
2124 chunk_table = NULL;
2125 samplerate = 0;
2126 sampleratio = 1.0;
2127 chan = 0;
2128 curf = 0.0;
2129 rate_factor = 1.0;
2130 rate = 1.0;
2131 eob = NULL;
2132 curr = NULL;
2134 sinc_table_built = false;
2135 sinc_use_table = USE_TABLE;
2136 sinc_use_interp = USE_INTERP;
2137 sinc_width = WIDTH;
2138 sinc_samples_per_zero_crossing = SAMPLES_PER_ZERO_CROSSING;
2139 sinc_table = NULL;
2141 #ifdef CK_SNDBUF_MEMORY_BUFFER
2142 mb_buffer = MultiBuffer< SAMPLE >();
2143 #endif /* CK_SNDBUF_MEMORY_BUFFER */
2145 loop = FALSE;
2146 fd = NULL;
2149 ~sndbuf_data()
2151 SAFE_DELETE_ARRAY( buffer );
2152 SAFE_DELETE_ARRAY( chunk_table );
2157 double sndbuf_sinc( sndbuf_data * d, double x );
2158 double sndbuf_t_sinc( sndbuf_data * d, double x );
2159 void sndbuf_make_sinc( sndbuf_data * d );
2160 void sndbuf_sinc_interpolate( sndbuf_data * d, SAMPLE * out );
2162 CK_DLL_CTOR( sndbuf_ctor )
2164 OBJ_MEMBER_UINT(SELF, sndbuf_offset_data) = (t_CKUINT)new sndbuf_data;
2167 CK_DLL_DTOR( sndbuf_dtor )
2169 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2170 SAFE_DELETE(d);
2171 OBJ_MEMBER_UINT(SELF, sndbuf_offset_data) = 0;
2174 inline t_CKUINT sndbuf_read( sndbuf_data * d, t_CKUINT offset, t_CKUINT howmuch )
2176 // check
2177 if( d->fd == NULL ) return 0;
2178 if( offset >= d->num_frames ) return 0;
2180 // log
2181 // EM_log( CK_LOG_FINE, "(sndbuf): reading %d:%d frames...", offset, howmuch );
2183 // prevent overflow
2184 if( howmuch > d->num_frames - offset )
2185 howmuch = d->num_frames - offset;
2187 t_CKUINT n;
2188 // seek
2189 sf_seek( d->fd, offset, SEEK_SET );
2190 #if defined(CK_S_DOUBLE)
2191 n = sf_readf_double( d->fd, d->buffer+offset*d->num_channels, howmuch );
2192 #else
2193 n = sf_readf_float( d->fd, d->buffer+offset*d->num_channels, howmuch );
2194 #endif
2196 d->chunks_read += n;
2198 // close
2199 if( d->chunks_read >= d->num_frames )
2201 // log
2202 EM_log( CK_LOG_INFO, "(sndbuf): all frames read, closing file..." );
2203 sf_close( d->fd );
2204 d->fd = NULL;
2207 return n;
2210 inline t_CKINT sndbuf_load( sndbuf_data * d, t_CKUINT where )
2212 // map to bin
2213 t_CKUINT bin = (t_CKUINT)(where / (t_CKFLOAT)d->chunks_size);
2214 if( bin >= d->chunks_total ) return 0;
2216 // already loaded
2217 if( d->chunk_table[bin] ) return 0;
2219 // read it
2220 t_CKINT ret = sndbuf_read( d, bin*d->chunks_size, d->chunks_size );
2222 // flag it
2223 d->chunk_table[bin] = true;
2225 // log
2226 // EM_log( CK_LOG_FINER, "chunk test: pos: %d bin: %d read:%d/%d", where, bin, d->chunks_read, d->num_frames );
2228 return ret;
2231 inline void sndbuf_setpos( sndbuf_data *d, double pos )
2233 if( !d->buffer ) return;
2235 d->curf = pos;
2237 // set curf within bounds
2238 if( d->loop )
2240 while( d->curf >= d->num_frames ) d->curf -= d->num_frames;
2241 while( d->curf < 0 ) d->curf += d->num_frames;
2243 else
2245 if( d->curf < 0 ) d->curf = 0;
2246 else if( d->curf >= d->num_frames ) d->curf = d->num_frames;
2249 t_CKINT i = (t_CKINT)d->curf;
2250 // ensure load
2251 if( d->fd != NULL ) sndbuf_load( d, i );
2252 // sets curr to correct position ( account for channels )
2253 d->curr = d->buffer + d->chan + i * d->num_channels;
2256 inline SAMPLE sndbuf_sampleAt( sndbuf_data * d, t_CKINT pos )
2258 // boundary cases
2259 t_CKINT nf = d->num_frames;
2260 if( d->loop ) {
2261 while( pos > nf ) pos -= nf;
2262 while( pos < 0 ) pos += nf;
2264 else {
2265 if( pos > nf ) pos = nf;
2266 if( pos < 0 ) pos = 0;
2269 t_CKUINT index = d->chan + pos * d->num_channels;
2270 // ensure load
2271 if( d->fd != NULL ) sndbuf_load( d, pos );
2272 // return sample
2273 return d->buffer[index];
2276 inline double sndbuf_getpos( sndbuf_data * d )
2278 if( !d->buffer ) return 0;
2279 return floor(d->curf);
2282 CK_DLL_CTRL( sndbuf_ctrl_loop )
2284 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2285 d->loop = GET_CK_INT(ARGS);
2286 RETURN->v_int = d->loop; // TODO: Check (everything)
2289 CK_DLL_CGET( sndbuf_cget_loop )
2291 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2292 RETURN->v_int = d->loop;
2295 // PRC's sinc interpolation function.. as found
2296 // http://www.cs.princeton.edu/courses/archive/spring03/cs325/src/TimeStuf/srconvrt.c
2298 // there's probably a lot in there that could be optimized, if we care to..
2300 // #define PI 3.14159265358979323846
2301 // wow... we are sensitive..
2303 inline double sndbuf_linear_interp( double * first, double * second, double * frac );
2304 bool sinc_table_built = false;
2306 void sndbuf_sinc_interpolate( sndbuf_data *d, SAMPLE * out )
2308 signed long j;
2309 double factor = d->rate;
2310 double time_now = d->curf;
2311 double one_over_factor;
2312 // UNUSED: double int_time = 0;
2313 // UNUSED: double last_time = 0;
2314 double temp1 = 0.0;
2316 long time_i = (long)time_now;
2318 // bounds checking now in sampleAt function...
2319 if( factor < 1.0 ) {
2320 for( j = -d->sinc_width + 1; j < d->sinc_width; j++ )
2322 temp1 += sndbuf_sampleAt(d,time_i+j) * sndbuf_sinc( d, (double)j );
2324 *out = (SAMPLE)temp1;
2326 else {
2327 one_over_factor = 1.0 / factor;
2328 for( j = -d->sinc_width + 1; j < d->sinc_width; j++ ) {
2329 temp1 += sndbuf_sampleAt(d,time_i+j) * one_over_factor * sndbuf_sinc( d, one_over_factor * (double)j );
2331 *out = (SAMPLE)temp1;
2335 void sndbuf_make_sinc( sndbuf_data * d )
2337 t_CKINT i;
2338 // fprintf(stderr, "building sinc table\n" );
2339 double temp, win_freq, win;
2340 win_freq = ONE_PI / d->sinc_width / d->sinc_samples_per_zero_crossing;
2341 t_CKINT tabsize = d->sinc_width * d->sinc_samples_per_zero_crossing;
2343 d->sinc_table = (double *) realloc( d->sinc_table, tabsize * sizeof(double) );
2344 d->sinc_table[0] = 1.0;
2345 for( i = 1; i < tabsize; i++ ) {
2346 temp = (double) i * ONE_PI / d->sinc_samples_per_zero_crossing;
2347 d->sinc_table[i] = (float)(sin(temp) / temp);
2348 win = 0.5 + 0.5 * cos(win_freq * i);
2349 d->sinc_table[i] *= (float)win;
2351 d->sinc_table_built = true;
2354 inline double sndbuf_linear_interp( double first_number, double second_number, double fraction )
2356 return (first_number + ((second_number - first_number) * fraction));
2359 double sndbuf_t_sinc( sndbuf_data * d, double x )
2361 t_CKINT low;
2362 double temp,delta;
2363 if( !d->sinc_table_built ) sndbuf_make_sinc(d);
2364 if( fabs(x) >= d->sinc_width-1 )
2365 return 0.0;
2366 else {
2367 temp = fabs(x) * (double) d->sinc_samples_per_zero_crossing;
2368 low = (t_CKINT)temp; /* these are interpolation steps */
2369 if( d->sinc_use_interp ) {
2370 delta = temp - low; /* and can be ommited if desired */
2371 return sndbuf_linear_interp( d->sinc_table[low], d->sinc_table[low + 1], delta );
2373 else return d->sinc_table[low];
2377 double sndbuf_sinc( sndbuf_data * d, double x )
2379 double temp;
2381 if( d->sinc_use_table ) return sndbuf_t_sinc(d,x);
2382 else {
2383 if( x == 0.0 ) return 1.0;
2384 else {
2385 temp = ONE_PI * x;
2386 return sin(temp) / (temp);
2391 CK_DLL_TICK( sndbuf_tick )
2393 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2395 #ifdef CK_SNDBUF_MEMORY_BUFFER
2396 // spencer's memory buffer stuff
2397 if( d->fd == 0 )
2398 // no file open - memory buffer mode
2400 Chuck_UGen * ugen = (Chuck_UGen *)SELF;
2401 if( ugen->m_num_src )
2402 // recording mode
2404 if( d->mb_buffer.size() == 0 )
2406 d->mb_buffer.resize( 44100 * 4 ); // default size: 4 seconds
2407 d->mb_record_position = d->mb_buffer;
2408 d->mb_playback_position = d->mb_buffer;
2411 if( d->mb_record_position >= d->mb_buffer.size() )
2412 d->mb_buffer.resize( d->mb_buffer.size() * 2 );
2414 *(d->mb_record_position++) = in;
2417 if( d->mb_buffer.size() )
2419 if( d->mb_playback_position >= d->mb_record_position )
2421 if( d->loop )
2422 d->mb_playback_position = 0;
2424 else if( ugen->m_num_src )
2426 *out = 0;
2427 return TRUE;
2430 else
2431 return FALSE;
2434 *out = *(d->mb_playback_position++);
2437 return TRUE;
2439 #endif /* CK_SNDBUF_MEMORY_BUFFER */
2440 if( !d->buffer ) return FALSE;
2442 // we're ticking once per sample ( system )
2443 // curf in samples;
2445 if( !d->loop && d->curr >= d->eob + d->num_channels ) return FALSE;
2447 // calculate frame
2448 if( d->interp == SNDBUF_DROP )
2450 *out = (SAMPLE)( (*(d->curr)) ) ;
2452 else if( d->interp == SNDBUF_INTERP )
2454 // samplewise linear interp
2455 double alpha = d->curf - floor(d->curf);
2456 *out = (SAMPLE)( (*(d->curr)) ) ;
2457 *out += (float)alpha * ( sndbuf_sampleAt(d, (long)d->curf+1 ) - *out );
2459 else if( d->interp == SNDBUF_SINC ) {
2460 // do that fancy sinc function!
2461 sndbuf_sinc_interpolate(d, out);
2464 // advance
2465 d->curf += d->rate;
2466 sndbuf_setpos(d, d->curf);
2468 return TRUE;
2472 #include "util_raw.h"
2475 CK_DLL_CTRL( sndbuf_ctrl_read )
2477 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2478 const char * filename = GET_CK_STRING(ARGS)->str.c_str();
2480 if( d->buffer )
2482 delete [] d->buffer;
2483 d->buffer = NULL;
2486 if( d->chunk_table )
2488 delete [] d->chunk_table;
2489 d->chunk_table = NULL;
2492 if( d->fd )
2494 sf_close( d->fd );
2495 d->fd = NULL;
2498 // log
2499 EM_log( CK_LOG_INFO, "(sndbuf): reading '%s'...", filename );
2501 // built in
2502 if( strstr(filename, "special:") )
2504 SAMPLE * rawdata = NULL;
2505 t_CKUINT rawsize = 0;
2506 t_CKUINT srate = 22050;
2508 // which
2509 if( strstr(filename, "special:sinewave") ) {
2510 rawsize = 1024; rawdata = NULL;
2512 else if( strstr(filename, "special:ahh") ) {
2513 rawsize = ahh_size; rawdata = ahh_data;
2515 else if( strstr(filename, "special:britestk") ) {
2516 rawsize = britestk_size; rawdata = britestk_data;
2518 else if( strstr(filename, "special:dope") ) {
2519 rawsize = dope_size; rawdata = dope_data;
2521 else if( strstr(filename, "special:eee") ) {
2522 rawsize = eee_size; rawdata = eee_data;
2524 else if( strstr(filename, "special:fwavblnk") ) {
2525 rawsize = fwavblnk_size; rawdata = fwavblnk_data;
2527 else if( strstr(filename, "special:halfwave") ) {
2528 rawsize = halfwave_size; rawdata = halfwave_data;
2530 else if( strstr(filename, "special:impuls10") ) {
2531 rawsize = impuls10_size; rawdata = impuls10_data;
2533 else if( strstr(filename, "special:impuls20") ) {
2534 rawsize = impuls20_size; rawdata = impuls20_data;
2536 else if( strstr(filename, "special:impuls40") ) {
2537 rawsize = impuls40_size; rawdata = impuls40_data;
2539 else if( strstr(filename, "special:mand1") ) {
2540 rawsize = mand1_size; rawdata = mand1_data;
2542 else if( strstr(filename, "special:mandpluk") ) {
2543 rawsize = mandpluk_size; rawdata = mandpluk_data;
2545 else if( strstr(filename, "special:marmstk1") ) {
2546 rawsize = marmstk1_size; rawdata = marmstk1_data;
2548 else if( strstr(filename, "special:ooo") ) {
2549 rawsize = ooo_size; rawdata = ooo_data;
2551 else if( strstr(filename, "special:peksblnk") ) {
2552 rawsize = peksblnk_size; rawdata = peksblnk_data;
2554 else if( strstr(filename, "special:ppksblnk") ) {
2555 rawsize = ppksblnk_size; rawdata = ppksblnk_data;
2557 else if( strstr(filename, "special:silence") ) {
2558 rawsize = silence_size; rawdata = silence_data;
2560 else if( strstr(filename, "special:sineblnk") ) {
2561 rawsize = sineblnk_size; rawdata = sineblnk_data;
2563 else if( strstr(filename, "special:sinewave") ) {
2564 rawsize = sinewave_size; rawdata = sinewave_data;
2566 else if( strstr(filename, "special:snglpeak") ) {
2567 rawsize = snglpeak_size; rawdata = snglpeak_data;
2569 else if( strstr(filename, "special:twopeaks") ) {
2570 rawsize = twopeaks_size; rawdata = twopeaks_data;
2572 else if( strstr(filename, "special:glot_ahh") ) {
2573 rawsize = glot_ahh_size; rawdata = glot_ahh_data; srate = 44100;
2575 else if( strstr(filename, "special:glot_eee") ) {
2576 rawsize = glot_eee_size; rawdata = glot_eee_data; srate = 44100;
2578 else if( strstr(filename, "special:glot_ooo") ) {
2579 rawsize = glot_ooo_size; rawdata = glot_ooo_data; srate = 44100;
2581 else if( strstr(filename, "special:glot_pop") ) {
2582 rawsize = glot_pop_size; rawdata = glot_pop_data; srate = 44100;
2585 d->num_frames = rawsize;
2586 d->num_channels = 1;
2587 d->chan = 0;
2588 d->samplerate = srate;
2589 d->num_samples = rawsize;
2591 // no chunking
2592 d->chunks_read = d->num_frames;
2594 if( rawdata ) {
2595 d->buffer = new SAMPLE[rawsize+1];
2596 for( t_CKUINT j = 0; j < rawsize; j++ ) {
2597 d->buffer[j] = (SAMPLE)rawdata[j]/(SAMPLE)SHRT_MAX;
2600 else if( strstr(filename, "special:sinewave") ) {
2601 d->buffer = new SAMPLE[rawsize+1];
2602 for( t_CKUINT j = 0; j < rawsize; j++ )
2603 d->buffer[j] = sin(2*ONE_PI*j/rawsize);
2605 else {
2606 fprintf( stderr, "[chuck](via SndBuf): cannot load '%s'\n", filename );
2607 return;
2610 d->buffer[rawsize] = d->buffer[0];
2612 else // read file
2614 // stat the file first
2615 struct stat s;
2616 if( stat( filename, &s ) )
2618 fprintf( stderr, "[chuck](via SndBuf): cannot stat file '%s'...\n", filename );
2619 return;
2622 // open it
2623 SF_INFO info;
2624 info.format = 0;
2625 const char * format = (const char *)strrchr( filename, '.');
2626 if( format && strcmp( format, ".raw" ) == 0 )
2628 fprintf( stderr, "[chuck](via SndBuf) %s :: type is '.raw'...\n assuming 16 bit signed mono (PCM)\n", filename );
2629 info.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16 | SF_ENDIAN_CPU ;
2630 info.channels = 1;
2631 info.samplerate = 44100;
2634 // open the handle
2635 d->fd = sf_open( filename, SFM_READ, &info );
2636 t_CKINT er = sf_error( d->fd );
2637 if( er )
2639 fprintf( stderr, "[chuck](via SndBuf): sndfile error '%i' opening '%s'...\n", er, filename );
2640 fprintf( stderr, "[chuck](via SndBuf): (reason: %s)\n", sf_strerror( d->fd ) );
2641 if( d->fd ) sf_close( d->fd );
2642 // escape
2643 return;
2646 // allocate
2647 t_CKINT size = info.channels * info.frames;
2648 d->buffer = new SAMPLE[size+info.channels];
2649 memset( d->buffer, 0, (size+info.channels)*sizeof(SAMPLE) );
2650 d->chan = 0;
2651 d->num_frames = info.frames;
2652 d->num_channels = info.channels;
2653 d->samplerate = info.samplerate;
2654 d->num_samples = size;
2656 // log
2657 EM_pushlog();
2658 EM_log( CK_LOG_INFO, "channels: %d", d->num_channels );
2659 EM_log( CK_LOG_INFO, "frames: %d", d->num_frames );
2660 EM_log( CK_LOG_INFO, "srate: %d", d->samplerate );
2661 EM_log( CK_LOG_INFO, "chunks: %d", d->chunks );
2662 EM_poplog();
2664 // read
2665 sf_seek( d->fd, 0, SEEK_SET );
2666 d->chunks_read = 0;
2668 // no chunk
2669 if( !d->chunks )
2671 // read all
2672 t_CKUINT f = sndbuf_read( d, 0, d->num_frames );
2673 // check
2674 if( f != (t_CKUINT)d->num_frames )
2676 fprintf( stderr, "[chuck](via SndBuf): read %d rather than %d frames from %s\n",
2677 f, size, filename );
2678 sf_close( d->fd ); d->fd = NULL;
2679 return;
2682 assert( d->fd == NULL );
2684 else
2686 // reset
2687 d->chunks_size = d->chunks;
2688 d->chunks_total = d->num_frames / d->chunks;
2689 d->chunks_total += d->num_frames % d->chunks ? 1 : 0;
2690 d->chunks_read = 0;
2691 d->chunk_table = new bool[d->chunks_total];
2692 memset( d->chunk_table, 0, d->chunks_total * sizeof(bool) );
2694 // read chunk
2695 // sndbuf_load( d, 0 );
2699 // d->interp = SNDBUF_INTERP;
2700 d->sampleratio = (double)d->samplerate / (double)g_srate;
2701 // set the rate
2702 d->rate = d->sampleratio * d->rate_factor;
2703 d->curr = d->buffer;
2704 d->curf = 0;
2705 d->eob = d->buffer + d->num_samples;
2708 CK_DLL_CTRL( sndbuf_ctrl_write )
2710 #ifdef SPENCER_SNDBUF_WRITE
2711 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2712 const char * filename = GET_CK_STRING(ARGS)->str.c_str();
2714 if( d->buffer )
2716 delete [] d->buffer;
2717 d->buffer = NULL;
2720 struct stat s;
2721 if( stat( filename, &s ) )
2723 fprintf( stderr, "[chuck](via SndBuf): cannot stat file '%s'...\n", filename );
2724 return;
2727 d->curr = d->buffer;
2728 d->eob = d->buffer + d->num_samples;
2729 #endif
2733 CK_DLL_CTRL( sndbuf_ctrl_rate )
2735 sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2736 t_CKFLOAT rate = GET_CK_FLOAT(ARGS); // rate
2737 d->rate = rate * d->sampleratio;
2738 d->rate_factor = rate;
2739 RETURN->v_float = d->rate_factor; // TODO: (or not TODO:)
2742 CK_DLL_CGET( sndbuf_cget_rate )
2744 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2745 RETURN->v_float = d->rate_factor;
2749 CK_DLL_CTRL( sndbuf_ctrl_freq )
2751 sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2752 t_CKFLOAT freq = GET_CK_FLOAT(ARGS); //hz
2754 d->rate = ( freq * (double) d->num_frames / (double) g_srate );
2755 d->rate_factor = d->rate / d->sampleratio;
2756 RETURN->v_float = d->rate * (t_CKFLOAT) g_srate / ( (t_CKFLOAT) d->num_frames ); // TODO: really?
2759 CK_DLL_CGET( sndbuf_cget_freq )
2761 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2762 RETURN->v_float = d->rate * (t_CKFLOAT) g_srate / ( (t_CKFLOAT) d->num_frames );
2765 CK_DLL_CTRL( sndbuf_ctrl_phase )
2767 sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2768 t_CKFLOAT phase = GET_CK_FLOAT(ARGS);
2769 sndbuf_setpos(d, phase * (double)d->num_frames);
2770 RETURN->v_float = (t_CKFLOAT) d->curf / (t_CKFLOAT)d->num_frames; // TODO:
2773 CK_DLL_CGET( sndbuf_cget_phase )
2775 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2776 //SET_NEXT_FLOAT( out, (t_CKFLOAT) d->curf / (t_CKFLOAT)d->num_frames );
2777 RETURN->v_float = (t_CKFLOAT) d->curf / (t_CKFLOAT)d->num_frames;
2780 CK_DLL_CTRL( sndbuf_ctrl_channel )
2782 sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2783 unsigned long chan = (unsigned long)GET_CK_INT(ARGS);
2784 if ( chan >= 0 && chan < d->num_channels ) {
2785 d->chan = chan;
2787 RETURN->v_int = (t_CKINT)d->chan;
2790 CK_DLL_CGET( sndbuf_cget_channel )
2792 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2793 //SET_NEXT_INT( out, d->chan );
2794 RETURN->v_int = (t_CKINT)d->chan;
2797 CK_DLL_CTRL( sndbuf_ctrl_pos )
2799 sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2800 t_CKINT pos = GET_CK_INT(ARGS);
2801 #ifdef CK_SNDBUF_MEMORY_BUFFER
2802 if( pos >= 0 && pos < d->mb_max_samples )
2803 d->mb_playback_position = pos;
2804 #endif /* CK_SNDBUF_MEMORY_BUFFER */
2805 sndbuf_setpos(d, pos);
2806 RETURN->v_int = (t_CKINT)sndbuf_getpos(d); // TODO TODO TODOOO
2809 CK_DLL_CGET( sndbuf_cget_pos )
2811 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2812 RETURN->v_int = (t_CKINT)sndbuf_getpos(d);
2815 CK_DLL_CTRL( sndbuf_ctrl_interp )
2817 sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2818 t_CKINT interp = GET_CK_INT(ARGS);
2819 d->interp = interp;
2820 RETURN->v_int = d->interp;
2823 CK_DLL_CGET( sndbuf_cget_interp )
2825 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2826 RETURN->v_int = d->interp;
2829 CK_DLL_CTRL( sndbuf_ctrl_chunks )
2831 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2832 t_CKINT frames = GET_NEXT_INT(ARGS);
2833 d->chunks = frames >= 0 ? frames : 0;
2834 RETURN->v_int = d->chunks;
2837 CK_DLL_CGET( sndbuf_cget_chunks )
2839 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2840 RETURN->v_int = d->chunks;
2843 CK_DLL_CTRL( sndbuf_ctrl_phase_offset )
2845 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2846 t_CKFLOAT phase_offset = GET_CK_FLOAT(ARGS);
2847 sndbuf_setpos(d, d->curf + phase_offset * (t_CKFLOAT)d->num_frames );
2850 CK_DLL_CGET( sndbuf_cget_samples )
2852 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2853 //SET_NEXT_INT( out, d->num_frames );
2854 RETURN->v_int = d->num_frames;
2857 CK_DLL_CGET( sndbuf_cget_length )
2859 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2860 //SET_NEXT_DUR( out, (t_CKDUR)d->num_frames );
2861 RETURN->v_dur = (t_CKDUR)d->num_frames / d->sampleratio;
2864 CK_DLL_CGET( sndbuf_cget_channels )
2866 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2867 //SET_NEXT_INT( out, d->num_channels );
2868 RETURN->v_int = d->num_channels;
2871 CK_DLL_CGET( sndbuf_cget_valueAt )
2873 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2874 t_CKINT i = GET_CK_INT(ARGS);
2875 if( d->fd ) sndbuf_load( d, i );
2876 RETURN->v_float = ( i > d->num_frames || i < 0 ) ? 0 : d->buffer[i];
2880 class Dyno_Data
2882 private:
2883 const static t_CKDUR ms;
2885 public:
2886 t_CKFLOAT slopeAbove;
2887 t_CKFLOAT slopeBelow;
2888 t_CKFLOAT thresh;
2889 t_CKFLOAT rt;
2890 t_CKFLOAT at;
2891 t_CKFLOAT xd; //sidechain
2892 int externalSideInput; // use input signal or a ctrl signal for env
2893 t_CKFLOAT sideInput; // the ctrl signal for the envelope
2895 int count; //diagnostic
2897 Dyno_Data() {
2898 xd = 0.0;
2899 count = 0;
2900 sideInput = 0;
2901 limit();
2903 ~Dyno_Data() {}
2905 void limit();
2906 void compress();
2907 void gate();
2908 void expand();
2909 void duck();
2911 //set the time constants for rt, at, and tav
2912 static t_CKFLOAT computeTimeConst(t_CKDUR t) {
2913 //AT = 1 - e ^ (-2.2T/t<AT)
2914 //as per chuck_type.cpp, T(sampling period) = 1.0
2915 return 1.0 - exp( -2.2 / t );
2918 static t_CKDUR timeConstToDur(t_CKFLOAT x) {
2919 return -2.2 / log(1.0 - x);
2922 //setters for timing constants
2923 void setAttackTime(t_CKDUR t);
2924 void setReleaseTime(t_CKDUR t);
2926 //other setters
2927 void setRatio(t_CKFLOAT newRatio);
2928 t_CKFLOAT getRatio();
2931 const t_CKDUR Dyno_Data::ms = g_vm->srate() * 1.0 / 1000.0;
2933 //setters for the timing constants
2934 void Dyno_Data::setAttackTime(t_CKDUR t) {
2935 at = computeTimeConst(t);
2938 void Dyno_Data::setReleaseTime(t_CKDUR t) {
2939 rt = computeTimeConst(t);
2942 void Dyno_Data::setRatio(t_CKFLOAT newRatio) {
2943 this->slopeAbove = 1.0 / newRatio;
2944 this->slopeBelow = 1.0;
2947 t_CKFLOAT Dyno_Data::getRatio()
2949 return this->slopeBelow / this->slopeAbove;
2952 //TODO: come up with better/good presets?
2954 //presets for the dynomics processor
2955 void Dyno_Data::limit() {
2956 slopeAbove = 0.1; // 10:1 compression above thresh
2957 slopeBelow = 1.0; // no compression below
2958 thresh = 0.5;
2959 at = computeTimeConst( 5.0 * ms );
2960 rt = computeTimeConst( 300.0 * ms );
2961 externalSideInput = 0;
2964 void Dyno_Data::compress() {
2965 slopeAbove = 0.5; // 2:1 compression
2966 slopeBelow = 1.0;
2967 thresh = 0.5;
2968 at = computeTimeConst( 5.0 * ms );
2969 rt = computeTimeConst( 500.0 * ms );
2970 externalSideInput = 0;
2973 void Dyno_Data::gate() {
2974 slopeAbove = 1.0;
2975 slopeBelow = 100000000; // infinity (more or less)
2976 thresh = 0.1;
2977 at = computeTimeConst( 11.0 * ms );
2978 rt = computeTimeConst( 100.0 * ms );
2979 externalSideInput = 0;
2982 void Dyno_Data::expand() {
2983 slopeAbove = 2.0; // 1:2 expansion
2984 slopeBelow = 1.0;
2985 thresh = 0.5;
2986 at = computeTimeConst( 20.0 * ms );
2987 rt = computeTimeConst( 400.0 * ms );
2988 externalSideInput = 0;
2991 void Dyno_Data::duck() {
2992 slopeAbove = 0.5; // when sideInput rises above thresh, gain starts going
2993 slopeBelow = 1.0; // down. it'll drop more as sideInput gets louder.
2994 thresh = 0.1;
2995 at = computeTimeConst( 10.0 * ms );
2996 rt = computeTimeConst( 1000.0 * ms );
2997 externalSideInput = 1;
3001 //controls for the preset modes
3002 CK_DLL_CTRL( dyno_ctrl_limit ) {
3003 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3004 d->limit();
3007 CK_DLL_CTRL( dyno_ctrl_compress ) {
3008 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3009 d->compress();
3012 CK_DLL_CTRL( dyno_ctrl_gate ) {
3013 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3014 d->gate();
3017 CK_DLL_CTRL( dyno_ctrl_expand ) {
3018 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3019 d->expand();
3022 CK_DLL_CTRL( dyno_ctrl_duck ) {
3023 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3024 d->duck();
3027 //additional controls: thresh
3028 CK_DLL_CTRL( dyno_ctrl_thresh ) {
3029 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3030 d->thresh = GET_CK_FLOAT(ARGS);
3031 RETURN->v_float = (t_CKFLOAT)d->thresh;
3034 CK_DLL_CGET( dyno_cget_thresh ) {
3035 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3036 RETURN->v_float = (t_CKFLOAT)d->thresh;
3039 //additional controls: attackTime
3040 CK_DLL_CTRL( dyno_ctrl_attackTime ) {
3041 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3042 d->setAttackTime( GET_CK_FLOAT(ARGS) );
3043 RETURN->v_dur = d->timeConstToDur(d->at);
3046 CK_DLL_CGET( dyno_cget_attackTime ) {
3047 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3048 RETURN->v_dur = d->timeConstToDur(d->at);
3051 //additional controls: releaseTime
3052 CK_DLL_CTRL( dyno_ctrl_releaseTime ) {
3053 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3054 d->setReleaseTime( GET_CK_FLOAT(ARGS) );
3055 RETURN->v_dur = d->timeConstToDur(d->rt);
3058 CK_DLL_CGET( dyno_cget_releaseTime ) {
3059 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3060 RETURN->v_dur = d->timeConstToDur(d->rt);
3063 //additional controls: ratio
3064 CK_DLL_CTRL( dyno_ctrl_ratio ) {
3065 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3066 d->setRatio( GET_CK_FLOAT(ARGS) );
3067 RETURN->v_float = d->getRatio();
3070 CK_DLL_CGET( dyno_cget_ratio ) {
3071 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3072 RETURN->v_float = d->getRatio();
3075 //additional controls: slopeBelow
3076 CK_DLL_CTRL( dyno_ctrl_slopeBelow ) {
3077 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3078 d->slopeBelow = GET_CK_FLOAT(ARGS);
3080 RETURN->v_float = d->slopeBelow;
3083 CK_DLL_CGET( dyno_cget_slopeBelow ) {
3084 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3085 RETURN->v_float = d->slopeBelow;
3088 //additional controls: slopeAbove
3089 CK_DLL_CTRL( dyno_ctrl_slopeAbove ) {
3090 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3091 d->slopeAbove = GET_CK_FLOAT(ARGS);
3093 RETURN->v_float = d->slopeAbove;
3096 CK_DLL_CGET( dyno_cget_slopeAbove ) {
3097 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3098 RETURN->v_float = d->slopeAbove;
3101 //additional controls: sideInput
3102 CK_DLL_CTRL( dyno_ctrl_sideInput ) {
3103 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3104 d->sideInput = GET_CK_FLOAT(ARGS);
3106 RETURN->v_float = d->sideInput;
3109 CK_DLL_CGET( dyno_cget_sideInput ) {
3110 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3111 RETURN->v_float = d->sideInput;
3114 //additional controls: externalSideInput
3115 CK_DLL_CTRL( dyno_ctrl_externalSideInput ) {
3116 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3117 d->externalSideInput = GET_CK_INT(ARGS);
3119 RETURN->v_int = d->externalSideInput;
3122 CK_DLL_CGET( dyno_cget_externalSideInput ) {
3123 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3124 RETURN->v_int = d->externalSideInput;
3127 //constructor
3128 CK_DLL_CTOR( dyno_ctor )
3130 OBJ_MEMBER_UINT(SELF, dyno_offset_data) = (t_CKUINT)new Dyno_Data;
3133 CK_DLL_DTOR( dyno_dtor )
3135 delete (Dyno_Data *)OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3136 OBJ_MEMBER_UINT(SELF, dyno_offset_data) = 0;
3139 // recomputes envelope, determines how the current amp envelope compares with
3140 // thresh, applies the appropriate new slope depending on how far above/below
3141 // the threshold the current envelope is.
3142 CK_DLL_TICK( dyno_tick )
3144 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3146 // only change sideInput if we're not using an external ctrl signal.
3147 // otherwise we'll just use whatever the user sent us last as the ctrl signal
3148 if(!d->externalSideInput)
3149 d->sideInput = in >= 0 ? in : -in;
3151 // 'a' is signal left after subtracting xd (to recompute sideChain envelope)
3152 double a = d->sideInput - d->xd;
3153 // a is only needed if positive to pull the envelope up, not to bring it down
3154 if ( a < 0 ) a=0;
3155 // the attack/release (peak) exponential filter to guess envelope
3156 d->xd = d->xd * (1 - d->rt) + d->at * a;
3158 // if you were to use the rms filter,
3159 // it would probably look, a sumpthin' like this
3160 // d->xd = TAV * in*in + (1+TAV) * d->xd
3162 // decide which slope to use, depending on whether we're below/above thresh
3163 double slope = d->xd > d->thresh ? d->slopeAbove : d->slopeBelow;
3164 // the gain function - apply the slope chosen above
3165 double f = slope == 1.0 ? 1.0 : pow( d->xd / d->thresh, slope - 1.0 );
3167 // apply the gain found above to input sample
3168 *out = f * in;
3170 return TRUE;
3176 #define LiSa_MAXVOICES 200
3177 #define LiSa_MAXBUFSIZE 4410000
3178 //-----------------------------------------------------------------------------
3179 // name: LiSaMulti_data
3180 // desc: ...
3181 //-----------------------------------------------------------------------------
3182 struct LiSaMulti_data
3184 SAMPLE * mdata;
3185 t_CKINT mdata_len;
3186 t_CKINT maxvoices;
3187 t_CKINT loop_start[LiSa_MAXVOICES], loop_end[LiSa_MAXVOICES], loop_end_rec;
3188 t_CKINT rindex; // record and play indices
3189 t_CKBOOL record, looprec, loopplay[LiSa_MAXVOICES], reset, append, play[LiSa_MAXVOICES], bi[LiSa_MAXVOICES];
3190 t_CKFLOAT coeff; // feedback coeff
3191 t_CKFLOAT voiceGain[LiSa_MAXVOICES]; //gain control for each voice
3192 t_CKDOUBLE p_inc[LiSa_MAXVOICES], pindex[LiSa_MAXVOICES]; // playback increment
3194 // ramp stuff
3195 t_CKDOUBLE rampup_len[LiSa_MAXVOICES], rampdown_len[LiSa_MAXVOICES], rec_ramplen, rec_ramplen_inv;
3196 t_CKDOUBLE rampup_len_inv[LiSa_MAXVOICES], rampdown_len_inv[LiSa_MAXVOICES];
3197 t_CKDOUBLE rampctr[LiSa_MAXVOICES];
3198 t_CKBOOL rampup[LiSa_MAXVOICES], rampdown[LiSa_MAXVOICES];
3200 t_CKINT track;
3202 // allocate memory, length in samples
3203 inline int buffer_alloc(t_CKINT length)
3205 mdata = (SAMPLE *)malloc(length * sizeof(SAMPLE));
3206 if(!mdata) {
3207 fprintf(stderr, "LiSaBasic: unable to allocate memory!\n");
3208 return false;
3211 mdata_len = length;
3212 maxvoices = 10; // default; user can set
3213 rec_ramplen = 0.;
3214 rec_ramplen_inv = 1.;
3216 track = 0;
3218 for (t_CKINT i=0; i < LiSa_MAXVOICES; i++) {
3219 loop_start[i] = 0;
3220 loop_end[i] = length - 1;
3221 loop_end_rec = length;
3223 pindex[i] = rindex = 0;
3224 play[i] = record = bi[i] = false;
3225 looprec = loopplay[i] = true;
3226 coeff = 0.;
3227 p_inc[i] = 1.;
3228 voiceGain[i] = 1.;
3230 // ramp stuff
3231 rampup[i] = rampdown[i] = false;
3232 rampup_len[i] = rampdown_len[i] = 0.;
3233 rampup_len_inv[i] = rampdown_len_inv[i] = 1.;
3234 rampctr[i] = 0.;
3237 return true;
3240 // dump a sample into the buffer; retain existing sample, scaled by "coeff"
3241 inline void recordSamp(SAMPLE insample)
3243 SAMPLE tempsample;
3245 if(record) {
3246 if(looprec) {
3247 if(rindex >= loop_end_rec) rindex = 0;
3248 tempsample = coeff * mdata[rindex] + insample;
3249 //mdata[rindex] = coeff * mdata[rindex] + insample;
3250 //rindex++;
3251 } else {
3252 if (rindex < loop_end_rec) {
3253 //mdata[rindex] = coeff * mdata[rindex] + insample;
3254 tempsample = coeff * mdata[rindex] + insample;
3255 //rindex++;
3256 } else {
3257 record = 0;
3258 return;
3262 // ramp stuff here
3263 if(rindex < rec_ramplen) {
3264 tempsample *= (rindex * rec_ramplen_inv);
3265 //fprintf(stderr, "ramping up %f\n", rindex * rec_ramplen_inv);
3266 } else if(rindex > (loop_end_rec - rec_ramplen)) {
3267 tempsample *= (loop_end_rec - rindex) * rec_ramplen_inv;
3268 //fprintf(stderr, "ramping down %f\n", (loop_end_rec - rindex) * rec_ramplen_inv);
3270 mdata[rindex] = tempsample;
3271 rindex++;
3275 // grab a sample from the buffer, with linear interpolation (add prc's SINC interp later)
3276 // increment play index
3277 inline SAMPLE getNextSamp(t_CKINT which)
3279 // constrain
3280 if(loopplay[which]) {
3281 if(bi[which]) { // change direction if bidirectional mode
3282 if(pindex[which] > loop_end[which] || pindex[which] < loop_start[which]) {
3283 pindex[which] -= p_inc[which];
3284 p_inc[which] = -p_inc[which];
3287 if( loop_start[which] == loop_end[which] ) pindex[which] = loop_start[which]; //catch this condition to avoid infinite while loops
3288 else {
3289 while(pindex[which] > loop_end[which]) pindex[which] = loop_start[which] + (pindex[which] - loop_end[which]);
3290 while(pindex[which] < loop_start[which]) pindex[which] = loop_end[which] - (loop_start[which] - pindex[which]);
3293 } else if(pindex[which] > mdata_len || pindex[which] < 0) {
3294 play[which] = 0;
3295 //fprintf(stderr, "turning voice %d off!\n", which);
3296 return (SAMPLE) 0.;
3299 // interp
3300 t_CKINT whereTrunc = (t_CKINT) pindex[which];
3301 t_CKDOUBLE whereFrac = pindex[which] - (t_CKDOUBLE)whereTrunc;
3302 t_CKINT whereNext = whereTrunc + 1;
3304 if (loopplay[which]) {
3305 if((whereNext) == loop_end[which]) {
3306 whereNext = loop_start[which];
3308 } else {
3309 if((whereTrunc) == mdata_len) {
3310 whereTrunc = mdata_len - 1;
3311 whereNext = 0;
3315 pindex[which] += p_inc[which];
3317 t_CKDOUBLE outsample;
3318 outsample = (t_CKDOUBLE)mdata[whereTrunc] + (t_CKDOUBLE)(mdata[whereNext] - mdata[whereTrunc]) * whereFrac;
3320 // ramp stuff
3321 if(rampup[which]) {
3322 outsample *= rampctr[which]++ * rampup_len_inv[which]; //remove divide
3323 if(rampctr[which] >= rampup_len[which]) rampup[which] = false;
3325 else if(rampdown[which]) {
3326 outsample *= (rampdown_len[which] - rampctr[which]++) * rampdown_len_inv[which];
3327 if(rampctr[which] >= rampdown_len[which]) {
3328 rampdown[which] = false;
3329 play[which] = false;
3333 outsample *= voiceGain[which];
3335 return (SAMPLE)outsample;
3338 // grab a sample from the buffer, with linear interpolation (add prc's SINC interp later)
3339 // given a position within the buffer
3340 inline SAMPLE getSamp(t_CKDOUBLE where, t_CKINT which)
3342 // constrain
3343 if(where > loop_end[which]) where = loop_end[which];
3344 if(where < loop_start[which]) where = loop_start[which];
3346 // interp
3347 t_CKINT whereTrunc = (t_CKINT) where;
3348 t_CKDOUBLE whereFrac = where - (t_CKDOUBLE)whereTrunc;
3349 t_CKINT whereNext = whereTrunc + 1;
3351 if((whereNext) == loop_end[which]) whereNext = loop_start[which];
3353 t_CKDOUBLE outsample;
3354 outsample = (t_CKDOUBLE)mdata[whereTrunc] + (t_CKDOUBLE)(mdata[whereNext] - mdata[whereTrunc]) * whereFrac;
3355 outsample *= voiceGain[which];
3357 //add voiceGain ctl here; return (SAMPLE)vgain[which]*outsample;
3358 return (SAMPLE)outsample;
3361 // ramp stuff
3362 inline void ramp_up(t_CKINT voicenum, t_CKDUR uptime)
3364 // fprintf(stderr, "ramping up voice %d", voicenum);
3366 rampup[voicenum] = true;
3367 play[voicenum] = true;
3368 rampup_len[voicenum] = (t_CKDOUBLE)uptime;
3369 if(rampup_len[voicenum] > 0.) rampup_len_inv[voicenum] = 1./rampup_len[voicenum];
3370 else rampup_len[voicenum] = 1.;
3372 // check to make sure we are not mid ramping down
3373 if(rampdown[voicenum]) {
3374 rampctr[voicenum] = rampup_len[voicenum] * (1. - rampctr[voicenum]/rampdown_len[voicenum]);
3375 rampdown[voicenum] = false;
3376 } else rampctr[voicenum] = 0;
3379 inline void ramp_down(t_CKINT voicenum, t_CKDUR downtime)
3381 rampdown[voicenum] = true;
3382 rampdown_len[voicenum] = (t_CKDOUBLE)downtime;
3383 if(rampdown_len[voicenum] > 0.) rampdown_len_inv[voicenum] = 1./rampdown_len[voicenum];
3384 else rampdown_len[voicenum] = 1.;
3386 // check to make sure we are not mid ramping up
3387 if(rampup[voicenum]) {
3388 rampctr[voicenum] = rampdown_len[voicenum] * (1. - rampctr[voicenum]/rampup_len[voicenum]);
3389 rampup[voicenum] = false;
3390 } else rampctr[voicenum] = 0;
3393 inline void set_rec_ramplen(t_CKDUR newlen)
3395 rec_ramplen = (t_CKDOUBLE)newlen;
3396 if(rec_ramplen > 0.) rec_ramplen_inv = 1./rec_ramplen;
3397 else rec_ramplen_inv = 1.;
3398 //fprintf ( stderr, "rec_ramplen = %f, inv = %f \n", rec_ramplen, rec_ramplen_inv );
3401 // tick_multi: mono
3402 // may want to make multichannel version,
3403 // want to be able to do the following:
3404 // LiSa l;
3405 // l.pan(voice, panval)
3406 //for simple stereo panning of a particular voice, and...
3407 // l.channelGain(voice, channel, gain)
3408 //to set the gain for a particular voice going to a particular channel; good for >2 voices (like 6 channels!)
3409 inline SAMPLE tick_multi( SAMPLE in)
3411 if(!mdata) return (SAMPLE) 0.;
3413 recordSamp(in);
3415 SAMPLE tempsample = 0.;
3417 if(track==0) {
3418 for (t_CKINT i=0; i<maxvoices; i++) {
3419 if(play[i]) tempsample += getNextSamp(i);
3421 } else if(track==1) {
3422 if(in<0.) in = -in;
3423 for (t_CKINT i=0; i<maxvoices; i++) {
3424 if(play[i]) tempsample += getSamp((t_CKDOUBLE)in * (loop_end[i] - loop_start[i]) + loop_start[i], i);
3426 } else if(track==2 && play[0]) {
3427 if(in<0.) in = -in; //only use voice 0 when tracking with durs.
3428 tempsample = getSamp( (t_CKDOUBLE)in, 0 );
3431 return tempsample;
3434 inline void clear_buf()
3436 for (t_CKINT i = 0; i < mdata_len; i++)
3437 mdata[i] = 0.;
3440 inline t_CKINT get_free_voice()
3442 t_CKINT voicenumber = 0;
3443 while(play[voicenumber] && voicenumber < maxvoices) {
3444 voicenumber++;
3446 if(voicenumber == maxvoices) voicenumber = -1;
3447 return voicenumber;
3450 //stick sample in record buffer
3451 inline void pokeSample( SAMPLE insample, t_CKINT index ) {
3453 if ( index > mdata_len || index < 0 ) {
3454 index = 0;
3455 fprintf(stderr, "LiSa: trying to put sample out of buffer range; ignoring");
3456 } else mdata[index] = insample;
3460 //grab sample directly from record buffer, with linear interpolation
3461 inline SAMPLE grabSample ( t_CKDOUBLE where ) {
3463 if ( where > mdata_len || where < 0 ) {
3464 where = 0;
3465 fprintf(stderr, "LiSa: trying to grab sample out of buffer range; ignoring");
3466 return 0.;
3467 } else {
3469 // interp
3470 t_CKINT whereTrunc = (t_CKINT) where;
3471 t_CKDOUBLE whereFrac = where - (t_CKDOUBLE)whereTrunc;
3472 t_CKINT whereNext = whereTrunc + 1;
3474 if((whereNext) == mdata_len) whereNext = 0;
3476 t_CKDOUBLE outsample;
3477 outsample = (t_CKDOUBLE)mdata[whereTrunc] + (t_CKDOUBLE)(mdata[whereNext] - mdata[whereTrunc]) * whereFrac;
3479 //add voiceGain ctl here; return (SAMPLE)vgain[which]*outsample;
3480 return (SAMPLE)outsample;
3490 //++++++++++++++++++++++++++++++++++++++++
3493 //++++++++++++++++++++++++++++++++++++++++
3496 //++++++++++++++++++++++++++++++++++++++++
3501 //-----------------------------------------------------------------------------
3502 // name: LiSaMulti_ctor()
3503 // desc: CTOR function ...
3504 //-----------------------------------------------------------------------------
3505 CK_DLL_CTOR( LiSaMulti_ctor )
3508 LiSaMulti_data * f = new LiSaMulti_data;
3509 memset( f, 0, sizeof(LiSaMulti_data) );
3510 OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data) = (t_CKUINT)f;
3515 //-----------------------------------------------------------------------------
3516 // name: LiSaMulti_dtor()
3517 // desc: DTOR function ...
3518 //-----------------------------------------------------------------------------
3519 CK_DLL_DTOR( LiSaMulti_dtor )
3521 // get data
3522 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3523 // delete
3524 SAFE_DELETE(d);
3525 // set
3526 OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data) = 0;
3530 //-----------------------------------------------------------------------------
3531 // name: LiSaMulti_tick()
3532 // desc: TICK function ...
3533 //-----------------------------------------------------------------------------
3534 CK_DLL_TICK( LiSaMulti_tick )
3536 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3537 *out = d->tick_multi( in );
3538 return TRUE;
3542 //-----------------------------------------------------------------------------
3543 // name: LiSaMulti_size()
3544 // desc: set size of buffer allocation
3545 //-----------------------------------------------------------------------------
3546 CK_DLL_CTRL( LiSaMulti_size )
3548 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3549 t_CKDUR buflen = GET_NEXT_DUR(ARGS);
3550 if (buflen > LiSa_MAXBUFSIZE) {
3551 fprintf(stderr, "buffer size request too large, resizing\n");
3552 buflen = LiSa_MAXBUFSIZE;
3554 d->buffer_alloc((t_CKINT)buflen);
3556 RETURN->v_dur = (t_CKDUR)buflen;
3559 CK_DLL_CGET( LiSaMulti_cget_size )
3561 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3563 RETURN->v_dur = (t_CKDUR)d->mdata_len;
3567 //-----------------------------------------------------------------------------
3568 // name: LiSaMulti_start_record()
3569 // desc: CTRL function ...
3570 //-----------------------------------------------------------------------------
3571 CK_DLL_CTRL( LiSaMulti_start_record )
3573 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3574 d->record = GET_NEXT_INT(ARGS);
3576 RETURN->v_int = (t_CKINT)d->record;
3580 //-----------------------------------------------------------------------------
3581 // name: LiSaMulti_start_play()
3582 // desc: CTRL function
3583 //-----------------------------------------------------------------------------
3584 CK_DLL_CTRL( LiSaMulti_start_play )
3586 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3587 t_CKINT which = GET_NEXT_INT(ARGS);
3588 d->play[which] = GET_NEXT_INT(ARGS);
3589 //fprintf(stderr, "voice %d playing = %d\n", which, d->play[which]);
3591 //turn off ramping toggles
3592 d->rampdown[which] = false;
3593 d->rampup[which] = false;
3595 RETURN->v_int = (t_CKINT)d->play[which];
3599 //-----------------------------------------------------------------------------
3600 // name: LiSaMulti_start_play()
3601 // desc: CTRL function
3602 //-----------------------------------------------------------------------------
3603 CK_DLL_CTRL( LiSaMulti_start_play0 )
3606 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3607 d->play[0] = GET_NEXT_INT(ARGS);
3608 //fprintf(stderr, "voice %d playing = %d\n", which, d->play[which]);
3610 //turn off ramping toggles
3611 d->rampdown[0] = false;
3612 d->rampup[0] = false;
3614 RETURN->v_int = (t_CKINT)d->play[0];
3619 //-----------------------------------------------------------------------------
3620 // name: LiSaMulti_ctrl_rate()
3621 // desc: CTRL function
3622 //-----------------------------------------------------------------------------
3623 CK_DLL_CTRL( LiSaMulti_ctrl_rate )
3625 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3626 t_CKINT which = GET_NEXT_INT(ARGS);
3627 d->p_inc[which] = (t_CKDOUBLE)GET_NEXT_FLOAT(ARGS);
3628 //fprintf(stderr, "setting voice %d rate to %f\n", which, d->p_inc[which]);
3630 RETURN->v_float = d->p_inc[which];
3634 CK_DLL_CTRL( LiSaMulti_ctrl_rate0 )
3636 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3637 d->p_inc[0] = (t_CKDOUBLE)GET_NEXT_FLOAT(ARGS);
3638 //fprintf(stderr, "setting voice %d rate to %f\n", which, d->p_inc[which]);
3640 RETURN->v_float = d->p_inc[0];
3643 //-----------------------------------------------------------------------------
3644 // name: LiSaMulti_cget_rate()
3645 // desc: CTRL function
3646 //-----------------------------------------------------------------------------
3647 CK_DLL_CTRL( LiSaMulti_cget_rate )
3649 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3650 t_CKINT which = GET_NEXT_INT(ARGS);
3651 //fprintf(stderr, "setting voice %d rate to %f\n", which, d->p_inc[which]);
3653 RETURN->v_float = d->p_inc[which];
3657 CK_DLL_CTRL( LiSaMulti_cget_rate0 )
3659 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3660 //fprintf(stderr, "setting voice %d rate to %f\n", which, d->p_inc[which]);
3662 RETURN->v_float = d->p_inc[0];
3665 //-----------------------------------------------------------------------------
3666 // name: LiSaMulti_ctrl_pindex()
3667 // desc: CTRL function
3668 //-----------------------------------------------------------------------------
3669 CK_DLL_CTRL( LiSaMulti_ctrl_pindex )
3671 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3672 t_CKINT which = GET_NEXT_INT(ARGS);
3673 d->pindex[which] = (t_CKDOUBLE)GET_NEXT_DUR(ARGS);
3675 RETURN->v_dur = (t_CKDUR)d->pindex[which];
3679 CK_DLL_CTRL( LiSaMulti_ctrl_pindex0 )
3681 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3682 d->pindex[0] = (t_CKDOUBLE)GET_NEXT_DUR(ARGS);
3684 RETURN->v_dur = (t_CKDUR)d->pindex[0];
3688 //-----------------------------------------------------------------------------
3689 // name: LiSaMulti_cget_pindex()
3690 // desc: CGET function
3691 //-----------------------------------------------------------------------------
3692 CK_DLL_CGET( LiSaMulti_cget_pindex )
3694 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3695 t_CKINT which = GET_NEXT_INT(ARGS);
3697 // return
3698 RETURN->v_dur = (t_CKDUR)d->pindex[which];
3702 CK_DLL_CGET( LiSaMulti_cget_pindex0 )
3704 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3706 // return
3707 RETURN->v_dur = (t_CKDUR)d->pindex[0];
3711 //-----------------------------------------------------------------------------
3712 // name: LiSaMulti_ctrl_pindex()
3713 // desc: CTRL function
3714 //-----------------------------------------------------------------------------
3715 CK_DLL_CTRL( LiSaMulti_ctrl_rindex )
3717 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3718 d->rindex = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS);
3720 RETURN->v_dur = (t_CKDUR)d->rindex;
3724 //-----------------------------------------------------------------------------
3725 // name: LiSaMulti_cget_pindex()
3726 // desc: CGET function
3727 //-----------------------------------------------------------------------------
3728 CK_DLL_CGET( LiSaMulti_cget_rindex )
3730 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3732 // return
3733 RETURN->v_dur = (t_CKDUR)d->rindex;
3737 //-----------------------------------------------------------------------------
3738 // name: LiSaMulti_ctrl_lstart()
3739 // desc: CTRL function
3740 //-----------------------------------------------------------------------------
3741 CK_DLL_CTRL( LiSaMulti_ctrl_lstart )
3743 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3744 t_CKINT which = GET_NEXT_INT(ARGS);
3745 d->loop_start[which] = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS);
3747 if (d->loop_start[which] < 0) d->loop_start[which] = 0;
3749 RETURN->v_dur = (t_CKDUR)d->loop_start[which];
3753 CK_DLL_CTRL( LiSaMulti_ctrl_lstart0 )
3755 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3756 d->loop_start[0] = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS);
3758 if (d->loop_start[0] < 0) d->loop_start[0] = 0;
3760 RETURN->v_dur = (t_CKDUR)d->loop_start[0];
3764 //-----------------------------------------------------------------------------
3765 // name: LiSaMulti_cget_lstart()
3766 // desc: CGET function
3767 //-----------------------------------------------------------------------------
3768 CK_DLL_CGET( LiSaMulti_cget_lstart )
3770 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3772 t_CKINT which = GET_NEXT_INT(ARGS);
3773 // return
3774 RETURN->v_dur = (t_CKDUR)d->loop_start[which];
3778 CK_DLL_CGET( LiSaMulti_cget_lstart0 )
3780 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3782 // return
3783 RETURN->v_dur = (t_CKDUR)d->loop_start[0];
3787 //-----------------------------------------------------------------------------
3788 // name: LiSaMulti_ctrl_lend()
3789 // desc: CTRL function
3790 //-----------------------------------------------------------------------------
3791 CK_DLL_CTRL( LiSaMulti_ctrl_lend )
3793 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3794 t_CKINT which = GET_NEXT_INT(ARGS);
3795 d->loop_end[which] = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS);
3797 //check to make sure loop_end is not too large
3798 if (d->loop_end[which] >= d->mdata_len) d->loop_end[which] = d->mdata_len - 1;
3800 RETURN->v_dur = (t_CKDUR)d->loop_end[which];
3804 CK_DLL_CTRL( LiSaMulti_ctrl_lend0 )
3806 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3807 d->loop_end[0] = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS);
3809 //check to make sure loop_end is not too large
3810 if (d->loop_end[0] >= d->mdata_len) d->loop_end[0] = d->mdata_len - 1;
3812 RETURN->v_dur = (t_CKDUR)d->loop_end[0];
3816 //-----------------------------------------------------------------------------
3817 // name: LiSaMulti_cget_lend()
3818 // desc: CGET function
3819 //-----------------------------------------------------------------------------
3820 CK_DLL_CGET( LiSaMulti_cget_lend )
3822 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3823 t_CKINT which = GET_NEXT_INT(ARGS);
3825 // return
3826 RETURN->v_dur = (t_CKDUR)d->loop_end[which];
3830 CK_DLL_CGET( LiSaMulti_cget_lend0 )
3832 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3834 // return
3835 RETURN->v_dur = (t_CKDUR)d->loop_end[0];
3839 //-----------------------------------------------------------------------------
3840 // name: LiSaMulti_ctrl_loop()
3841 // desc: CTRL function
3842 //-----------------------------------------------------------------------------
3843 CK_DLL_CTRL( LiSaMulti_ctrl_loop )
3845 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3846 t_CKINT which = GET_NEXT_INT(ARGS);
3847 d->loopplay[which] = (t_CKBOOL)GET_NEXT_INT(ARGS);
3851 CK_DLL_CTRL( LiSaMulti_ctrl_loop0 )
3853 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3854 d->loopplay[0] = (t_CKBOOL)GET_NEXT_INT(ARGS);
3856 RETURN->v_int = (t_CKINT)d->loopplay[0];
3860 //-----------------------------------------------------------------------------
3861 // name: LiSaMulti_cget_loop()
3862 // desc: CGET function
3863 //-----------------------------------------------------------------------------
3864 CK_DLL_CGET( LiSaMulti_cget_loop )
3866 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3867 t_CKINT which = GET_NEXT_INT(ARGS);
3869 // return
3870 RETURN->v_int = (t_CKINT)d->loopplay[which];
3874 CK_DLL_CGET( LiSaMulti_cget_loop0 )
3876 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3878 // return
3879 RETURN->v_int = (t_CKINT)d->loopplay[0];
3883 //-----------------------------------------------------------------------------
3884 // name: LiSaMulti_ctrl_bi()
3885 // desc: CTRL function
3886 //-----------------------------------------------------------------------------
3887 CK_DLL_CTRL( LiSaMulti_ctrl_bi )
3889 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3890 t_CKINT which = GET_NEXT_INT(ARGS);
3891 d->bi[which] = (t_CKBOOL)GET_NEXT_INT(ARGS);
3893 RETURN->v_int = (t_CKINT)d->bi[which];
3897 CK_DLL_CTRL( LiSaMulti_ctrl_bi0 )
3899 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3900 d->bi[0] = (t_CKBOOL)GET_NEXT_INT(ARGS);
3902 RETURN->v_int = (t_CKINT)d->bi[0];
3906 //-----------------------------------------------------------------------------
3907 // name: LiSaMulti_cget_bi()
3908 // desc: CGET function
3909 //-----------------------------------------------------------------------------
3910 CK_DLL_CGET( LiSaMulti_cget_bi )
3912 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3913 t_CKINT which = GET_NEXT_INT(ARGS);
3915 // return
3916 RETURN->v_int = (t_CKINT)d->bi[which];
3920 CK_DLL_CGET( LiSaMulti_cget_bi0 )
3922 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3924 // return
3925 RETURN->v_int = (t_CKINT)d->bi[0];
3929 //-----------------------------------------------------------------------------
3930 // name: LiSaMulti_ctrl_loop_end_rec()
3931 // desc: CTRL function
3932 //-----------------------------------------------------------------------------
3933 CK_DLL_CTRL( LiSaMulti_ctrl_loop_end_rec )
3935 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3936 d->loop_end_rec = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS);
3938 RETURN->v_dur = (t_CKDUR)d->loop_end_rec;
3942 //-----------------------------------------------------------------------------
3943 // name: LiSaMulti_cget_loop_end_rec()
3944 // desc: CGET function
3945 //-----------------------------------------------------------------------------
3946 CK_DLL_CGET( LiSaMulti_cget_loop_end_rec )
3948 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3950 // return
3951 RETURN->v_dur = (t_CKDUR)d->loop_end_rec;
3955 //-----------------------------------------------------------------------------
3956 // name: LiSaMulti_ctrl_loop_rec()
3957 // desc: CTRL function
3958 //-----------------------------------------------------------------------------
3959 CK_DLL_CTRL( LiSaMulti_ctrl_loop_rec )
3961 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3962 d->looprec = (t_CKBOOL)GET_NEXT_INT(ARGS);
3964 RETURN->v_int = (t_CKINT)d->looprec;
3968 //-----------------------------------------------------------------------------
3969 // name: LiSaMulti_cget_loop_rec()
3970 // desc: CGET function
3971 //-----------------------------------------------------------------------------
3972 CK_DLL_CGET( LiSaMulti_cget_loop_rec )
3974 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3976 // return
3977 RETURN->v_int = (t_CKINT)d->looprec;
3980 //-----------------------------------------------------------------------------
3981 // name: LiSaMulti_ctrl_sample(); put a sample directly into record buffer
3982 // desc: CTRL function
3983 //-----------------------------------------------------------------------------
3984 CK_DLL_CTRL( LiSaMulti_ctrl_sample )
3986 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3987 SAMPLE sample_in = (SAMPLE)GET_NEXT_FLOAT(ARGS);
3988 int index_in = (t_CKINT)GET_NEXT_DUR(ARGS);
3990 d->pokeSample( sample_in, index_in );
3992 RETURN->v_float = (t_CKFLOAT)sample_in; //pass input through
3995 //-----------------------------------------------------------------------------
3996 // name: LiSaMulti_cget_sample(); grab a sample from the record buffer
3997 // desc: CGET function
3998 //-----------------------------------------------------------------------------
3999 CK_DLL_CGET( LiSaMulti_cget_sample )
4001 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4002 double index_in = (t_CKDOUBLE)GET_NEXT_DUR(ARGS);
4003 // return
4004 RETURN->v_float = (t_CKFLOAT)d->grabSample( index_in ); //change this to getSamp for interpolation
4008 //-----------------------------------------------------------------------------
4009 // name: LiSaMulti_ctrl_voicegain()
4010 // desc: CTRL function
4011 //-----------------------------------------------------------------------------
4012 CK_DLL_CTRL( LiSaMulti_ctrl_voicegain )
4014 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4015 t_CKINT which = GET_NEXT_INT(ARGS);
4016 d->voiceGain[which] = (t_CKDOUBLE)GET_NEXT_FLOAT(ARGS);
4018 RETURN->v_float = (t_CKFLOAT)d->coeff;
4022 //-----------------------------------------------------------------------------
4023 // name: LiSaMulti_cget_voicegain()
4024 // desc: CGET function
4025 //-----------------------------------------------------------------------------
4026 CK_DLL_CGET( LiSaMulti_cget_voicegain )
4028 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4029 t_CKINT which = GET_NEXT_INT(ARGS);
4031 // return
4032 RETURN->v_float = (t_CKFLOAT)d->voiceGain[which];
4036 //-----------------------------------------------------------------------------
4037 // name: LiSaMulti_ctrl_coeff()
4038 // desc: CTRL function
4039 //-----------------------------------------------------------------------------
4040 CK_DLL_CTRL( LiSaMulti_ctrl_coeff )
4042 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4043 d->coeff = (t_CKDOUBLE)GET_NEXT_FLOAT(ARGS);
4045 RETURN->v_float = (t_CKFLOAT)d->coeff;
4048 //-----------------------------------------------------------------------------
4049 // name: LiSaMulti_cget_coeff()
4050 // desc: CGET function
4051 //-----------------------------------------------------------------------------
4052 CK_DLL_CGET( LiSaMulti_cget_coeff )
4054 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4056 // return
4057 RETURN->v_float = (t_CKFLOAT)d->coeff;
4061 //-----------------------------------------------------------------------------
4062 // name: LiSaMulti_ctrl_clear()
4063 // desc: CTRL function
4064 //-----------------------------------------------------------------------------
4065 CK_DLL_CTRL( LiSaMulti_ctrl_clear )
4067 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4068 d->clear_buf();
4073 //-----------------------------------------------------------------------------
4074 // name: LiSaMulti_cget_voice()
4075 // desc: CGET function
4076 //-----------------------------------------------------------------------------
4077 CK_DLL_CGET( LiSaMulti_cget_voice )
4079 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4081 // return
4082 RETURN->v_int = (t_CKINT)d->get_free_voice();
4086 // ramp stuff
4087 //-----------------------------------------------------------------------------
4088 // name: LiSaMulti_ctrl_rampup()
4089 // desc: CTRL function
4090 //-----------------------------------------------------------------------------
4091 CK_DLL_CTRL( LiSaMulti_ctrl_rampup )
4093 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4094 t_CKINT voice = GET_NEXT_INT(ARGS);
4095 t_CKDUR len = GET_NEXT_DUR(ARGS);
4097 d->ramp_up(voice, len);
4099 RETURN->v_dur = (t_CKDUR)len;
4103 CK_DLL_CTRL( LiSaMulti_ctrl_rampup0 )
4105 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4106 t_CKDUR len = GET_NEXT_DUR(ARGS);
4108 d->ramp_up(0, len);
4110 RETURN->v_dur = (t_CKDUR)len;
4114 //-----------------------------------------------------------------------------
4115 // name: LiSaMulti_ctrl_rampdown()
4116 // desc: CTRL function
4117 //-----------------------------------------------------------------------------
4118 CK_DLL_CTRL( LiSaMulti_ctrl_rampdown )
4120 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4121 t_CKINT voice = GET_NEXT_INT(ARGS);
4122 t_CKDUR len = GET_NEXT_DUR(ARGS);
4124 d->ramp_down(voice, len);
4126 RETURN->v_dur = (t_CKDUR)len;
4130 CK_DLL_CTRL( LiSaMulti_ctrl_rampdown0 )
4132 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4133 t_CKDUR len = GET_NEXT_DUR(ARGS);
4135 d->ramp_down(0, len);
4137 RETURN->v_dur = (t_CKDUR)len;
4141 //-----------------------------------------------------------------------------
4142 // name: LiSaMulti_ctrl_rec_ramplen()
4143 // desc: CTRL function
4144 //-----------------------------------------------------------------------------
4145 CK_DLL_CTRL( LiSaMulti_ctrl_rec_ramplen )
4147 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4148 t_CKDUR newramplen = GET_NEXT_DUR(ARGS);
4149 d->set_rec_ramplen(newramplen);
4151 RETURN->v_dur = (t_CKDUR)newramplen;
4155 //-----------------------------------------------------------------------------
4156 // name: LiSaMulti_ctrl_maxvoices()
4157 // desc: CTRL function
4158 //-----------------------------------------------------------------------------
4159 CK_DLL_CTRL( LiSaMulti_ctrl_maxvoices )
4161 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4162 d->maxvoices = GET_NEXT_INT(ARGS);
4163 if( d->maxvoices > LiSa_MAXVOICES) {
4164 d->maxvoices = LiSa_MAXVOICES;
4165 fprintf(stderr, "LiSa: MAXVOICES limited to %d.\n", LiSa_MAXVOICES);
4167 RETURN->v_int = d->maxvoices;
4171 //-----------------------------------------------------------------------------
4172 // name: LiSaMulti_cget_maxvoices()
4173 // desc: CGET function
4174 //-----------------------------------------------------------------------------
4175 CK_DLL_CGET( LiSaMulti_cget_maxvoices )
4177 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4179 // return
4180 RETURN->v_int = d->maxvoices;
4184 //-----------------------------------------------------------------------------
4185 // name: LiSaMulti_cget_samp()
4186 // desc: CGET function
4187 //-----------------------------------------------------------------------------
4188 CK_DLL_CGET( LiSaMulti_cget_value )
4190 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4191 t_CKINT voice = GET_NEXT_INT(ARGS);
4192 t_CKDOUBLE where = (t_CKDOUBLE) GET_NEXT_DUR(ARGS);
4194 // return
4195 RETURN->v_dur = (t_CKDUR)d->getSamp(where, voice);
4199 CK_DLL_CGET( LiSaMulti_cget_value0 )
4201 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4203 t_CKDOUBLE where = (t_CKDOUBLE) GET_NEXT_DUR(ARGS);
4204 // return
4205 RETURN->v_dur = (t_CKDUR)d->getSamp(where, 0);
4209 //-----------------------------------------------------------------------------
4210 // name: LiSaMulti_ctrl_track()
4211 // desc: CTRL function
4212 //-----------------------------------------------------------------------------
4213 CK_DLL_CTRL( LiSaMulti_ctrl_track )
4215 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4216 d->track = (t_CKINT)GET_NEXT_INT(ARGS);
4218 RETURN->v_int = d->track;
4222 //-----------------------------------------------------------------------------
4223 // name: LiSaMulti_cget_sync()
4224 // desc: CGET function
4225 //-----------------------------------------------------------------------------
4226 CK_DLL_CGET( LiSaMulti_cget_track )
4228 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4230 // return
4231 RETURN->v_int = d->track;
4235 //-----------------------------------------------------------------------------
4236 // name: LiSaMulti_pmsg()
4237 // desc: PMSG function ...
4238 //-----------------------------------------------------------------------------
4239 CK_DLL_PMSG(LiSaMulti_pmsg )
4241 return FALSE;