*** empty log message ***
[chuck-blob.git] / v2 / ugen_xxx.cpp
blob7ddedaecceb4eae843022ef6bac069ec0c7e458f
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 delayp_offset_data = 0;
72 static t_CKUINT sndbuf_offset_data = 0;
73 static t_CKUINT dyno_offset_data = 0;
74 // static t_CKUINT zerox_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 #ifndef __DISABLE_SNDBUF__
515 // add sndbuf
516 //! sound buffer ( now interpolating )
517 //! reads from a variety of file formats
518 //! see \example sndbuf.ck
519 //QUERY->ugen_add( QUERY, "sndbuf", NULL );
520 // set funcs
521 //QUERY->ugen_func( QUERY, sndbuf_ctor, sndbuf_dtor, sndbuf_tick, NULL );
522 // set ctrl
523 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_read, NULL, "string", "read" ); //! loads file for reading
524 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_write, NULL, "string", "write" ); //! loads a file for writing ( or not )
525 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_pos, sndbuf_cget_pos, "int", "pos" ); //! set position ( 0 < p < .samples )
526 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_loop, sndbuf_cget_loop, "int", "loop" ); //! toggle looping
527 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_interp, sndbuf_cget_interp, "int", "interp" ); //! set interpolation ( 0=drop, 1=linear, 2=sinc )
528 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_rate, sndbuf_cget_rate, "float", "rate" ); //! playback rate ( relative to file's natural speed )
529 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_rate, sndbuf_cget_rate, "float", "play" ); //! play (same as rate)
530 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_freq, sndbuf_cget_freq, "float", "freq" ); //! playback rate ( file loops / second )
531 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_phase, sndbuf_cget_phase, "float", "phase" ); //! set phase position ( 0-1 )
532 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_channel, sndbuf_cget_channel, "int", "channel" ); //! select channel ( 0 < p < .channels )
533 //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_phase_offset, sndbuf_cget_phase, "float", "phase_offset" ); //! set a phase offset
534 //QUERY->ugen_ctrl( QUERY, NULL, sndbuf_cget_samples, "int", "samples" ); //! fetch number of samples
535 //QUERY->ugen_ctrl( QUERY, NULL, sndbuf_cget_length, "dur", "length" ); //! fetch length
536 //QUERY->ugen_ctrl( QUERY, NULL, sndbuf_cget_channels, "int", "channels" ); //! fetch number of channels
538 //---------------------------------------------------------------------
539 // init as base class: sndbuf
540 //---------------------------------------------------------------------
541 if( !type_engine_import_ugen_begin( env, "SndBuf", "UGen", env->global(),
542 sndbuf_ctor, sndbuf_dtor,
543 sndbuf_tick, NULL ) )
544 return FALSE;
546 // add member variable
547 sndbuf_offset_data = type_engine_import_mvar( env, "int", "@sndbuf_data", FALSE );
548 if( sndbuf_offset_data == CK_INVALID_OFFSET ) goto error;
550 // add ctrl: read
551 func = make_new_mfun( "string", "read", sndbuf_ctrl_read );
552 func->add_arg( "string", "read" );
553 if( !type_engine_import_mfun( env, func ) ) goto error;
554 // add cget: read // area
555 //func = make_new_mfun( "string", "read", sndbuf_cget_read );
556 //if( !type_engine_import_mfun( env, func ) ) goto error;
558 // add ctrl: write
559 func = make_new_mfun( "string", "write", sndbuf_ctrl_write );
560 func->add_arg( "string", "read" );
561 if( !type_engine_import_mfun( env, func ) ) goto error;
562 // add cget: write
563 //func = make_new_mfun( "string", "write", sndbuf_cget_write );
564 //if( !type_engine_import_mfun( env, func ) ) goto error;
566 // add ctrl: pos
567 func = make_new_mfun( "int", "pos", sndbuf_ctrl_pos );
568 func->add_arg( "int", "pos" );
569 if( !type_engine_import_mfun( env, func ) ) goto error;
570 // add cget: pos
571 func = make_new_mfun( "int", "pos", sndbuf_cget_pos );
572 if( !type_engine_import_mfun( env, func ) ) goto error;
574 // add ctrl: loop
575 func = make_new_mfun( "int", "loop", sndbuf_ctrl_loop );
576 func->add_arg( "int", "loop" );
577 if( !type_engine_import_mfun( env, func ) ) goto error;
578 // add cget: loop
579 func = make_new_mfun( "int", "loop", sndbuf_cget_loop );
580 if( !type_engine_import_mfun( env, func ) ) goto error;
582 // add ctrl: interp
583 func = make_new_mfun( "int", "interp", sndbuf_ctrl_interp );
584 func->add_arg( "int", "interp" );
585 if( !type_engine_import_mfun( env, func ) ) goto error;
586 // add cget: interp
587 func = make_new_mfun( "int", "interp", sndbuf_cget_interp );
588 if( !type_engine_import_mfun( env, func ) ) goto error;
590 // add ctrl: rate
591 func = make_new_mfun( "float", "rate", sndbuf_ctrl_rate );
592 func->add_arg( "float", "rate" );
593 if( !type_engine_import_mfun( env, func ) ) goto error;
594 // add cget: rate
595 func = make_new_mfun( "float", "rate", sndbuf_cget_rate );
596 if( !type_engine_import_mfun( env, func ) ) goto error;
598 // add ctrl: play
599 func = make_new_mfun( "float", "play", sndbuf_ctrl_rate );
600 func->add_arg( "float", "play" );
601 if( !type_engine_import_mfun( env, func ) ) goto error;
602 // add cget: play // good
603 func = make_new_mfun( "float", "play", sndbuf_cget_rate );
604 if( !type_engine_import_mfun( env, func ) ) goto error;
606 // add ctrl: freq
607 func = make_new_mfun( "float", "freq", sndbuf_ctrl_freq );
608 func->add_arg( "float", "freq" );
609 if( !type_engine_import_mfun( env, func ) ) goto error;
610 // add cget: freq
611 func = make_new_mfun( "float", "freq", sndbuf_cget_freq );
612 if( !type_engine_import_mfun( env, func ) ) goto error;
614 // add ctrl: phase
615 func = make_new_mfun( "float", "phase", sndbuf_ctrl_phase );
616 func->add_arg( "float", "phase" );
617 if( !type_engine_import_mfun( env, func ) ) goto error;
618 // add cget: phase
619 func = make_new_mfun( "float", "phase", sndbuf_cget_phase );
620 if( !type_engine_import_mfun( env, func ) ) goto error;
622 // add ctrl: channel
623 func = make_new_mfun( "int", "channel", sndbuf_ctrl_channel );
624 func->add_arg( "int", "channel" );
625 if( !type_engine_import_mfun( env, func ) ) goto error;
626 // add cget: channel
627 func = make_new_mfun( "int", "channel", sndbuf_cget_channel );
628 if( !type_engine_import_mfun( env, func ) ) goto error;
630 // add ctrl: phase_offset
631 func = make_new_mfun( "float", "phaseOffset", sndbuf_ctrl_phase_offset );
632 func->add_arg( "float", "value" );
633 if( !type_engine_import_mfun( env, func ) ) goto error;
634 // add cget: phase_offset
635 // func = make_new_mfun( "float", "phaseOffset", sndbuf_cget_phase_offset );
636 // if( !type_engine_import_mfun( env, func ) ) goto error;
638 // add ctrl: chunks
639 func = make_new_mfun( "int", "chunks", sndbuf_ctrl_chunks );
640 func->add_arg( "int", "frames" );
641 if( !type_engine_import_mfun( env, func ) ) goto error;
642 // add cget: chunks
643 func = make_new_mfun( "int", "chunks", sndbuf_cget_chunks );
644 if( !type_engine_import_mfun( env, func ) ) goto error;
646 // add cget: samples
647 func = make_new_mfun( "int", "samples", sndbuf_cget_samples );
648 if( !type_engine_import_mfun( env, func ) ) goto error;
650 // add cget: length
651 func = make_new_mfun( "dur", "length", sndbuf_cget_length );
652 if( !type_engine_import_mfun( env, func ) ) goto error;
654 // add cget: channels
655 func = make_new_mfun( "int", "channels", sndbuf_cget_channels );
656 if( !type_engine_import_mfun( env, func ) ) goto error;
658 // add cget: valueAt
659 func = make_new_mfun( "float", "valueAt", sndbuf_cget_valueAt );
660 func->add_arg( "int", "pos" );
661 if( !type_engine_import_mfun( env, func ) ) goto error;
663 // end import
664 if( !type_engine_import_class_end( env ) )
665 return FALSE;
667 #endif // __DISABLE_SNDBUF__
670 //---------------------------------------------------------------------
671 // init as base class: Dyno
672 //---------------------------------------------------------------------
673 if( !type_engine_import_ugen_begin( env, "Dyno", "UGen", env->global(),
674 dyno_ctor, dyno_dtor, dyno_tick, NULL ) )
675 return FALSE;
677 // add member variable
678 dyno_offset_data = type_engine_import_mvar( env, "int", "@dyno_data", FALSE );
679 if( dyno_offset_data == CK_INVALID_OFFSET ) goto error;
681 // add ctrl: limit
682 func = make_new_mfun( "void", "limit", dyno_ctrl_limit );
683 //func->add_arg( "string", "mode" );
684 if( !type_engine_import_mfun( env, func ) ) goto error;
686 // add ctrl: compress
687 func = make_new_mfun( "void", "compress", dyno_ctrl_compress );
688 //func->add_arg( "string", "mode" );
689 if( !type_engine_import_mfun( env, func ) ) goto error;
691 // add ctrl: gate
692 func = make_new_mfun( "void", "gate", dyno_ctrl_gate );
693 //func->add_arg( "string", "mode" );
694 if( !type_engine_import_mfun( env, func ) ) goto error;
696 // add ctrl: expand
697 func = make_new_mfun( "void", "expand", dyno_ctrl_expand );
698 //func->add_arg( "string", "mode" );
699 if( !type_engine_import_mfun( env, func ) ) goto error;
701 // add ctrl: duck
702 func = make_new_mfun( "void", "duck", dyno_ctrl_duck );
703 //func->add_arg( "string", "mode" );
704 if( !type_engine_import_mfun( env, func ) ) goto error;
706 //add ctrl: thresh
707 func = make_new_mfun( "float", "thresh", dyno_ctrl_thresh );
708 func->add_arg( "float", "thresh" );
709 if( !type_engine_import_mfun( env, func ) ) goto error;
711 // add cget: thresh
712 func = make_new_mfun( "float", "thresh", dyno_cget_thresh );
713 if( !type_engine_import_mfun( env, func ) ) goto error;
715 //add ctrl: attackTime
716 func = make_new_mfun( "dur", "attackTime", dyno_ctrl_attackTime );
717 func->add_arg( "dur", "aTime" );
718 if( !type_engine_import_mfun( env, func ) ) goto error;
720 //add cget: attackTime
721 func = make_new_mfun( "dur", "attackTime", dyno_ctrl_attackTime );
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 func->add_arg( "dur", "rTime" );
727 if( !type_engine_import_mfun( env, func ) ) goto error;
729 //add ctrl: releaseTime
730 func = make_new_mfun( "dur", "releaseTime", dyno_ctrl_releaseTime );
731 if( !type_engine_import_mfun( env, func ) ) goto error;
733 //add ctrl: ratio
734 func = make_new_mfun( "float", "ratio", dyno_ctrl_ratio );
735 func->add_arg( "float", "ratio" );
736 if( !type_engine_import_mfun( env, func ) ) goto error;
738 //add cget: ratio
739 func = make_new_mfun( "float", "ratio", dyno_cget_ratio );
740 if( !type_engine_import_mfun( env, func ) ) goto error;
742 //add ctrl: slopeBelow
743 func = make_new_mfun( "float", "slopeBelow", dyno_ctrl_slopeBelow );
744 func->add_arg( "float", "slopeBelow" );
745 if( !type_engine_import_mfun( env, func ) ) goto error;
747 //add cget: slopeBelow
748 func = make_new_mfun( "float", "slopeBelow", dyno_cget_slopeBelow );
749 if( !type_engine_import_mfun( env, func ) ) goto error;
751 //add ctrl: slopeAbove
752 func = make_new_mfun( "float", "slopeAbove", dyno_ctrl_slopeAbove );
753 func->add_arg( "float", "slopeAbove" );
754 if( !type_engine_import_mfun( env, func ) ) goto error;
756 //add cget: slopeAbove
757 func = make_new_mfun( "float", "slopeAbove", dyno_cget_slopeAbove );
758 if( !type_engine_import_mfun( env, func ) ) goto error;
760 //add ctrl: sideInput
761 func = make_new_mfun( "float", "sideInput", dyno_ctrl_sideInput );
762 func->add_arg( "float", "sideInput" );
763 if( !type_engine_import_mfun( env, func ) ) goto error;
765 //add cget: sideInput
766 func = make_new_mfun( "float", "sideInput", dyno_cget_sideInput );
767 if( !type_engine_import_mfun( env, func ) ) goto error;
769 //add ctrl: externalSideInput
770 func = make_new_mfun( "int", "externalSideInput", dyno_ctrl_externalSideInput );
771 func->add_arg( "int", "externalSideInput" );
772 if( !type_engine_import_mfun( env, func ) ) goto error;
774 //add cget: externalSideInput
775 func = make_new_mfun( "int", "externalSideInput", dyno_cget_externalSideInput );
776 if( !type_engine_import_mfun( env, func ) ) goto error;
778 // end import
779 if( !type_engine_import_class_end( env ) )
780 return FALSE;
782 // import LiSa!
783 if( !lisa_query( QUERY ) )
784 return FALSE;
786 return TRUE;
788 error:
790 // end the class import
791 type_engine_import_class_end( env );
793 return FALSE;
799 // LiSa (live sampling data offset)
800 static t_CKUINT LiSaBasic_offset_data = 0;
801 static t_CKUINT LiSaMulti_offset_data = 0;
803 //-----------------------------------------------------------------------------
804 // name: lisa_query()
805 // desc: ...
806 //-----------------------------------------------------------------------------
807 DLL_QUERY lisa_query( Chuck_DL_Query * QUERY )
809 Chuck_Env * env = Chuck_Env::instance();
810 Chuck_DL_Func * func = NULL;
812 //---------------------------------------------------------------------
813 // init class: LiSa; overloaded class for both LiSaBasic and LiSaMulti
814 // - probably don't need the others anymore....
815 // author: Dan Trueman (dan /at/ music.princeton.edu)
816 //---------------------------------------------------------------------
817 if( !type_engine_import_ugen_begin( env, "LiSa", "UGen", env->global(),
818 LiSaMulti_ctor, LiSaMulti_dtor,
819 LiSaMulti_tick, LiSaMulti_pmsg ) )
820 return FALSE;
822 // set/get buffer size
823 func = make_new_mfun( "dur", "duration", LiSaMulti_size );
824 func->add_arg( "dur", "val" );
825 if( !type_engine_import_mfun( env, func ) ) goto error;
826 func = make_new_mfun( "dur", "duration", LiSaMulti_cget_size );
827 if( !type_engine_import_mfun( env, func ) ) goto error;
829 // start/stop recording
830 func = make_new_mfun( "int", "record", LiSaMulti_start_record );
831 func->add_arg( "int", "toggle" );
832 if( !type_engine_import_mfun( env, func ) ) goto error;
834 // start/stop playing
835 func = make_new_mfun( "int", "play", LiSaMulti_start_play );
836 func->add_arg( "int", "voice" );
837 func->add_arg( "int", "toggle" );
838 if( !type_engine_import_mfun( env, func ) ) goto error;
839 func = make_new_mfun( "int", "play", LiSaMulti_start_play0 );
840 func->add_arg( "int", "toggle" );
841 if( !type_engine_import_mfun( env, func ) ) goto error;
843 // set/get playback rate
844 func = make_new_mfun( "float", "rate", LiSaMulti_ctrl_rate );
845 func->add_arg( "int", "voice" );
846 func->add_arg( "float", "val" );
847 if( !type_engine_import_mfun( env, func ) ) goto error;
848 func = make_new_mfun( "float", "rate", LiSaMulti_cget_rate );
849 func->add_arg( "int", "voice" );
850 if( !type_engine_import_mfun( env, func ) ) goto error;
851 func = make_new_mfun( "float", "rate", LiSaMulti_ctrl_rate0 );
852 func->add_arg( "float", "val" );
853 if( !type_engine_import_mfun( env, func ) ) goto error;
854 func = make_new_mfun( "float", "rate", LiSaMulti_cget_rate0 );
855 if( !type_engine_import_mfun( env, func ) ) goto error;
857 // playback position
858 func = make_new_mfun( "dur", "playPos", LiSaMulti_ctrl_pindex );
859 func->add_arg( "int", "voice" );
860 func->add_arg( "dur", "val" );
861 if( !type_engine_import_mfun( env, func ) ) goto error;
862 func = make_new_mfun( "dur", "playPos", LiSaMulti_cget_pindex );
863 func->add_arg( "int", "voice" );
864 if( !type_engine_import_mfun( env, func ) ) goto error;
865 func = make_new_mfun( "dur", "playPos", LiSaMulti_ctrl_pindex0 );
866 func->add_arg( "dur", "val" );
867 if( !type_engine_import_mfun( env, func ) ) goto error;
868 func = make_new_mfun( "dur", "playPos", LiSaMulti_cget_pindex0 );
869 if( !type_engine_import_mfun( env, func ) ) goto error;
871 // record position
872 func = make_new_mfun( "dur", "recPos", LiSaMulti_ctrl_rindex );
873 func->add_arg( "dur", "val" );
874 if( !type_engine_import_mfun( env, func ) ) goto error;
875 func = make_new_mfun( "dur", "recPos", LiSaMulti_cget_rindex );
876 if( !type_engine_import_mfun( env, func ) ) goto error;
878 // loopstart position
879 func = make_new_mfun( "dur", "loopStart", LiSaMulti_ctrl_lstart );
880 func->add_arg( "int", "voice" );
881 func->add_arg( "dur", "val" );
882 if( !type_engine_import_mfun( env, func ) ) goto error;
883 func = make_new_mfun( "dur", "loopStart", LiSaMulti_cget_lstart );
884 func->add_arg( "int", "voice" );
885 if( !type_engine_import_mfun( env, func ) ) goto error;
886 func = make_new_mfun( "dur", "loopStart", LiSaMulti_ctrl_lstart0 );
887 func->add_arg( "dur", "val" );
888 if( !type_engine_import_mfun( env, func ) ) goto error;
889 func = make_new_mfun( "dur", "loopStart", LiSaMulti_cget_lstart0 );
890 if( !type_engine_import_mfun( env, func ) ) goto error;
892 // loopend position
893 func = make_new_mfun( "dur", "loopEnd", LiSaMulti_ctrl_lend );
894 func->add_arg( "int", "voice" );
895 func->add_arg( "dur", "val" );
896 if( !type_engine_import_mfun( env, func ) ) goto error;
897 func = make_new_mfun( "dur", "loopEnd", LiSaMulti_cget_lend);
898 func->add_arg( "int", "voice" );
899 if( !type_engine_import_mfun( env, func ) ) goto error;
900 func = make_new_mfun( "dur", "loopEnd", LiSaMulti_ctrl_lend0 );
901 func->add_arg( "dur", "val" );
902 if( !type_engine_import_mfun( env, func ) ) goto error;
903 func = make_new_mfun( "dur", "loopEnd", LiSaMulti_cget_lend0);
904 if( !type_engine_import_mfun( env, func ) ) goto error;
906 // loop
907 func = make_new_mfun( "int", "loop", LiSaMulti_ctrl_loop );
908 func->add_arg( "int", "voice" );
909 func->add_arg( "int", "val" );
910 if( !type_engine_import_mfun( env, func ) ) goto error;
911 func = make_new_mfun( "int", "loop", LiSaMulti_cget_loop);
912 func->add_arg( "int", "voice" );
913 if( !type_engine_import_mfun( env, func ) ) goto error;
914 func = make_new_mfun( "int", "loop", LiSaMulti_ctrl_loop0 );
915 func->add_arg( "int", "val" );
916 if( !type_engine_import_mfun( env, func ) ) goto error;
917 func = make_new_mfun( "int", "loop", LiSaMulti_cget_loop0);
918 if( !type_engine_import_mfun( env, func ) ) goto error;
920 // bidirectional looping
921 func = make_new_mfun( "int", "bi", LiSaMulti_ctrl_bi );
922 func->add_arg( "int", "voice" );
923 func->add_arg( "int", "val" );
924 if( !type_engine_import_mfun( env, func ) ) goto error;
925 func = make_new_mfun( "int", "bi", LiSaMulti_cget_bi);
926 func->add_arg( "int", "voice" );
927 if( !type_engine_import_mfun( env, func ) ) goto error;
928 func = make_new_mfun( "int", "bi", LiSaMulti_ctrl_bi0 );
929 func->add_arg( "int", "val" );
930 if( !type_engine_import_mfun( env, func ) ) goto error;
931 func = make_new_mfun( "int", "bi", LiSaMulti_cget_bi0);
932 if( !type_engine_import_mfun( env, func ) ) goto error;
934 // loopend_rec position
935 func = make_new_mfun( "dur", "loopEndRec", LiSaMulti_ctrl_loop_end_rec );
936 func->add_arg( "dur", "val" );
937 if( !type_engine_import_mfun( env, func ) ) goto error;
938 func = make_new_mfun( "dur", "loopEndRec", LiSaMulti_cget_loop_end_rec);
939 if( !type_engine_import_mfun( env, func ) ) goto error;
941 // loop_rec toggle set; for turning on/off loop recording
942 func = make_new_mfun( "int", "loopRec", LiSaMulti_ctrl_loop_rec );
943 func->add_arg( "int", "val" );
944 if( !type_engine_import_mfun( env, func ) ) goto error;
945 func = make_new_mfun( "int", "loopRec", LiSaMulti_cget_loop_rec);
946 if( !type_engine_import_mfun( env, func ) ) goto error;
948 // look at or put sample directly in record buffer, do not pass go
949 func = make_new_mfun( "float", "valueAt", LiSaMulti_ctrl_sample );
950 func->add_arg( "float", "val" );
951 func->add_arg( "dur", "index" );
952 if( !type_engine_import_mfun( env, func ) ) goto error;
953 func = make_new_mfun( "float", "valueAt", LiSaMulti_cget_sample);
954 func->add_arg( "dur", "index" );
955 if( !type_engine_import_mfun( env, func ) ) goto error;
957 // set/get voiceGain
958 func = make_new_mfun( "float", "voiceGain", LiSaMulti_ctrl_voicegain );
959 func->add_arg( "int", "voice" );
960 func->add_arg( "float", "val" );
961 if( !type_engine_import_mfun( env, func ) ) goto error;
962 func = make_new_mfun( "float", "voiceGain", LiSaMulti_cget_voicegain);
963 func->add_arg( "int", "voice" );
965 // set record feedback coefficient
966 func = make_new_mfun( "float", "feedback", LiSaMulti_ctrl_coeff );
967 func->add_arg( "float", "val" );
968 if( !type_engine_import_mfun( env, func ) ) goto error;
969 func = make_new_mfun( "float", "feedback", LiSaMulti_cget_coeff);
970 if( !type_engine_import_mfun( env, func ) ) goto error;
972 // clear buffer
973 func = make_new_mfun( "void", "clear", LiSaMulti_ctrl_clear );
974 if( !type_engine_import_mfun( env, func ) ) goto error;
976 // get free voice
977 func = make_new_mfun( "int", "getVoice", LiSaMulti_cget_voice );
978 if( !type_engine_import_mfun( env, func ) ) goto error;
980 // set maxvoices
981 func = make_new_mfun( "int", "maxVoices", LiSaMulti_ctrl_maxvoices );
982 func->add_arg( "int", "val" );
983 if( !type_engine_import_mfun( env, func ) ) goto error;
984 func = make_new_mfun( "int", "maxVoices", LiSaMulti_cget_maxvoices);
985 if( !type_engine_import_mfun( env, func ) ) goto error;
987 // ramp stuff
988 func = make_new_mfun( "void", "rampUp", LiSaMulti_ctrl_rampup );
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( "void", "rampDown", LiSaMulti_ctrl_rampdown );
994 func->add_arg( "int", "voice" );
995 func->add_arg( "dur", "val" );
996 if( !type_engine_import_mfun( env, func ) ) goto error;
998 func = make_new_mfun( "dur", "recRamp", LiSaMulti_ctrl_rec_ramplen );
999 func->add_arg( "dur", "val" );
1000 if( !type_engine_import_mfun( env, func ) ) goto error;
1002 func = make_new_mfun( "void", "rampUp", LiSaMulti_ctrl_rampup0 );
1003 func->add_arg( "dur", "val" );
1004 if( !type_engine_import_mfun( env, func ) ) goto error;
1006 func = make_new_mfun( "void", "rampDown", LiSaMulti_ctrl_rampdown0 );
1007 func->add_arg( "dur", "val" );
1008 if( !type_engine_import_mfun( env, func ) ) goto error;
1010 // get value
1011 func = make_new_mfun( "dur", "value", LiSaMulti_cget_value );
1012 func->add_arg( "int", "voice" );
1013 func->add_arg( "dur", "val" );
1014 if( !type_engine_import_mfun( env, func ) ) goto error;
1015 func = make_new_mfun( "dur", "value", LiSaMulti_cget_value0 );
1016 func->add_arg( "dur", "val" );
1017 if( !type_engine_import_mfun( env, func ) ) goto error;
1019 // track
1020 func = make_new_mfun( "int", "track", LiSaMulti_ctrl_track );
1021 func->add_arg( "int", "val" );
1022 if( !type_engine_import_mfun( env, func ) ) goto error;
1023 func = make_new_mfun( "int", "track", LiSaMulti_cget_track);
1024 if( !type_engine_import_mfun( env, func ) ) goto error;
1026 // sync = track
1027 func = make_new_mfun( "int", "sync", LiSaMulti_ctrl_track );
1028 func->add_arg( "int", "val" );
1029 if( !type_engine_import_mfun( env, func ) ) goto error;
1030 func = make_new_mfun( "int", "sync", LiSaMulti_cget_track);
1031 if( !type_engine_import_mfun( env, func ) ) goto error;
1033 // sync = track
1034 func = make_new_mfun( "int", "sync", LiSaMulti_ctrl_track );
1035 func->add_arg( "int", "val" );
1036 if( !type_engine_import_mfun( env, func ) ) goto error;
1037 func = make_new_mfun( "int", "sync", LiSaMulti_cget_track);
1038 if( !type_engine_import_mfun( env, func ) ) goto error;
1040 // end the class import
1041 type_engine_import_class_end( env );
1043 return TRUE;
1045 error:
1047 // end the class import
1048 type_engine_import_class_end( env );
1050 return FALSE;
1056 //-----------------------------------------------------------------------------
1057 // name: multi_ctor()
1058 // desc: ...
1059 //-----------------------------------------------------------------------------
1060 CK_DLL_CTOR( multi_ctor )
1062 // do nothing
1068 //-----------------------------------------------------------------------------
1069 // name: multi_cget_chan()
1070 // desc: ...
1071 //-----------------------------------------------------------------------------
1072 CK_DLL_CGET( multi_cget_chan )
1074 // get ugen
1075 Chuck_UGen * ugen = (Chuck_UGen *)SELF;
1076 // value
1077 t_CKINT index = GET_NEXT_INT( ARGS );
1078 // return
1079 RETURN->v_object = index >= 0 && index < ugen->m_multi_chan_size ?
1080 ugen->m_multi_chan[index] : NULL ;
1086 //-----------------------------------------------------------------------------
1087 // name: stereo_ctor()
1088 // desc: ...
1089 //-----------------------------------------------------------------------------
1090 CK_DLL_CTOR( stereo_ctor )
1092 // get ugen
1093 Chuck_UGen * ugen = (Chuck_UGen *)SELF;
1095 // multi
1096 if( ugen->m_multi_chan_size )
1098 // set left
1099 OBJ_MEMBER_UINT(SELF, stereo_offset_left) = (t_CKUINT)(ugen->m_multi_chan[0]);
1100 // set right
1101 OBJ_MEMBER_UINT(SELF, stereo_offset_right) = (t_CKUINT)(ugen->m_multi_chan[1]);
1103 else // mono
1105 // set left and right to self
1106 OBJ_MEMBER_UINT(SELF, stereo_offset_left) = (t_CKUINT)ugen;
1107 OBJ_MEMBER_UINT(SELF, stereo_offset_right) = (t_CKUINT)ugen;
1114 //-----------------------------------------------------------------------------
1115 // name: stereo_ctrl_pan()
1116 // desc: ...
1117 //-----------------------------------------------------------------------------
1118 CK_DLL_CTRL( stereo_ctrl_pan )
1120 Chuck_UGen * ugen = (Chuck_UGen * )SELF;
1121 Chuck_UGen * left = ugen->m_multi_chan[0];
1122 Chuck_UGen * right = ugen->m_multi_chan[1];
1123 // get arg
1124 t_CKFLOAT pan = GET_CK_FLOAT(ARGS);
1125 // clip it
1126 if( pan < -1.0 ) pan = -1.0;
1127 else if( pan > 1.0 ) pan = 1.0;
1128 // set it
1129 OBJ_MEMBER_FLOAT(SELF, stereo_offset_pan) = pan;
1130 // pan it
1131 left->m_pan = pan < 0.0 ? 1.0 : 1.0 - pan;
1132 right->m_pan = pan > 0.0 ? 1.0 : 1.0 + pan;
1134 RETURN->v_float = pan;
1140 //-----------------------------------------------------------------------------
1141 // name: stereo_cget_pan()
1142 // desc: ...
1143 //-----------------------------------------------------------------------------
1144 CK_DLL_CGET( stereo_cget_pan )
1146 RETURN->v_float = OBJ_MEMBER_FLOAT(SELF, stereo_offset_pan);
1152 //-----------------------------------------------------------------------------
1153 // name: dac_tick()
1154 // desc: ...
1155 //-----------------------------------------------------------------------------
1156 CK_DLL_TICK( dac_tick )
1158 *out = in; return TRUE;
1164 //-----------------------------------------------------------------------------
1165 // name: bunghole_tick
1166 // desc: ...
1167 //-----------------------------------------------------------------------------
1168 CK_DLL_TICK( bunghole_tick )
1170 *out = 0.0f; return 0;
1176 //-----------------------------------------------------------------------------
1177 // name: noise_tick()
1178 // desc: ...
1179 //-----------------------------------------------------------------------------
1180 CK_DLL_TICK( noise_tick )
1182 *out = -1.0 + 2.0 * (SAMPLE)rand() / RAND_MAX;
1183 return TRUE;
1187 enum { NOISE_WHITE=0, NOISE_PINK, NOISE_BROWN, NOISE_FBM, NOISE_FLIP, NOISE_XOR };
1189 class CNoise_Data
1191 private:
1192 SAMPLE value;
1194 t_CKFLOAT fbmH;
1195 t_CKINT counter;
1196 t_CKINT * pink_array;
1197 t_CKINT pink_depth;
1198 bool pink_rand;
1199 t_CKINT rand_bits;
1200 double scale;
1201 double bias;
1203 t_CKINT last;
1205 public:
1206 CNoise_Data() {
1207 value = 0;
1208 mode = NOISE_PINK;
1209 pink_depth = 24;
1210 pink_array = NULL;
1211 counter = 1;
1212 scale = 2.0 / (double) RAND_MAX ;
1213 bias = -1.0;
1214 pink_rand = false;
1215 t_CKINT randt = RAND_MAX;
1216 rand_bits = 0;
1217 fprob = (t_CKINT)( (double)RAND_MAX * 1.0 / 32.0 );
1218 while ( randt > 0 ) {
1219 rand_bits++;
1220 randt = randt >> 1;
1222 // fprintf(stderr, "random bits - %d", rand_bits );
1223 setMode ( "pink" );
1225 ~CNoise_Data() {}
1227 t_CKINT fprob;
1228 t_CKUINT mode;
1229 void tick( t_CKTIME now, SAMPLE * out );
1230 void setMode( const char * c );
1232 t_CKINT pink_tick( SAMPLE * out);
1233 t_CKINT brown_tick( SAMPLE * out);
1234 t_CKINT xor_tick( SAMPLE * out);
1235 t_CKINT flip_tick( SAMPLE * out);
1236 t_CKINT fbm_tick( SAMPLE * out);
1240 CK_DLL_CTOR( cnoise_ctor )
1242 OBJ_MEMBER_UINT(SELF, cnoise_offset_data) = (t_CKUINT)new CNoise_Data;
1245 CK_DLL_DTOR( cnoise_dtor )
1247 delete (CNoise_Data *)OBJ_MEMBER_UINT(SELF, cnoise_offset_data);
1248 OBJ_MEMBER_UINT(SELF, cnoise_offset_data) = 0;
1251 CK_DLL_TICK( cnoise_tick )
1253 CNoise_Data * d = ( CNoise_Data * )OBJ_MEMBER_UINT(SELF, cnoise_offset_data);
1254 switch( d->mode ) {
1255 case NOISE_WHITE:
1256 return noise_tick(SELF,in,out,SHRED);
1257 break;
1258 case NOISE_PINK:
1259 return d->pink_tick(out);
1260 break;
1261 case NOISE_BROWN:
1262 return d->brown_tick(out);
1263 break;
1264 case NOISE_XOR:
1265 return d->xor_tick(out);
1266 break;
1267 case NOISE_FLIP:
1268 return d->flip_tick(out);
1269 break;
1270 case NOISE_FBM:
1271 return d->fbm_tick(out);
1272 break;
1274 return TRUE;
1277 t_CKINT CNoise_Data::pink_tick( SAMPLE * out )
1279 //based on Voss-McCartney
1281 if ( pink_array == NULL ) {
1282 pink_array = (t_CKINT *) malloc ( sizeof ( t_CKINT ) * pink_depth );
1283 last = 0;
1284 for ( t_CKINT i = 0 ; i < pink_depth ; i++ ) { pink_array[i] = rand(); last += pink_array[i]; }
1285 scale = 2.0 / ((double)RAND_MAX * ( pink_depth + 1.0 ) );
1286 bias = 0.0;
1287 // fprintf( stderr, "scale %f %f %d %d \n", scale, bias, RAND_MAX, pink_depth + 1 );
1290 t_CKINT pind = 0;
1292 //count trailing zeroes
1293 while ( pind < pink_depth && ! (counter & ( 1 << pind ) ) ) pind++;
1295 // fprintf (stderr, "counter %d pink - %d \n", counter, pind );
1297 if ( pind < pink_depth ) {
1298 t_CKINT diff = rand() - pink_array[pind];
1299 pink_array[pind] += diff;
1300 last += diff;
1303 *out = bias + scale * ( rand() + last );
1304 counter++;
1305 if ( pink_rand ) counter = rand();
1306 return TRUE;
1309 t_CKINT CNoise_Data::xor_tick( SAMPLE * out )
1311 t_CKINT mask = 0;
1312 for ( t_CKINT i = 0; i < rand_bits ; i++ )
1313 if ( rand() <= fprob )
1314 mask |= ( 1 << i );
1315 last = last ^ mask;
1316 *out = bias + scale * (SAMPLE)last;
1317 return TRUE;
1320 t_CKINT CNoise_Data::flip_tick( SAMPLE * out )
1322 t_CKINT ind = (t_CKINT) ( (double) rand_bits * rand() / ( RAND_MAX + 1.0 ) );
1324 last = last ^ ( 1 << ind );
1325 // fprintf ( stderr, "ind - %d %d %f %f", ind, last, bias, scale );
1326 *out = bias + scale * (SAMPLE)last;
1327 return TRUE;
1330 t_CKINT
1331 CNoise_Data::brown_tick( SAMPLE * out ) {
1332 //brownian noise function..later!
1333 *out = 0;
1334 return TRUE;
1337 t_CKINT
1338 CNoise_Data::fbm_tick( SAMPLE * out ) {
1339 //non-brownian noise function..later!
1340 *out = 0;
1341 return TRUE;
1344 void
1345 CNoise_Data::setMode( const char * c ) {
1346 if ( strcmp ( c, "white" ) == 0 ) {
1347 // fprintf(stderr, "white noise\n");
1348 mode = NOISE_WHITE;
1349 scale = 2.0 / (t_CKFLOAT)RAND_MAX;
1350 bias = -1.0;
1352 if ( strcmp ( c, "pink" ) == 0 ) {
1353 // fprintf(stderr, "pink noise\n");
1354 mode = NOISE_PINK;
1355 scale = 2.0 / (double)(RAND_MAX * ( pink_depth + 1 ) );
1356 bias = -1.0;
1358 if ( strcmp ( c, "flip" ) == 0) {
1359 // fprintf(stderr, "bitflip noise\n");
1360 mode = NOISE_FLIP;
1361 scale = 2.0 / (t_CKFLOAT)RAND_MAX;
1362 bias = -1.0;
1364 if ( strcmp ( c, "xor" ) == 0) {
1365 // fprintf(stderr, "xor noise\n");
1366 mode = NOISE_XOR;
1367 scale = 2.0 / (t_CKFLOAT)RAND_MAX;
1368 bias = -1.0;
1370 if ( strcmp ( c, "brown" ) == 0) {
1371 // fprintf(stderr, "brownian noise\n");
1372 mode = NOISE_BROWN;
1373 scale = 2.0 / (t_CKFLOAT)RAND_MAX;
1374 bias = -1.0;
1376 if ( strcmp ( c, "fbm" ) == 0) {
1377 // fprintf(stderr, "fbm noise\n");
1378 mode = NOISE_FBM;
1379 scale = 2.0 / (t_CKFLOAT)RAND_MAX;
1380 bias = -1.0;
1385 CK_DLL_CTRL( cnoise_ctrl_mode )
1387 CNoise_Data * d = ( CNoise_Data * )OBJ_MEMBER_UINT(SELF, cnoise_offset_data);
1388 const char * mode= (const char *)*(char **)GET_CK_STRING(ARGS);
1389 d->setMode(mode);
1392 CK_DLL_CTRL( cnoise_ctrl_fprob )
1394 CNoise_Data * d = ( CNoise_Data * )OBJ_MEMBER_UINT(SELF, cnoise_offset_data);
1395 t_CKFLOAT p= GET_CK_FLOAT(ARGS);
1396 d->fprob = (t_CKINT) ( (double)RAND_MAX * p );
1401 //-----------------------------------------------------------------------------
1402 // name: struct Pulse_Data
1403 // desc: ...
1404 //-----------------------------------------------------------------------------
1405 struct Pulse_Data
1407 SAMPLE value;
1408 t_CKUINT when;
1409 Pulse_Data( ) { value = 1.0f; when = 0; }
1413 //-----------------------------------------------------------------------------
1414 // name: impulse_ctor()
1415 // desc: ...
1416 //-----------------------------------------------------------------------------
1417 CK_DLL_CTOR( impulse_ctor )
1419 // return data to be used later
1420 OBJ_MEMBER_UINT(SELF, impulse_offset_data) = (t_CKUINT)new Pulse_Data;
1426 //-----------------------------------------------------------------------------
1427 // name: impulse_dtor()
1428 // desc: ...
1429 //-----------------------------------------------------------------------------
1430 CK_DLL_DTOR( impulse_dtor )
1432 // delete
1433 delete (Pulse_Data *)OBJ_MEMBER_UINT(SELF, impulse_offset_data);
1434 OBJ_MEMBER_UINT(SELF, impulse_offset_data) = 0;
1440 //-----------------------------------------------------------------------------
1441 // name: impulse_tick()
1442 // desc: ...
1443 //-----------------------------------------------------------------------------
1444 CK_DLL_TICK( impulse_tick )
1446 Pulse_Data * d = (Pulse_Data *)OBJ_MEMBER_UINT(SELF, impulse_offset_data);
1447 if( d->when )
1449 *out = d->value;
1450 d->when = 0;
1452 else
1453 *out = 0.0f;
1455 return TRUE;
1460 //-----------------------------------------------------------------------------
1461 // name: impulse_ctrl_next()
1462 // desc: ...
1463 //-----------------------------------------------------------------------------
1464 CK_DLL_CTRL( impulse_ctrl_next )
1466 Pulse_Data * d = (Pulse_Data *)OBJ_MEMBER_UINT(SELF, impulse_offset_data);
1467 d->value = (SAMPLE)GET_CK_FLOAT(ARGS);
1468 d->when = 1;
1469 RETURN->v_float = (t_CKFLOAT)d->value;
1475 //-----------------------------------------------------------------------------
1476 // name: impulse_cget_next()
1477 // desc: ...
1478 //-----------------------------------------------------------------------------
1479 CK_DLL_CGET( impulse_cget_next )
1481 Pulse_Data * d = (Pulse_Data *)OBJ_MEMBER_UINT(SELF, impulse_offset_data);
1482 RETURN->v_float = (t_CKFLOAT)d->value;
1488 //-----------------------------------------------------------------------------
1489 // name: step_ctor()
1490 // desc: ...
1491 //-----------------------------------------------------------------------------
1492 CK_DLL_CTOR( step_ctor )
1494 // return data to be used later
1495 OBJ_MEMBER_UINT(SELF, step_offset_data) = (t_CKUINT)new SAMPLE( 1.0f );
1501 //-----------------------------------------------------------------------------
1502 // name: step_dtor()
1503 // desc: ...
1504 //-----------------------------------------------------------------------------
1505 CK_DLL_DTOR( step_dtor )
1507 // delete
1508 delete (SAMPLE *)OBJ_MEMBER_UINT(SELF, step_offset_data);
1509 OBJ_MEMBER_UINT(SELF, step_offset_data) = 0;
1513 //-----------------------------------------------------------------------------
1514 // name: step_tick()
1515 // desc: ...
1516 //-----------------------------------------------------------------------------
1517 CK_DLL_TICK( step_tick )
1519 SAMPLE * d = (SAMPLE *)OBJ_MEMBER_UINT(SELF, step_offset_data);
1520 *out = *d;
1522 return TRUE;
1526 //-----------------------------------------------------------------------------
1527 // name: step_ctrl_next()
1528 // desc: ...
1529 //-----------------------------------------------------------------------------
1530 CK_DLL_CTRL( step_ctrl_next )
1532 SAMPLE * d = (SAMPLE *)OBJ_MEMBER_UINT(SELF, step_offset_data);
1533 *d = (SAMPLE)GET_CK_FLOAT(ARGS);
1534 RETURN->v_float = (t_CKFLOAT)(*d);
1538 //-----------------------------------------------------------------------------
1539 // name: step_cget_next()
1540 // desc: ...
1541 //-----------------------------------------------------------------------------
1542 CK_DLL_CGET( step_cget_next )
1544 SAMPLE * d = (SAMPLE *)OBJ_MEMBER_UINT(SELF, step_offset_data);
1545 RETURN->v_float = (t_CKFLOAT)(*d);
1551 //-----------------------------------------------------------------------------
1552 // name: halfrect_tick()
1553 // desc: ...
1554 //-----------------------------------------------------------------------------
1555 CK_DLL_TICK( halfrect_tick )
1557 *out = in > 0.0f ? in : 0.0f;
1558 return TRUE;
1564 //-----------------------------------------------------------------------------
1565 // name: fullrect_tick()
1566 // desc: ...
1567 //-----------------------------------------------------------------------------
1568 CK_DLL_TICK( fullrect_tick )
1570 *out = in >= 0.0f ? in : -in;
1571 return TRUE;
1578 //-----------------------------------------------------------------------------
1579 // name: zerox_ctor()
1580 // desc: ...
1581 //-----------------------------------------------------------------------------
1582 CK_DLL_CTOR( zerox_ctor )
1584 OBJ_MEMBER_UINT(SELF, zerox_offset_data) = (t_CKUINT)new SAMPLE( 0.0f );
1588 //-----------------------------------------------------------------------------
1589 // name: zerox_dtor()
1590 // desc: ...
1591 //-----------------------------------------------------------------------------
1592 CK_DLL_DTOR( zerox_dtor )
1594 delete (SAMPLE *)OBJ_MEMBER_UINT(SELF, zerox_offset_data);
1595 OBJ_MEMBER_UINT(SELF, zerox_offset_data) = 0;
1599 #define __SGN(x) (x >= 0.0f ? 1.0f : -1.0f )
1600 //-----------------------------------------------------------------------------
1601 // name: zerox_tick()
1602 // desc: ...
1603 //-----------------------------------------------------------------------------
1604 CK_DLL_TICK( zerox_tick )
1606 SAMPLE * d = (SAMPLE *)OBJ_MEMBER_UINT(SELF, zerox_offset_data);
1607 *out = __SGN(in) != __SGN(*d);
1608 *out *= __SGN(in);
1609 *d = in;
1611 return TRUE;
1618 struct delayp_data
1621 SAMPLE * buffer;
1622 t_CKINT bufsize;
1624 t_CKTIME now;
1626 double readpos; //readpos ( moves at constant speed, sample per sample
1627 double writepos; // relative to read position
1629 t_CKTIME offset; // distance between read and write
1631 t_CKDUR offset_start;
1632 t_CKDUR offset_target;
1634 t_CKTIME move_end_time; //target time
1635 t_CKDUR move_duration; //time we started shift
1637 SAMPLE last_sample;
1638 t_CKDUR last_offset;
1640 #ifdef _DEBUG
1641 int lasti;
1642 #endif
1644 double acoeff[2];
1645 double bcoeff[2];
1646 SAMPLE outputs[3];
1647 SAMPLE inputs[3];
1649 delayp_data()
1651 bufsize = 2 * g_srate;
1652 buffer = ( SAMPLE * ) realloc ( NULL, sizeof ( SAMPLE ) * bufsize );
1653 t_CKINT i;
1655 for ( i = 0 ; i < bufsize ; i++ ) buffer[i] = 0;
1656 for ( i = 0 ; i < 3 ; i++ ) { acoeff[i] = 0; bcoeff[i] = 0; }
1658 acoeff[0] = 1.0;
1659 acoeff[1] = -.99;
1660 bcoeff[0] = 1.0;
1661 bcoeff[1] = -1.0;
1663 readpos = 0.0;
1665 now = 0.0;
1667 offset = 0.0;
1668 last_offset = 0.0;
1669 offset_start = 0.0;
1670 offset_target = 0.0;
1672 move_duration = 1.0;
1673 move_end_time = 0.0;
1675 #ifdef _DEBUG
1676 lasti = -1;
1677 #endif
1678 last_sample = 0;
1681 ~delayp_data()
1683 SAFE_DELETE_ARRAY( buffer );
1687 CK_DLL_CTOR( delayp_ctor )
1689 OBJ_MEMBER_UINT(SELF, delayp_offset_data) = (t_CKUINT)new delayp_data;
1692 CK_DLL_DTOR( delayp_dtor )
1694 delayp_data * d = (delayp_data *)OBJ_MEMBER_UINT(SELF, delayp_offset_data);
1695 SAFE_DELETE(d);
1696 OBJ_MEMBER_UINT(SELF, delayp_offset_data) = 0;
1699 CK_DLL_PMSG( delayp_pmsg )
1701 return TRUE;
1704 CK_DLL_TICK( delayp_tick )
1706 delayp_data * d = (delayp_data *)OBJ_MEMBER_UINT(SELF, delayp_offset_data);
1707 if ( !d->buffer ) return FALSE;
1709 // area
1710 d->now = ((Chuck_UGen*)SELF)->shred->vm_ref->shreduler()->now_system;
1712 //calculate new write-offset position ( we interpolate if we've been assigned a new write-offset )
1713 if ( d->now >= d->move_end_time || d->move_duration == 0 ) d->offset = d->offset_target;
1714 else {
1715 double dt = 1.0 + ( d->now - d->move_end_time ) / ( d->move_duration );
1716 d->offset = d->offset_start + dt * ( d->offset_target - d->offset_start );
1717 // fprintf (stderr, "dt %f, off %f , start %f target %f\n", dt, d->writeoff, d->writeoff_start, d->writeoff_target );
1720 //find locations in buffer...
1721 double write = (d->readpos ) + d->offset;
1722 double last_write = (d->readpos - 1.0) + d->last_offset ;
1724 //linear interpolation. will introduce some lowpass/aliasing.
1725 double write_delta = write - last_write;
1726 double sample_delta = in - d->last_sample;
1728 double duck_constant = 0.69;
1731 double gee = fabs(write_delta) - 1.0;
1733 if ( gee < 24.0 ) {
1734 double head_contact = ( gee > 0 ) ? exp ( - duck_constant * gee ) : 1.0;
1735 t_CKINT i, smin, smax, sampi;
1736 SAMPLE sampf = 0;
1737 if ( write_delta >= 0 ) { //forward.
1738 smin = (t_CKINT) floor ( last_write );
1739 smax = (t_CKINT) floor ( write );
1740 for ( i = smin+1 ; i <= smax ; i++ ) {
1741 sampf = d->last_sample + sample_delta * ( double(i) - last_write ) / write_delta;
1742 sampi = ( i + d->bufsize * 2 ) % d->bufsize;
1743 #ifdef _DEBUG
1744 if ( d->lasti == sampi ) {
1745 fprintf( stderr, "[chuck](via Curve): over!\n");
1747 d->lasti = sampi;
1748 #endif
1749 d->buffer[sampi] += sampf * head_contact ;
1752 else { //moving in reverse
1753 smin = (t_CKINT) floor ( write );
1754 smax = (t_CKINT) floor ( last_write );
1755 for ( i = smin+1 ; i <= smax ; i++ ) {
1756 sampf = d->last_sample + sample_delta * ( double(i) - last_write ) / write_delta;
1757 sampi = ( i + d->bufsize * 2 ) % d->bufsize;
1758 #ifdef _DEBUG
1759 if ( d->lasti == sampi ) {
1760 fprintf(stderr, "[chuck](via Curve): over!\n");
1762 d->lasti = sampi;
1763 #endif
1764 d->buffer[sampi] += sampf * head_contact;
1769 d->last_offset = d->offset;
1770 d->last_sample = in;
1773 //output should go through a dc blocking filter, for cases where
1774 //we are zipping around in the buffer leaving a fairly constant
1775 //trail of samples
1777 //output last sample
1779 t_CKINT rpos = (t_CKINT) fmod( d->readpos, d->bufsize ) ;
1781 // *out = d->buffer[rpos];
1784 // did i try to write a dc blocking filter?
1785 d->outputs[0] = 0.0;
1786 d->inputs [0] = d->buffer[rpos];
1788 d->outputs[0] += d->bcoeff[1] * d->inputs[1];
1789 d->inputs [1] = d->inputs[0];
1791 d->outputs[0] += d->bcoeff[0] * d->inputs[0];
1793 d->outputs[0] += -d->acoeff[1] * d->outputs[1];
1794 d->outputs[1] = d->outputs[0];
1796 //clear at readpos ( write doesn't !)
1797 *out = d->outputs[0];
1800 *out = d->buffer[rpos];
1802 d->buffer[rpos] = 0; //clear once it's been read
1803 d->readpos = fmod ( d->readpos + 1.0 , double( d->bufsize ) );
1805 return TRUE;
1809 CK_DLL_CTRL( delayp_ctrl_delay )
1811 delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data);
1812 t_CKDUR target = GET_CK_DUR(ARGS); // rate
1813 // area
1815 if ( target != d->offset_target ) {
1816 if ( target > d->bufsize ) {
1817 fprintf( stderr, "[chuck](via delayp): delay time %f over max! set max first!\n", target);
1818 return;
1820 d->offset_target = target;
1821 d->offset_start = d->last_offset;
1823 t_CKTIME snow = ((Chuck_UGen*)SELF)->shred->now;
1824 d->move_end_time = snow + d->move_duration;
1826 RETURN->v_dur = d->last_offset; // TODO:
1829 CK_DLL_CGET( delayp_cget_delay )
1831 delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data);
1832 //SET_NEXT_DUR( out, d->writeoff_last );
1833 RETURN->v_dur = d->last_offset; // TODO:
1836 CK_DLL_CTRL( delayp_ctrl_window )
1838 delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data);
1839 t_CKDUR window = GET_CK_DUR(ARGS); // rate
1840 if ( window >= 0 ) {
1841 d->move_duration = window;
1842 //fprintf ( stderr, "set window time %f , %f , %d \n", d->writeoff_window_time, d->writeoff, d->bufsize );
1844 RETURN->v_dur = d->move_duration; // TODO:
1847 CK_DLL_CGET( delayp_cget_window )
1849 delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data);
1850 RETURN->v_dur = d->move_duration; // TODO:
1854 CK_DLL_CTRL( delayp_ctrl_max )
1856 delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data);
1857 t_CKDUR nmax = GET_CK_DUR(ARGS); // rate
1858 if ( d->bufsize != (t_CKINT)nmax && nmax > 1.0 ) {
1859 d->bufsize = (t_CKINT)(nmax+.5);
1860 d->buffer = ( SAMPLE * ) realloc ( d->buffer, sizeof ( SAMPLE ) * d->bufsize );
1861 for ( t_CKINT i = 0; i < d->bufsize; i++ ) d->buffer[i] = 0;
1863 RETURN->v_dur = d->bufsize; // TODO??
1866 CK_DLL_CGET( delayp_cget_max )
1868 delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data);
1869 //SET_NEXT_DUR( out, (t_CKDUR) d->bufsize );
1870 RETURN->v_dur = d->bufsize;
1874 #ifndef __DISABLE_SNDBUF__
1876 //-----------------------------------------------------------------------------
1877 // name: sndbuf
1878 // desc: ...
1879 //-----------------------------------------------------------------------------
1880 enum { SNDBUF_DROP = 0, SNDBUF_INTERP, SNDBUF_SINC};
1883 #define WIDTH 16 /* this controls the number of neighboring samples
1884 which are used to interpolate the new samples. The
1885 processing time is linearly related to this width */
1886 #define DELAY_SIZE 140
1888 #define USE_TABLE TRUE /* this controls whether a linearly interpolated lookup
1889 table is used for sinc function calculation, or the
1890 sinc is calculated by floating point trig function calls. */
1892 #define USE_INTERP TRUE /* this controls whether the table is linear
1893 interpolated or not. If you re not using the
1894 table, this has no effect */
1896 #define SAMPLES_PER_ZERO_CROSSING 32 /* this defines how finely the sinc function
1897 is sampled for storage in the table */
1899 #ifdef CK_SNDBUF_MEMORY_BUFFER
1900 //------------------------------------------------------------------------------
1901 // name: MultiBuffer
1902 // desc: presents multiple buffers in memory as a single sequential logical
1903 // buffer, for constant time reallocing. tries to be as discreet as possible,
1904 // so you can basically use it like a pointer. optimized for iterative access,
1905 // as random access has T = O(bufsize)
1906 //------------------------------------------------------------------------------
1907 template< class _type >
1908 class MultiBuffer
1911 public:
1912 MultiBuffer()
1914 m_size = 0;
1917 ~MultiBuffer()
1919 deallocate();
1922 size_t size()
1924 return m_size;
1927 void resize( size_t size )
1929 assert( size > m_size ); // for now
1930 size_t new_buffer_size = size - m_size;
1932 extent new_extent;
1933 new_extent.position = new _type[new_buffer_size];
1934 new_extent.length = new_buffer_size;
1935 m_bufs.push_back( new_extent );
1936 m_size = size;
1939 void deallocate()
1941 // delete everything
1942 size_t i, len = m_bufs.size();
1943 for( i = 0; i < len; i++ )
1944 delete[] m_bufs[i].position;
1945 m_size = 0;
1948 class Pointer
1950 public:
1951 Pointer()
1953 m_mb = NULL;
1954 m_lpos = 0;
1955 m_extent = 0;
1956 m_extpos = 0;
1959 Pointer( MultiBuffer * mb )
1961 m_mb = mb;
1962 m_lpos = 0;
1963 m_extent = 0;
1964 m_extpos = 0;
1967 Pointer( const Pointer & mbp )\v
1969 m_mb = mbp.m_mb;
1970 m_lpos = mbp.m_lpos;
1971 m_extent = mbp.m_extent;
1972 m_extpos = mbp.m_extpos;
1975 Pointer & operator=( MultiBuffer & mb )
1977 m_mb = &mb;
1978 m_lpos = 0;
1979 m_extent = 0;
1980 m_extpos = 0;
1982 return *this;
1985 Pointer & operator=( const Pointer & mbp )
1987 m_mb = mbp.m_mb;
1988 m_lpos = mbp.m_lpos;
1989 m_extent = mbp.m_extent;
1990 m_extpos = mbp.m_extpos;
1992 return *this;
1995 Pointer & operator=( size_t i )
1997 reset();
1998 increment( i );
1999 return *this;
2002 _type & operator*()
2004 return m_mb->m_bufs[m_extent].position[m_extpos];
2007 Pointer operator+( size_t i ) const
2009 Pointer mbp( *this );
2010 mbp.increment( i );
2011 return mbp;
2014 Pointer operator++( int )
2016 Pointer mbp = *this;
2017 this->increment( 1 );
2018 return mbp;
2021 bool operator>=( const Pointer & mbp ) const
2023 return ( m_lpos >= mbp.m_lpos );
2026 bool operator>=( const size_t i ) const
2028 return ( m_lpos >= i );
2031 void increment( size_t i )
2033 m_lpos += i;
2034 if( m_lpos >= (m_mb->m_size) )
2036 m_extent = m_mb->m_bufs.size();
2037 m_extpos = m_lpos - m_mb->m_size;
2038 return;
2041 extent ext_current = m_mb->m_bufs[m_extent];
2042 i += m_extpos;
2043 while( i >= ext_current.length )
2045 i -= ext_current.length;
2046 m_extent++;
2047 ext_current = m_mb->m_bufs[m_extent];
2050 m_extpos = i;
2053 void reset()
2055 m_lpos = 0;
2056 m_extent = 0;
2057 m_extpos = 0;
2060 protected:
2061 MultiBuffer * m_mb;
2063 size_t m_lpos; // position in logical buffer
2064 size_t m_extent; // current extent
2065 size_t m_extpos; // position within the extent
2068 protected:
2070 struct extent
2072 _type * position;
2073 size_t length;
2076 /* data shared by a set of MultiBuffers */
2077 vector< extent > m_bufs; // array of sequentially allocated buffers
2078 size_t m_size; // overall size of total memory represented
2080 #endif /* CK_SNDBUF_MEMORY_BUFFER */
2082 // data for each sndbuf
2083 struct sndbuf_data
2085 SAMPLE * buffer;
2086 t_CKUINT num_samples;
2087 t_CKUINT num_channels;
2088 t_CKUINT num_frames;
2089 t_CKUINT samplerate;
2090 t_CKUINT chan;
2091 t_CKUINT chunks;
2092 t_CKUINT chunks_read;
2093 t_CKUINT chunks_total;
2094 t_CKUINT chunks_size;
2095 bool * chunk_table;
2097 SAMPLE * eob;
2098 SAMPLE * curr;
2099 t_CKFLOAT sampleratio;
2100 t_CKFLOAT curf;
2101 t_CKFLOAT rate_factor;
2102 t_CKFLOAT rate;
2103 t_CKINT interp;
2104 t_CKBOOL loop;
2106 bool sinc_table_built;
2107 bool sinc_use_table;
2108 bool sinc_use_interp;
2109 t_CKINT sinc_samples_per_zero_crossing;
2110 t_CKINT sinc_width;
2111 double * sinc_table;
2113 #ifdef CK_SNDBUF_MEMORY_BUFFER
2114 MultiBuffer< SAMPLE > mb_buffer;
2115 t_CKUINT mb_max_samples;
2116 MultiBuffer< SAMPLE >::Pointer mb_record_position;
2117 MultiBuffer< SAMPLE >::Pointer mb_playback_position;
2118 #endif /* CK_SNDBUF_MEMORY_BUFFER */
2120 SNDFILE * fd;
2122 // constructor
2123 sndbuf_data()
2125 buffer = NULL;
2126 interp = SNDBUF_INTERP;
2127 num_channels = 0;
2128 num_frames = 0;
2129 num_samples = 0;
2130 chunks = 0;
2131 chunks_read = 0;
2132 chunks_total = 0;
2133 chunks_size = 0;
2134 chunk_table = NULL;
2135 samplerate = 0;
2136 sampleratio = 1.0;
2137 chan = 0;
2138 curf = 0.0;
2139 rate_factor = 1.0;
2140 rate = 1.0;
2141 eob = NULL;
2142 curr = NULL;
2144 sinc_table_built = false;
2145 sinc_use_table = USE_TABLE;
2146 sinc_use_interp = USE_INTERP;
2147 sinc_width = WIDTH;
2148 sinc_samples_per_zero_crossing = SAMPLES_PER_ZERO_CROSSING;
2149 sinc_table = NULL;
2151 #ifdef CK_SNDBUF_MEMORY_BUFFER
2152 mb_buffer = MultiBuffer< SAMPLE >();
2153 #endif /* CK_SNDBUF_MEMORY_BUFFER */
2155 loop = FALSE;
2156 fd = NULL;
2159 ~sndbuf_data()
2161 SAFE_DELETE_ARRAY( buffer );
2162 SAFE_DELETE_ARRAY( chunk_table );
2167 double sndbuf_sinc( sndbuf_data * d, double x );
2168 double sndbuf_t_sinc( sndbuf_data * d, double x );
2169 void sndbuf_make_sinc( sndbuf_data * d );
2170 void sndbuf_sinc_interpolate( sndbuf_data * d, SAMPLE * out );
2172 CK_DLL_CTOR( sndbuf_ctor )
2174 OBJ_MEMBER_UINT(SELF, sndbuf_offset_data) = (t_CKUINT)new sndbuf_data;
2177 CK_DLL_DTOR( sndbuf_dtor )
2179 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2180 SAFE_DELETE(d);
2181 OBJ_MEMBER_UINT(SELF, sndbuf_offset_data) = 0;
2184 inline t_CKUINT sndbuf_read( sndbuf_data * d, t_CKUINT offset, t_CKUINT howmuch )
2186 // check
2187 if( d->fd == NULL ) return 0;
2188 if( offset >= d->num_frames ) return 0;
2190 // log
2191 // EM_log( CK_LOG_FINE, "(sndbuf): reading %d:%d frames...", offset, howmuch );
2193 // prevent overflow
2194 if( howmuch > d->num_frames - offset )
2195 howmuch = d->num_frames - offset;
2197 t_CKUINT n;
2198 // seek
2199 sf_seek( d->fd, offset, SEEK_SET );
2200 #if defined(CK_S_DOUBLE)
2201 n = sf_readf_double( d->fd, d->buffer+offset*d->num_channels, howmuch );
2202 #else
2203 n = sf_readf_float( d->fd, d->buffer+offset*d->num_channels, howmuch );
2204 #endif
2206 d->chunks_read += n;
2208 // close
2209 if( d->chunks_read >= d->num_frames )
2211 // log
2212 EM_log( CK_LOG_INFO, "(sndbuf): all frames read, closing file..." );
2213 sf_close( d->fd );
2214 d->fd = NULL;
2217 return n;
2220 inline t_CKINT sndbuf_load( sndbuf_data * d, t_CKUINT where )
2222 // map to bin
2223 t_CKUINT bin = (t_CKUINT)(where / (t_CKFLOAT)d->chunks_size);
2224 if( bin >= d->chunks_total ) return 0;
2226 // already loaded
2227 if( d->chunk_table[bin] ) return 0;
2229 // read it
2230 t_CKINT ret = sndbuf_read( d, bin*d->chunks_size, d->chunks_size );
2232 // flag it
2233 d->chunk_table[bin] = true;
2235 // log
2236 // EM_log( CK_LOG_FINER, "chunk test: pos: %d bin: %d read:%d/%d", where, bin, d->chunks_read, d->num_frames );
2238 return ret;
2241 inline void sndbuf_setpos( sndbuf_data *d, double pos )
2243 if( !d->buffer ) return;
2245 d->curf = pos;
2247 // set curf within bounds
2248 if( d->loop )
2250 while( d->curf >= d->num_frames ) d->curf -= d->num_frames;
2251 while( d->curf < 0 ) d->curf += d->num_frames;
2253 else
2255 if( d->curf < 0 ) d->curf = 0;
2256 else if( d->curf >= d->num_frames ) d->curf = d->num_frames;
2259 t_CKINT i = (t_CKINT)d->curf;
2260 // ensure load
2261 if( d->fd != NULL ) sndbuf_load( d, i );
2262 // sets curr to correct position ( account for channels )
2263 d->curr = d->buffer + d->chan + i * d->num_channels;
2266 inline SAMPLE sndbuf_sampleAt( sndbuf_data * d, t_CKINT pos )
2268 // boundary cases
2269 t_CKINT nf = d->num_frames;
2270 if( d->loop ) {
2271 while( pos > nf ) pos -= nf;
2272 while( pos < 0 ) pos += nf;
2274 else {
2275 if( pos > nf ) pos = nf;
2276 if( pos < 0 ) pos = 0;
2279 t_CKUINT index = d->chan + pos * d->num_channels;
2280 // ensure load
2281 if( d->fd != NULL ) sndbuf_load( d, pos );
2282 // return sample
2283 return d->buffer[index];
2286 inline double sndbuf_getpos( sndbuf_data * d )
2288 if( !d->buffer ) return 0;
2289 return floor(d->curf);
2292 CK_DLL_CTRL( sndbuf_ctrl_loop )
2294 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2295 d->loop = GET_CK_INT(ARGS);
2296 RETURN->v_int = d->loop; // TODO: Check (everything)
2299 CK_DLL_CGET( sndbuf_cget_loop )
2301 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2302 RETURN->v_int = d->loop;
2305 // PRC's sinc interpolation function.. as found
2306 // http://www.cs.princeton.edu/courses/archive/spring03/cs325/src/TimeStuf/srconvrt.c
2308 // there's probably a lot in there that could be optimized, if we care to..
2310 // #define PI 3.14159265358979323846
2311 // wow... we are sensitive..
2313 inline double sndbuf_linear_interp( double * first, double * second, double * frac );
2314 bool sinc_table_built = false;
2316 void sndbuf_sinc_interpolate( sndbuf_data *d, SAMPLE * out )
2318 signed long j;
2319 double factor = d->rate;
2320 double time_now = d->curf;
2321 double one_over_factor;
2322 // UNUSED: double int_time = 0;
2323 // UNUSED: double last_time = 0;
2324 double temp1 = 0.0;
2326 long time_i = (long)time_now;
2328 // bounds checking now in sampleAt function...
2329 if( factor < 1.0 ) {
2330 for( j = -d->sinc_width + 1; j < d->sinc_width; j++ )
2332 temp1 += sndbuf_sampleAt(d,time_i+j) * sndbuf_sinc( d, (double)j );
2334 *out = (SAMPLE)temp1;
2336 else {
2337 one_over_factor = 1.0 / factor;
2338 for( j = -d->sinc_width + 1; j < d->sinc_width; j++ ) {
2339 temp1 += sndbuf_sampleAt(d,time_i+j) * one_over_factor * sndbuf_sinc( d, one_over_factor * (double)j );
2341 *out = (SAMPLE)temp1;
2345 void sndbuf_make_sinc( sndbuf_data * d )
2347 t_CKINT i;
2348 // fprintf(stderr, "building sinc table\n" );
2349 double temp, win_freq, win;
2350 win_freq = ONE_PI / d->sinc_width / d->sinc_samples_per_zero_crossing;
2351 t_CKINT tabsize = d->sinc_width * d->sinc_samples_per_zero_crossing;
2353 d->sinc_table = (double *) realloc( d->sinc_table, tabsize * sizeof(double) );
2354 d->sinc_table[0] = 1.0;
2355 for( i = 1; i < tabsize; i++ ) {
2356 temp = (double) i * ONE_PI / d->sinc_samples_per_zero_crossing;
2357 d->sinc_table[i] = (float)(sin(temp) / temp);
2358 win = 0.5 + 0.5 * cos(win_freq * i);
2359 d->sinc_table[i] *= (float)win;
2361 d->sinc_table_built = true;
2364 inline double sndbuf_linear_interp( double first_number, double second_number, double fraction )
2366 return (first_number + ((second_number - first_number) * fraction));
2369 double sndbuf_t_sinc( sndbuf_data * d, double x )
2371 t_CKINT low;
2372 double temp,delta;
2373 if( !d->sinc_table_built ) sndbuf_make_sinc(d);
2374 if( fabs(x) >= d->sinc_width-1 )
2375 return 0.0;
2376 else {
2377 temp = fabs(x) * (double) d->sinc_samples_per_zero_crossing;
2378 low = (t_CKINT)temp; /* these are interpolation steps */
2379 if( d->sinc_use_interp ) {
2380 delta = temp - low; /* and can be ommited if desired */
2381 return sndbuf_linear_interp( d->sinc_table[low], d->sinc_table[low + 1], delta );
2383 else return d->sinc_table[low];
2387 double sndbuf_sinc( sndbuf_data * d, double x )
2389 double temp;
2391 if( d->sinc_use_table ) return sndbuf_t_sinc(d,x);
2392 else {
2393 if( x == 0.0 ) return 1.0;
2394 else {
2395 temp = ONE_PI * x;
2396 return sin(temp) / (temp);
2401 CK_DLL_TICK( sndbuf_tick )
2403 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2405 #ifdef CK_SNDBUF_MEMORY_BUFFER
2406 // spencer's memory buffer stuff
2407 if( d->fd == 0 )
2408 // no file open - memory buffer mode
2410 Chuck_UGen * ugen = (Chuck_UGen *)SELF;
2411 if( ugen->m_num_src )
2412 // recording mode
2414 if( d->mb_buffer.size() == 0 )
2416 d->mb_buffer.resize( 44100 * 4 ); // default size: 4 seconds
2417 d->mb_record_position = d->mb_buffer;
2418 d->mb_playback_position = d->mb_buffer;
2421 if( d->mb_record_position >= d->mb_buffer.size() )
2422 d->mb_buffer.resize( d->mb_buffer.size() * 2 );
2424 *(d->mb_record_position++) = in;
2427 if( d->mb_buffer.size() )
2429 if( d->mb_playback_position >= d->mb_record_position )
2431 if( d->loop )
2432 d->mb_playback_position = 0;
2434 else if( ugen->m_num_src )
2436 *out = 0;
2437 return TRUE;
2440 else
2441 return FALSE;
2444 *out = *(d->mb_playback_position++);
2447 return TRUE;
2449 #endif /* CK_SNDBUF_MEMORY_BUFFER */
2450 if( !d->buffer ) return FALSE;
2452 // we're ticking once per sample ( system )
2453 // curf in samples;
2455 if( !d->loop && d->curr >= d->eob + d->num_channels ) return FALSE;
2457 // calculate frame
2458 if( d->interp == SNDBUF_DROP )
2460 *out = (SAMPLE)( (*(d->curr)) ) ;
2462 else if( d->interp == SNDBUF_INTERP )
2464 // samplewise linear interp
2465 double alpha = d->curf - floor(d->curf);
2466 *out = (SAMPLE)( (*(d->curr)) ) ;
2467 *out += (float)alpha * ( sndbuf_sampleAt(d, (long)d->curf+1 ) - *out );
2469 else if( d->interp == SNDBUF_SINC ) {
2470 // do that fancy sinc function!
2471 sndbuf_sinc_interpolate(d, out);
2474 // advance
2475 d->curf += d->rate;
2476 sndbuf_setpos(d, d->curf);
2478 return TRUE;
2482 #include "util_raw.h"
2485 CK_DLL_CTRL( sndbuf_ctrl_read )
2487 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2488 const char * filename = GET_CK_STRING(ARGS)->str.c_str();
2490 if( d->buffer )
2492 delete [] d->buffer;
2493 d->buffer = NULL;
2496 if( d->chunk_table )
2498 delete [] d->chunk_table;
2499 d->chunk_table = NULL;
2502 if( d->fd )
2504 sf_close( d->fd );
2505 d->fd = NULL;
2508 // log
2509 EM_log( CK_LOG_INFO, "(sndbuf): reading '%s'...", filename );
2511 // built in
2512 if( strstr(filename, "special:") )
2514 SAMPLE * rawdata = NULL;
2515 t_CKUINT rawsize = 0;
2516 t_CKUINT srate = 22050;
2518 // which
2519 if( strstr(filename, "special:sinewave") ) {
2520 rawsize = 1024; rawdata = NULL;
2522 else if( strstr(filename, "special:ahh") ) {
2523 rawsize = ahh_size; rawdata = ahh_data;
2525 else if( strstr(filename, "special:britestk") ) {
2526 rawsize = britestk_size; rawdata = britestk_data;
2528 else if( strstr(filename, "special:dope") ) {
2529 rawsize = dope_size; rawdata = dope_data;
2531 else if( strstr(filename, "special:eee") ) {
2532 rawsize = eee_size; rawdata = eee_data;
2534 else if( strstr(filename, "special:fwavblnk") ) {
2535 rawsize = fwavblnk_size; rawdata = fwavblnk_data;
2537 else if( strstr(filename, "special:halfwave") ) {
2538 rawsize = halfwave_size; rawdata = halfwave_data;
2540 else if( strstr(filename, "special:impuls10") ) {
2541 rawsize = impuls10_size; rawdata = impuls10_data;
2543 else if( strstr(filename, "special:impuls20") ) {
2544 rawsize = impuls20_size; rawdata = impuls20_data;
2546 else if( strstr(filename, "special:impuls40") ) {
2547 rawsize = impuls40_size; rawdata = impuls40_data;
2549 else if( strstr(filename, "special:mand1") ) {
2550 rawsize = mand1_size; rawdata = mand1_data;
2552 else if( strstr(filename, "special:mandpluk") ) {
2553 rawsize = mandpluk_size; rawdata = mandpluk_data;
2555 else if( strstr(filename, "special:marmstk1") ) {
2556 rawsize = marmstk1_size; rawdata = marmstk1_data;
2558 else if( strstr(filename, "special:ooo") ) {
2559 rawsize = ooo_size; rawdata = ooo_data;
2561 else if( strstr(filename, "special:peksblnk") ) {
2562 rawsize = peksblnk_size; rawdata = peksblnk_data;
2564 else if( strstr(filename, "special:ppksblnk") ) {
2565 rawsize = ppksblnk_size; rawdata = ppksblnk_data;
2567 else if( strstr(filename, "special:silence") ) {
2568 rawsize = silence_size; rawdata = silence_data;
2570 else if( strstr(filename, "special:sineblnk") ) {
2571 rawsize = sineblnk_size; rawdata = sineblnk_data;
2573 else if( strstr(filename, "special:sinewave") ) {
2574 rawsize = sinewave_size; rawdata = sinewave_data;
2576 else if( strstr(filename, "special:snglpeak") ) {
2577 rawsize = snglpeak_size; rawdata = snglpeak_data;
2579 else if( strstr(filename, "special:twopeaks") ) {
2580 rawsize = twopeaks_size; rawdata = twopeaks_data;
2582 else if( strstr(filename, "special:glot_ahh") ) {
2583 rawsize = glot_ahh_size; rawdata = glot_ahh_data; srate = 44100;
2585 else if( strstr(filename, "special:glot_eee") ) {
2586 rawsize = glot_eee_size; rawdata = glot_eee_data; srate = 44100;
2588 else if( strstr(filename, "special:glot_ooo") ) {
2589 rawsize = glot_ooo_size; rawdata = glot_ooo_data; srate = 44100;
2591 else if( strstr(filename, "special:glot_pop") ) {
2592 rawsize = glot_pop_size; rawdata = glot_pop_data; srate = 44100;
2595 d->num_frames = rawsize;
2596 d->num_channels = 1;
2597 d->chan = 0;
2598 d->samplerate = srate;
2599 d->num_samples = rawsize;
2601 // no chunking
2602 d->chunks_read = d->num_frames;
2604 if( rawdata ) {
2605 d->buffer = new SAMPLE[rawsize+1];
2606 for( t_CKUINT j = 0; j < rawsize; j++ ) {
2607 d->buffer[j] = (SAMPLE)rawdata[j]/(SAMPLE)SHRT_MAX;
2610 else if( strstr(filename, "special:sinewave") ) {
2611 d->buffer = new SAMPLE[rawsize+1];
2612 for( t_CKUINT j = 0; j < rawsize; j++ )
2613 d->buffer[j] = sin(2*ONE_PI*j/rawsize);
2615 else {
2616 fprintf( stderr, "[chuck](via SndBuf): cannot load '%s'\n", filename );
2617 return;
2620 d->buffer[rawsize] = d->buffer[0];
2622 else // read file
2624 // stat the file first
2625 struct stat s;
2626 if( stat( filename, &s ) )
2628 fprintf( stderr, "[chuck](via SndBuf): cannot stat file '%s'...\n", filename );
2629 return;
2632 // open it
2633 SF_INFO info;
2634 info.format = 0;
2635 const char * format = (const char *)strrchr( filename, '.');
2636 if( format && strcmp( format, ".raw" ) == 0 )
2638 fprintf( stderr, "[chuck](via SndBuf) %s :: type is '.raw'...\n assuming 16 bit signed mono (PCM)\n", filename );
2639 info.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16 | SF_ENDIAN_CPU ;
2640 info.channels = 1;
2641 info.samplerate = 44100;
2644 // open the handle
2645 d->fd = sf_open( filename, SFM_READ, &info );
2646 t_CKINT er = sf_error( d->fd );
2647 if( er )
2649 fprintf( stderr, "[chuck](via SndBuf): sndfile error '%i' opening '%s'...\n", er, filename );
2650 fprintf( stderr, "[chuck](via SndBuf): (reason: %s)\n", sf_strerror( d->fd ) );
2651 if( d->fd ) sf_close( d->fd );
2652 // escape
2653 return;
2656 // allocate
2657 t_CKINT size = info.channels * info.frames;
2658 d->buffer = new SAMPLE[size+info.channels];
2659 memset( d->buffer, 0, (size+info.channels)*sizeof(SAMPLE) );
2660 d->chan = 0;
2661 d->num_frames = info.frames;
2662 d->num_channels = info.channels;
2663 d->samplerate = info.samplerate;
2664 d->num_samples = size;
2666 // log
2667 EM_pushlog();
2668 EM_log( CK_LOG_INFO, "channels: %d", d->num_channels );
2669 EM_log( CK_LOG_INFO, "frames: %d", d->num_frames );
2670 EM_log( CK_LOG_INFO, "srate: %d", d->samplerate );
2671 EM_log( CK_LOG_INFO, "chunks: %d", d->chunks );
2672 EM_poplog();
2674 // read
2675 sf_seek( d->fd, 0, SEEK_SET );
2676 d->chunks_read = 0;
2678 // no chunk
2679 if( !d->chunks )
2681 // read all
2682 t_CKUINT f = sndbuf_read( d, 0, d->num_frames );
2683 // check
2684 if( f != (t_CKUINT)d->num_frames )
2686 fprintf( stderr, "[chuck](via SndBuf): read %d rather than %d frames from %s\n",
2687 f, size, filename );
2688 sf_close( d->fd ); d->fd = NULL;
2689 return;
2692 assert( d->fd == NULL );
2694 else
2696 // reset
2697 d->chunks_size = d->chunks;
2698 d->chunks_total = d->num_frames / d->chunks;
2699 d->chunks_total += d->num_frames % d->chunks ? 1 : 0;
2700 d->chunks_read = 0;
2701 d->chunk_table = new bool[d->chunks_total];
2702 memset( d->chunk_table, 0, d->chunks_total * sizeof(bool) );
2704 // read chunk
2705 // sndbuf_load( d, 0 );
2709 // d->interp = SNDBUF_INTERP;
2710 d->sampleratio = (double)d->samplerate / (double)g_srate;
2711 // set the rate
2712 d->rate = d->sampleratio * d->rate_factor;
2713 d->curr = d->buffer;
2714 d->curf = 0;
2715 d->eob = d->buffer + d->num_samples;
2718 CK_DLL_CTRL( sndbuf_ctrl_write )
2720 #ifdef SPENCER_SNDBUF_WRITE
2721 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2722 const char * filename = GET_CK_STRING(ARGS)->str.c_str();
2724 if( d->buffer )
2726 delete [] d->buffer;
2727 d->buffer = NULL;
2730 struct stat s;
2731 if( stat( filename, &s ) )
2733 fprintf( stderr, "[chuck](via SndBuf): cannot stat file '%s'...\n", filename );
2734 return;
2737 d->curr = d->buffer;
2738 d->eob = d->buffer + d->num_samples;
2739 #endif
2743 CK_DLL_CTRL( sndbuf_ctrl_rate )
2745 sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2746 t_CKFLOAT rate = GET_CK_FLOAT(ARGS); // rate
2747 d->rate = rate * d->sampleratio;
2748 d->rate_factor = rate;
2749 RETURN->v_float = d->rate_factor; // TODO: (or not TODO:)
2752 CK_DLL_CGET( sndbuf_cget_rate )
2754 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2755 RETURN->v_float = d->rate_factor;
2759 CK_DLL_CTRL( sndbuf_ctrl_freq )
2761 sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2762 t_CKFLOAT freq = GET_CK_FLOAT(ARGS); //hz
2764 d->rate = ( freq * (double) d->num_frames / (double) g_srate );
2765 d->rate_factor = d->rate / d->sampleratio;
2766 RETURN->v_float = d->rate * (t_CKFLOAT) g_srate / ( (t_CKFLOAT) d->num_frames ); // TODO: really?
2769 CK_DLL_CGET( sndbuf_cget_freq )
2771 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2772 RETURN->v_float = d->rate * (t_CKFLOAT) g_srate / ( (t_CKFLOAT) d->num_frames );
2775 CK_DLL_CTRL( sndbuf_ctrl_phase )
2777 sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2778 t_CKFLOAT phase = GET_CK_FLOAT(ARGS);
2779 sndbuf_setpos(d, phase * (double)d->num_frames);
2780 RETURN->v_float = (t_CKFLOAT) d->curf / (t_CKFLOAT)d->num_frames; // TODO:
2783 CK_DLL_CGET( sndbuf_cget_phase )
2785 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2786 //SET_NEXT_FLOAT( out, (t_CKFLOAT) d->curf / (t_CKFLOAT)d->num_frames );
2787 RETURN->v_float = (t_CKFLOAT) d->curf / (t_CKFLOAT)d->num_frames;
2790 CK_DLL_CTRL( sndbuf_ctrl_channel )
2792 sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2793 unsigned long chan = (unsigned long)GET_CK_INT(ARGS);
2794 if ( chan >= 0 && chan < d->num_channels ) {
2795 d->chan = chan;
2797 RETURN->v_int = (t_CKINT)d->chan;
2800 CK_DLL_CGET( sndbuf_cget_channel )
2802 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2803 //SET_NEXT_INT( out, d->chan );
2804 RETURN->v_int = (t_CKINT)d->chan;
2807 CK_DLL_CTRL( sndbuf_ctrl_pos )
2809 sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2810 t_CKINT pos = GET_CK_INT(ARGS);
2811 #ifdef CK_SNDBUF_MEMORY_BUFFER
2812 if( pos >= 0 && pos < d->mb_max_samples )
2813 d->mb_playback_position = pos;
2814 #endif /* CK_SNDBUF_MEMORY_BUFFER */
2815 sndbuf_setpos(d, pos);
2816 RETURN->v_int = (t_CKINT)sndbuf_getpos(d); // TODO TODO TODOOO
2819 CK_DLL_CGET( sndbuf_cget_pos )
2821 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2822 RETURN->v_int = (t_CKINT)sndbuf_getpos(d);
2825 CK_DLL_CTRL( sndbuf_ctrl_interp )
2827 sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2828 t_CKINT interp = GET_CK_INT(ARGS);
2829 d->interp = interp;
2830 RETURN->v_int = d->interp;
2833 CK_DLL_CGET( sndbuf_cget_interp )
2835 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2836 RETURN->v_int = d->interp;
2839 CK_DLL_CTRL( sndbuf_ctrl_chunks )
2841 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2842 t_CKINT frames = GET_NEXT_INT(ARGS);
2843 d->chunks = frames >= 0 ? frames : 0;
2844 RETURN->v_int = d->chunks;
2847 CK_DLL_CGET( sndbuf_cget_chunks )
2849 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2850 RETURN->v_int = d->chunks;
2853 CK_DLL_CTRL( sndbuf_ctrl_phase_offset )
2855 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2856 t_CKFLOAT phase_offset = GET_CK_FLOAT(ARGS);
2857 sndbuf_setpos(d, d->curf + phase_offset * (t_CKFLOAT)d->num_frames );
2860 CK_DLL_CGET( sndbuf_cget_samples )
2862 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2863 //SET_NEXT_INT( out, d->num_frames );
2864 RETURN->v_int = d->num_frames;
2867 CK_DLL_CGET( sndbuf_cget_length )
2869 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2870 //SET_NEXT_DUR( out, (t_CKDUR)d->num_frames );
2871 RETURN->v_dur = (t_CKDUR)d->num_frames / d->sampleratio;
2874 CK_DLL_CGET( sndbuf_cget_channels )
2876 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2877 //SET_NEXT_INT( out, d->num_channels );
2878 RETURN->v_int = d->num_channels;
2881 CK_DLL_CGET( sndbuf_cget_valueAt )
2883 sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data);
2884 t_CKINT i = GET_CK_INT(ARGS);
2885 if( d->fd ) sndbuf_load( d, i );
2886 RETURN->v_float = ( i > d->num_frames || i < 0 ) ? 0 : d->buffer[i];
2889 #endif // __DISABLE_SNDBUF__
2892 class Dyno_Data
2894 private:
2895 const static t_CKDUR ms;
2897 public:
2898 t_CKFLOAT slopeAbove;
2899 t_CKFLOAT slopeBelow;
2900 t_CKFLOAT thresh;
2901 t_CKFLOAT rt;
2902 t_CKFLOAT at;
2903 t_CKFLOAT xd; //sidechain
2904 int externalSideInput; // use input signal or a ctrl signal for env
2905 t_CKFLOAT sideInput; // the ctrl signal for the envelope
2907 int count; //diagnostic
2909 Dyno_Data() {
2910 xd = 0.0;
2911 count = 0;
2912 sideInput = 0;
2913 limit();
2915 ~Dyno_Data() {}
2917 void limit();
2918 void compress();
2919 void gate();
2920 void expand();
2921 void duck();
2923 //set the time constants for rt, at, and tav
2924 static t_CKFLOAT computeTimeConst(t_CKDUR t) {
2925 //AT = 1 - e ^ (-2.2T/t<AT)
2926 //as per chuck_type.cpp, T(sampling period) = 1.0
2927 return 1.0 - exp( -2.2 / t );
2930 static t_CKDUR timeConstToDur(t_CKFLOAT x) {
2931 return -2.2 / log(1.0 - x);
2934 //setters for timing constants
2935 void setAttackTime(t_CKDUR t);
2936 void setReleaseTime(t_CKDUR t);
2938 //other setters
2939 void setRatio(t_CKFLOAT newRatio);
2940 t_CKFLOAT getRatio();
2943 const t_CKDUR Dyno_Data::ms = g_vm->srate() * 1.0 / 1000.0;
2945 //setters for the timing constants
2946 void Dyno_Data::setAttackTime(t_CKDUR t) {
2947 at = computeTimeConst(t);
2950 void Dyno_Data::setReleaseTime(t_CKDUR t) {
2951 rt = computeTimeConst(t);
2954 void Dyno_Data::setRatio(t_CKFLOAT newRatio) {
2955 this->slopeAbove = 1.0 / newRatio;
2956 this->slopeBelow = 1.0;
2959 t_CKFLOAT Dyno_Data::getRatio()
2961 return this->slopeBelow / this->slopeAbove;
2964 //TODO: come up with better/good presets?
2966 //presets for the dynomics processor
2967 void Dyno_Data::limit() {
2968 slopeAbove = 0.1; // 10:1 compression above thresh
2969 slopeBelow = 1.0; // no compression below
2970 thresh = 0.5;
2971 at = computeTimeConst( 5.0 * ms );
2972 rt = computeTimeConst( 300.0 * ms );
2973 externalSideInput = 0;
2976 void Dyno_Data::compress() {
2977 slopeAbove = 0.5; // 2:1 compression
2978 slopeBelow = 1.0;
2979 thresh = 0.5;
2980 at = computeTimeConst( 5.0 * ms );
2981 rt = computeTimeConst( 500.0 * ms );
2982 externalSideInput = 0;
2985 void Dyno_Data::gate() {
2986 slopeAbove = 1.0;
2987 slopeBelow = 100000000; // infinity (more or less)
2988 thresh = 0.1;
2989 at = computeTimeConst( 11.0 * ms );
2990 rt = computeTimeConst( 100.0 * ms );
2991 externalSideInput = 0;
2994 void Dyno_Data::expand() {
2995 slopeAbove = 2.0; // 1:2 expansion
2996 slopeBelow = 1.0;
2997 thresh = 0.5;
2998 at = computeTimeConst( 20.0 * ms );
2999 rt = computeTimeConst( 400.0 * ms );
3000 externalSideInput = 0;
3003 void Dyno_Data::duck() {
3004 slopeAbove = 0.5; // when sideInput rises above thresh, gain starts going
3005 slopeBelow = 1.0; // down. it'll drop more as sideInput gets louder.
3006 thresh = 0.1;
3007 at = computeTimeConst( 10.0 * ms );
3008 rt = computeTimeConst( 1000.0 * ms );
3009 externalSideInput = 1;
3013 //controls for the preset modes
3014 CK_DLL_CTRL( dyno_ctrl_limit ) {
3015 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3016 d->limit();
3019 CK_DLL_CTRL( dyno_ctrl_compress ) {
3020 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3021 d->compress();
3024 CK_DLL_CTRL( dyno_ctrl_gate ) {
3025 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3026 d->gate();
3029 CK_DLL_CTRL( dyno_ctrl_expand ) {
3030 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3031 d->expand();
3034 CK_DLL_CTRL( dyno_ctrl_duck ) {
3035 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3036 d->duck();
3039 //additional controls: thresh
3040 CK_DLL_CTRL( dyno_ctrl_thresh ) {
3041 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3042 d->thresh = GET_CK_FLOAT(ARGS);
3043 RETURN->v_float = (t_CKFLOAT)d->thresh;
3046 CK_DLL_CGET( dyno_cget_thresh ) {
3047 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3048 RETURN->v_float = (t_CKFLOAT)d->thresh;
3051 //additional controls: attackTime
3052 CK_DLL_CTRL( dyno_ctrl_attackTime ) {
3053 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3054 d->setAttackTime( GET_CK_FLOAT(ARGS) );
3055 RETURN->v_dur = d->timeConstToDur(d->at);
3058 CK_DLL_CGET( dyno_cget_attackTime ) {
3059 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3060 RETURN->v_dur = d->timeConstToDur(d->at);
3063 //additional controls: releaseTime
3064 CK_DLL_CTRL( dyno_ctrl_releaseTime ) {
3065 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3066 d->setReleaseTime( GET_CK_FLOAT(ARGS) );
3067 RETURN->v_dur = d->timeConstToDur(d->rt);
3070 CK_DLL_CGET( dyno_cget_releaseTime ) {
3071 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3072 RETURN->v_dur = d->timeConstToDur(d->rt);
3075 //additional controls: ratio
3076 CK_DLL_CTRL( dyno_ctrl_ratio ) {
3077 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3078 d->setRatio( GET_CK_FLOAT(ARGS) );
3079 RETURN->v_float = d->getRatio();
3082 CK_DLL_CGET( dyno_cget_ratio ) {
3083 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3084 RETURN->v_float = d->getRatio();
3087 //additional controls: slopeBelow
3088 CK_DLL_CTRL( dyno_ctrl_slopeBelow ) {
3089 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3090 d->slopeBelow = GET_CK_FLOAT(ARGS);
3092 RETURN->v_float = d->slopeBelow;
3095 CK_DLL_CGET( dyno_cget_slopeBelow ) {
3096 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3097 RETURN->v_float = d->slopeBelow;
3100 //additional controls: slopeAbove
3101 CK_DLL_CTRL( dyno_ctrl_slopeAbove ) {
3102 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3103 d->slopeAbove = GET_CK_FLOAT(ARGS);
3105 RETURN->v_float = d->slopeAbove;
3108 CK_DLL_CGET( dyno_cget_slopeAbove ) {
3109 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3110 RETURN->v_float = d->slopeAbove;
3113 //additional controls: sideInput
3114 CK_DLL_CTRL( dyno_ctrl_sideInput ) {
3115 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3116 d->sideInput = GET_CK_FLOAT(ARGS);
3118 RETURN->v_float = d->sideInput;
3121 CK_DLL_CGET( dyno_cget_sideInput ) {
3122 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3123 RETURN->v_float = d->sideInput;
3126 //additional controls: externalSideInput
3127 CK_DLL_CTRL( dyno_ctrl_externalSideInput ) {
3128 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3129 d->externalSideInput = GET_CK_INT(ARGS);
3131 RETURN->v_int = d->externalSideInput;
3134 CK_DLL_CGET( dyno_cget_externalSideInput ) {
3135 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3136 RETURN->v_int = d->externalSideInput;
3139 //constructor
3140 CK_DLL_CTOR( dyno_ctor )
3142 OBJ_MEMBER_UINT(SELF, dyno_offset_data) = (t_CKUINT)new Dyno_Data;
3145 CK_DLL_DTOR( dyno_dtor )
3147 delete (Dyno_Data *)OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3148 OBJ_MEMBER_UINT(SELF, dyno_offset_data) = 0;
3151 // recomputes envelope, determines how the current amp envelope compares with
3152 // thresh, applies the appropriate new slope depending on how far above/below
3153 // the threshold the current envelope is.
3154 CK_DLL_TICK( dyno_tick )
3156 Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data);
3158 // only change sideInput if we're not using an external ctrl signal.
3159 // otherwise we'll just use whatever the user sent us last as the ctrl signal
3160 if(!d->externalSideInput)
3161 d->sideInput = in >= 0 ? in : -in;
3163 // 'a' is signal left after subtracting xd (to recompute sideChain envelope)
3164 double a = d->sideInput - d->xd;
3165 // a is only needed if positive to pull the envelope up, not to bring it down
3166 if ( a < 0 ) a=0;
3167 // the attack/release (peak) exponential filter to guess envelope
3168 d->xd = d->xd * (1 - d->rt) + d->at * a;
3170 // if you were to use the rms filter,
3171 // it would probably look, a sumpthin' like this
3172 // d->xd = TAV * in*in + (1+TAV) * d->xd
3174 // decide which slope to use, depending on whether we're below/above thresh
3175 double slope = d->xd > d->thresh ? d->slopeAbove : d->slopeBelow;
3176 // the gain function - apply the slope chosen above
3177 double f = slope == 1.0 ? 1.0 : pow( d->xd / d->thresh, slope - 1.0 );
3179 // apply the gain found above to input sample
3180 *out = f * in;
3182 return TRUE;
3188 #define LiSa_MAXVOICES 200
3189 #define LiSa_MAXBUFSIZE 44100000
3190 //-----------------------------------------------------------------------------
3191 // name: LiSaMulti_data
3192 // desc: ...
3193 //-----------------------------------------------------------------------------
3194 struct LiSaMulti_data
3196 SAMPLE * mdata;
3197 t_CKINT mdata_len;
3198 t_CKINT maxvoices;
3199 t_CKINT loop_start[LiSa_MAXVOICES], loop_end[LiSa_MAXVOICES], loop_end_rec;
3200 t_CKINT rindex; // record and play indices
3201 t_CKBOOL record, looprec, loopplay[LiSa_MAXVOICES], reset, append, play[LiSa_MAXVOICES], bi[LiSa_MAXVOICES];
3202 t_CKFLOAT coeff; // feedback coeff
3203 t_CKFLOAT voiceGain[LiSa_MAXVOICES]; //gain control for each voice
3204 t_CKDOUBLE p_inc[LiSa_MAXVOICES], pindex[LiSa_MAXVOICES]; // playback increment
3206 // ramp stuff
3207 t_CKDOUBLE rampup_len[LiSa_MAXVOICES], rampdown_len[LiSa_MAXVOICES], rec_ramplen, rec_ramplen_inv;
3208 t_CKDOUBLE rampup_len_inv[LiSa_MAXVOICES], rampdown_len_inv[LiSa_MAXVOICES];
3209 t_CKDOUBLE rampctr[LiSa_MAXVOICES];
3210 t_CKBOOL rampup[LiSa_MAXVOICES], rampdown[LiSa_MAXVOICES];
3212 t_CKINT track;
3214 // allocate memory, length in samples
3215 inline int buffer_alloc(t_CKINT length)
3217 mdata = (SAMPLE *)malloc((length + 1) * sizeof(SAMPLE)); //extra sample for safety....
3218 if(!mdata) {
3219 fprintf(stderr, "LiSaBasic: unable to allocate memory!\n");
3220 return false;
3223 mdata_len = length;
3224 maxvoices = 10; // default; user can set
3225 rec_ramplen = 0.;
3226 rec_ramplen_inv = 1.;
3228 track = 0;
3230 for (t_CKINT i=0; i < LiSa_MAXVOICES; i++) {
3231 loop_start[i] = 0;
3232 loop_end[i] = length - 1;
3233 loop_end_rec = length;
3235 pindex[i] = rindex = 0;
3236 play[i] = record = bi[i] = false;
3237 looprec = loopplay[i] = true;
3238 coeff = 0.;
3239 p_inc[i] = 1.;
3240 voiceGain[i] = 1.;
3242 // ramp stuff
3243 rampup[i] = rampdown[i] = false;
3244 rampup_len[i] = rampdown_len[i] = 0.;
3245 rampup_len_inv[i] = rampdown_len_inv[i] = 1.;
3246 rampctr[i] = 0.;
3249 return true;
3252 // dump a sample into the buffer; retain existing sample, scaled by "coeff"
3253 inline void recordSamp(SAMPLE insample)
3255 SAMPLE tempsample;
3257 if(record) {
3258 if(looprec) {
3259 if(rindex >= loop_end_rec) rindex = 0;
3260 tempsample = coeff * mdata[rindex] + insample;
3261 //mdata[rindex] = coeff * mdata[rindex] + insample;
3262 //rindex++;
3263 } else {
3264 if (rindex < loop_end_rec) {
3265 //mdata[rindex] = coeff * mdata[rindex] + insample;
3266 tempsample = coeff * mdata[rindex] + insample;
3267 //rindex++;
3268 } else {
3269 record = 0;
3270 return;
3274 // ramp stuff here
3275 if(rindex < rec_ramplen) {
3276 tempsample *= (rindex * rec_ramplen_inv);
3277 //fprintf(stderr, "ramping up %f\n", rindex * rec_ramplen_inv);
3278 } else if(rindex > (loop_end_rec - rec_ramplen)) {
3279 tempsample *= (loop_end_rec - rindex) * rec_ramplen_inv;
3280 //fprintf(stderr, "ramping down %f\n", (loop_end_rec - rindex) * rec_ramplen_inv);
3282 mdata[rindex] = tempsample;
3283 rindex++;
3287 // grab a sample from the buffer, with linear interpolation (add prc's SINC interp later)
3288 // increment play index
3289 inline SAMPLE getNextSamp(t_CKINT which)
3291 // constrain
3292 if(loopplay[which]) {
3293 if(bi[which]) { // change direction if bidirectional mode
3294 if(pindex[which] >= loop_end[which] || pindex[which] < loop_start[which]) { //should be >= ?
3295 pindex[which] -= p_inc[which];
3296 p_inc[which] = -p_inc[which];
3299 if( loop_start[which] == loop_end[which] ) pindex[which] = loop_start[which]; //catch this condition to avoid infinite while loops
3300 else {
3301 while(pindex[which] >= loop_end[which]) pindex[which] = loop_start[which] + (pindex[which] - loop_end[which]); //again, >=?
3302 while(pindex[which] < loop_start[which]) pindex[which] = loop_end[which] - (loop_start[which] - pindex[which]);
3305 } else if(pindex[which] >= mdata_len || pindex[which] < 0) { //should be >=, no?
3306 play[which] = 0;
3307 //fprintf(stderr, "turning voice %d off!\n", which);
3308 return (SAMPLE) 0.;
3311 // interp
3312 t_CKINT whereTrunc = (t_CKINT) pindex[which];
3313 t_CKDOUBLE whereFrac = pindex[which] - (t_CKDOUBLE)whereTrunc;
3314 t_CKINT whereNext = whereTrunc + 1;
3316 if (loopplay[which]) {
3317 if((whereNext) == loop_end[which]) {
3318 whereNext = loop_start[which];
3320 } else {
3321 if((whereTrunc) == mdata_len) {
3322 whereTrunc = mdata_len - 1;
3323 whereNext = 0;
3327 pindex[which] += p_inc[which];
3329 t_CKDOUBLE outsample;
3330 outsample = (t_CKDOUBLE)mdata[whereTrunc] + (t_CKDOUBLE)(mdata[whereNext] - mdata[whereTrunc]) * whereFrac;
3332 // ramp stuff
3333 if(rampup[which]) {
3334 outsample *= rampctr[which]++ * rampup_len_inv[which]; //remove divide
3335 if(rampctr[which] >= rampup_len[which]) rampup[which] = false;
3337 else if(rampdown[which]) {
3338 outsample *= (rampdown_len[which] - rampctr[which]++) * rampdown_len_inv[which];
3339 if(rampctr[which] >= rampdown_len[which]) {
3340 rampdown[which] = false;
3341 play[which] = false;
3345 outsample *= voiceGain[which];
3347 return (SAMPLE)outsample;
3350 // grab a sample from the buffer, with linear interpolation (add prc's SINC interp later)
3351 // given a position within the buffer
3352 inline SAMPLE getSamp(t_CKDOUBLE where, t_CKINT which)
3354 // constrain
3355 if(where > loop_end[which]) where = loop_end[which];
3356 if(where < loop_start[which]) where = loop_start[which];
3358 // interp
3359 t_CKINT whereTrunc = (t_CKINT) where;
3360 t_CKDOUBLE whereFrac = where - (t_CKDOUBLE)whereTrunc;
3361 t_CKINT whereNext = whereTrunc + 1;
3363 if((whereNext) == loop_end[which]) whereNext = loop_start[which];
3365 t_CKDOUBLE outsample;
3366 outsample = (t_CKDOUBLE)mdata[whereTrunc] + (t_CKDOUBLE)(mdata[whereNext] - mdata[whereTrunc]) * whereFrac;
3367 outsample *= voiceGain[which];
3369 //add voiceGain ctl here; return (SAMPLE)vgain[which]*outsample;
3370 return (SAMPLE)outsample;
3373 // ramp stuff
3374 inline void ramp_up(t_CKINT voicenum, t_CKDUR uptime)
3376 // fprintf(stderr, "ramping up voice %d", voicenum);
3378 rampup[voicenum] = true;
3379 play[voicenum] = true;
3380 rampup_len[voicenum] = (t_CKDOUBLE)uptime;
3381 if(rampup_len[voicenum] > 0.) rampup_len_inv[voicenum] = 1./rampup_len[voicenum];
3382 else rampup_len[voicenum] = 1.;
3384 // check to make sure we are not mid ramping down
3385 if(rampdown[voicenum]) {
3386 rampctr[voicenum] = rampup_len[voicenum] * (1. - rampctr[voicenum]/rampdown_len[voicenum]);
3387 rampdown[voicenum] = false;
3388 } else rampctr[voicenum] = 0;
3391 inline void ramp_down(t_CKINT voicenum, t_CKDUR downtime)
3393 rampdown[voicenum] = true;
3394 rampdown_len[voicenum] = (t_CKDOUBLE)downtime;
3395 if(rampdown_len[voicenum] > 0.) rampdown_len_inv[voicenum] = 1./rampdown_len[voicenum];
3396 else rampdown_len[voicenum] = 1.;
3398 // check to make sure we are not mid ramping up
3399 if(rampup[voicenum]) {
3400 rampctr[voicenum] = rampdown_len[voicenum] * (1. - rampctr[voicenum]/rampup_len[voicenum]);
3401 rampup[voicenum] = false;
3402 } else rampctr[voicenum] = 0;
3405 inline void set_rec_ramplen(t_CKDUR newlen)
3407 rec_ramplen = (t_CKDOUBLE)newlen;
3408 if(rec_ramplen > 0.) rec_ramplen_inv = 1./rec_ramplen;
3409 else rec_ramplen_inv = 1.;
3410 //fprintf ( stderr, "rec_ramplen = %f, inv = %f \n", rec_ramplen, rec_ramplen_inv );
3413 // tick_multi: mono
3414 // may want to make multichannel version,
3415 // want to be able to do the following:
3416 // LiSa l;
3417 // l.pan(voice, panval)
3418 //for simple stereo panning of a particular voice, and...
3419 // l.channelGain(voice, channel, gain)
3420 //to set the gain for a particular voice going to a particular channel; good for >2 voices (like 6 channels!)
3421 inline SAMPLE tick_multi( SAMPLE in)
3423 if(!mdata) return (SAMPLE) 0.;
3425 recordSamp(in);
3427 SAMPLE tempsample = 0.;
3429 if(track==0) {
3430 for (t_CKINT i=0; i<maxvoices; i++) {
3431 if(play[i]) tempsample += getNextSamp(i);
3433 } else if(track==1) {
3434 if(in<0.) in = -in;
3435 for (t_CKINT i=0; i<maxvoices; i++) {
3436 if(play[i]) tempsample += getSamp((t_CKDOUBLE)in * (loop_end[i] - loop_start[i]) + loop_start[i], i);
3438 } else if(track==2 && play[0]) {
3439 if(in<0.) in = -in; //only use voice 0 when tracking with durs.
3440 tempsample = getSamp( (t_CKDOUBLE)in, 0 );
3443 return tempsample;
3446 inline void clear_buf()
3448 for (t_CKINT i = 0; i < mdata_len; i++)
3449 mdata[i] = 0.;
3452 inline t_CKINT get_free_voice()
3454 t_CKINT voicenumber = 0;
3455 while(play[voicenumber] && voicenumber < maxvoices) {
3456 voicenumber++;
3458 if(voicenumber == maxvoices) voicenumber = -1;
3459 return voicenumber;
3462 //stick sample in record buffer
3463 inline void pokeSample( SAMPLE insample, t_CKINT index ) {
3465 if ( index > mdata_len || index < 0 ) {
3466 index = 0;
3467 fprintf(stderr, "LiSa: trying to put sample out of buffer range; ignoring");
3468 } else mdata[index] = insample;
3472 //grab sample directly from record buffer, with linear interpolation
3473 inline SAMPLE grabSample ( t_CKDOUBLE where ) {
3475 if ( where > mdata_len || where < 0 ) {
3476 where = 0;
3477 fprintf(stderr, "LiSa: trying to grab sample out of buffer range; ignoring");
3478 return 0.;
3479 } else {
3481 // interp
3482 t_CKINT whereTrunc = (t_CKINT) where;
3483 t_CKDOUBLE whereFrac = where - (t_CKDOUBLE)whereTrunc;
3484 t_CKINT whereNext = whereTrunc + 1;
3486 if((whereNext) == mdata_len) whereNext = 0;
3488 t_CKDOUBLE outsample;
3489 outsample = (t_CKDOUBLE)mdata[whereTrunc] + (t_CKDOUBLE)(mdata[whereNext] - mdata[whereTrunc]) * whereFrac;
3491 //add voiceGain ctl here; return (SAMPLE)vgain[which]*outsample;
3492 return (SAMPLE)outsample;
3502 //++++++++++++++++++++++++++++++++++++++++
3505 //++++++++++++++++++++++++++++++++++++++++
3508 //++++++++++++++++++++++++++++++++++++++++
3513 //-----------------------------------------------------------------------------
3514 // name: LiSaMulti_ctor()
3515 // desc: CTOR function ...
3516 //-----------------------------------------------------------------------------
3517 CK_DLL_CTOR( LiSaMulti_ctor )
3520 LiSaMulti_data * f = new LiSaMulti_data;
3521 memset( f, 0, sizeof(LiSaMulti_data) );
3522 OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data) = (t_CKUINT)f;
3527 //-----------------------------------------------------------------------------
3528 // name: LiSaMulti_dtor()
3529 // desc: DTOR function ...
3530 //-----------------------------------------------------------------------------
3531 CK_DLL_DTOR( LiSaMulti_dtor )
3533 // get data
3534 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3535 // delete
3536 SAFE_DELETE(d);
3537 // set
3538 OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data) = 0;
3542 //-----------------------------------------------------------------------------
3543 // name: LiSaMulti_tick()
3544 // desc: TICK function ...
3545 //-----------------------------------------------------------------------------
3546 CK_DLL_TICK( LiSaMulti_tick )
3548 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3549 *out = d->tick_multi( in );
3550 return TRUE;
3554 //-----------------------------------------------------------------------------
3555 // name: LiSaMulti_size()
3556 // desc: set size of buffer allocation
3557 //-----------------------------------------------------------------------------
3558 CK_DLL_CTRL( LiSaMulti_size )
3560 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3561 t_CKDUR buflen = GET_NEXT_DUR(ARGS);
3562 if (buflen > LiSa_MAXBUFSIZE) {
3563 fprintf(stderr, "buffer size request too large, resizing\n");
3564 buflen = LiSa_MAXBUFSIZE;
3566 d->buffer_alloc((t_CKINT)buflen);
3568 RETURN->v_dur = (t_CKDUR)buflen;
3571 CK_DLL_CGET( LiSaMulti_cget_size )
3573 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3575 RETURN->v_dur = (t_CKDUR)d->mdata_len;
3579 //-----------------------------------------------------------------------------
3580 // name: LiSaMulti_start_record()
3581 // desc: CTRL function ...
3582 //-----------------------------------------------------------------------------
3583 CK_DLL_CTRL( LiSaMulti_start_record )
3585 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3586 d->record = GET_NEXT_INT(ARGS);
3588 RETURN->v_int = (t_CKINT)d->record;
3592 //-----------------------------------------------------------------------------
3593 // name: LiSaMulti_start_play()
3594 // desc: CTRL function
3595 //-----------------------------------------------------------------------------
3596 CK_DLL_CTRL( LiSaMulti_start_play )
3598 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3599 t_CKINT which = GET_NEXT_INT(ARGS);
3600 d->play[which] = GET_NEXT_INT(ARGS);
3601 //fprintf(stderr, "voice %d playing = %d\n", which, d->play[which]);
3603 //turn off ramping toggles
3604 d->rampdown[which] = false;
3605 d->rampup[which] = false;
3607 RETURN->v_int = (t_CKINT)d->play[which];
3611 //-----------------------------------------------------------------------------
3612 // name: LiSaMulti_start_play()
3613 // desc: CTRL function
3614 //-----------------------------------------------------------------------------
3615 CK_DLL_CTRL( LiSaMulti_start_play0 )
3618 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3619 d->play[0] = GET_NEXT_INT(ARGS);
3620 //fprintf(stderr, "voice %d playing = %d\n", which, d->play[which]);
3622 //turn off ramping toggles
3623 d->rampdown[0] = false;
3624 d->rampup[0] = false;
3626 RETURN->v_int = (t_CKINT)d->play[0];
3631 //-----------------------------------------------------------------------------
3632 // name: LiSaMulti_ctrl_rate()
3633 // desc: CTRL function
3634 //-----------------------------------------------------------------------------
3635 CK_DLL_CTRL( LiSaMulti_ctrl_rate )
3637 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3638 t_CKINT which = GET_NEXT_INT(ARGS);
3639 d->p_inc[which] = (t_CKDOUBLE)GET_NEXT_FLOAT(ARGS);
3640 //fprintf(stderr, "setting voice %d rate to %f\n", which, d->p_inc[which]);
3642 RETURN->v_float = d->p_inc[which];
3646 CK_DLL_CTRL( LiSaMulti_ctrl_rate0 )
3648 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3649 d->p_inc[0] = (t_CKDOUBLE)GET_NEXT_FLOAT(ARGS);
3650 //fprintf(stderr, "setting voice %d rate to %f\n", which, d->p_inc[which]);
3652 RETURN->v_float = d->p_inc[0];
3655 //-----------------------------------------------------------------------------
3656 // name: LiSaMulti_cget_rate()
3657 // desc: CTRL function
3658 //-----------------------------------------------------------------------------
3659 CK_DLL_CTRL( LiSaMulti_cget_rate )
3661 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3662 t_CKINT which = GET_NEXT_INT(ARGS);
3663 //fprintf(stderr, "setting voice %d rate to %f\n", which, d->p_inc[which]);
3665 RETURN->v_float = d->p_inc[which];
3669 CK_DLL_CTRL( LiSaMulti_cget_rate0 )
3671 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3672 //fprintf(stderr, "setting voice %d rate to %f\n", which, d->p_inc[which]);
3674 RETURN->v_float = d->p_inc[0];
3677 //-----------------------------------------------------------------------------
3678 // name: LiSaMulti_ctrl_pindex()
3679 // desc: CTRL function
3680 //-----------------------------------------------------------------------------
3681 CK_DLL_CTRL( LiSaMulti_ctrl_pindex )
3683 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3684 t_CKINT which = GET_NEXT_INT(ARGS);
3685 d->pindex[which] = (t_CKDOUBLE)GET_NEXT_DUR(ARGS);
3687 RETURN->v_dur = (t_CKDUR)d->pindex[which];
3691 CK_DLL_CTRL( LiSaMulti_ctrl_pindex0 )
3693 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3694 d->pindex[0] = (t_CKDOUBLE)GET_NEXT_DUR(ARGS);
3696 RETURN->v_dur = (t_CKDUR)d->pindex[0];
3700 //-----------------------------------------------------------------------------
3701 // name: LiSaMulti_cget_pindex()
3702 // desc: CGET function
3703 //-----------------------------------------------------------------------------
3704 CK_DLL_CGET( LiSaMulti_cget_pindex )
3706 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3707 t_CKINT which = GET_NEXT_INT(ARGS);
3709 // return
3710 RETURN->v_dur = (t_CKDUR)d->pindex[which];
3714 CK_DLL_CGET( LiSaMulti_cget_pindex0 )
3716 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3718 // return
3719 RETURN->v_dur = (t_CKDUR)d->pindex[0];
3723 //-----------------------------------------------------------------------------
3724 // name: LiSaMulti_ctrl_pindex()
3725 // desc: CTRL function
3726 //-----------------------------------------------------------------------------
3727 CK_DLL_CTRL( LiSaMulti_ctrl_rindex )
3729 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3730 d->rindex = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS);
3732 RETURN->v_dur = (t_CKDUR)d->rindex;
3736 //-----------------------------------------------------------------------------
3737 // name: LiSaMulti_cget_pindex()
3738 // desc: CGET function
3739 //-----------------------------------------------------------------------------
3740 CK_DLL_CGET( LiSaMulti_cget_rindex )
3742 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3744 // return
3745 RETURN->v_dur = (t_CKDUR)d->rindex;
3749 //-----------------------------------------------------------------------------
3750 // name: LiSaMulti_ctrl_lstart()
3751 // desc: CTRL function
3752 //-----------------------------------------------------------------------------
3753 CK_DLL_CTRL( LiSaMulti_ctrl_lstart )
3755 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3756 t_CKINT which = GET_NEXT_INT(ARGS);
3757 d->loop_start[which] = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS);
3759 if (d->loop_start[which] < 0) d->loop_start[which] = 0;
3761 RETURN->v_dur = (t_CKDUR)d->loop_start[which];
3765 CK_DLL_CTRL( LiSaMulti_ctrl_lstart0 )
3767 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3768 d->loop_start[0] = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS);
3770 if (d->loop_start[0] < 0) d->loop_start[0] = 0;
3772 RETURN->v_dur = (t_CKDUR)d->loop_start[0];
3776 //-----------------------------------------------------------------------------
3777 // name: LiSaMulti_cget_lstart()
3778 // desc: CGET function
3779 //-----------------------------------------------------------------------------
3780 CK_DLL_CGET( LiSaMulti_cget_lstart )
3782 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3784 t_CKINT which = GET_NEXT_INT(ARGS);
3785 // return
3786 RETURN->v_dur = (t_CKDUR)d->loop_start[which];
3790 CK_DLL_CGET( LiSaMulti_cget_lstart0 )
3792 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3794 // return
3795 RETURN->v_dur = (t_CKDUR)d->loop_start[0];
3799 //-----------------------------------------------------------------------------
3800 // name: LiSaMulti_ctrl_lend()
3801 // desc: CTRL function
3802 //-----------------------------------------------------------------------------
3803 CK_DLL_CTRL( LiSaMulti_ctrl_lend )
3805 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3806 t_CKINT which = GET_NEXT_INT(ARGS);
3807 d->loop_end[which] = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS);
3809 //check to make sure loop_end is not too large
3810 if (d->loop_end[which] >= d->mdata_len) d->loop_end[which] = d->mdata_len - 1;
3812 RETURN->v_dur = (t_CKDUR)d->loop_end[which];
3816 CK_DLL_CTRL( LiSaMulti_ctrl_lend0 )
3818 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3819 d->loop_end[0] = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS);
3821 //check to make sure loop_end is not too large
3822 if (d->loop_end[0] >= d->mdata_len) d->loop_end[0] = d->mdata_len - 1;
3824 RETURN->v_dur = (t_CKDUR)d->loop_end[0];
3828 //-----------------------------------------------------------------------------
3829 // name: LiSaMulti_cget_lend()
3830 // desc: CGET function
3831 //-----------------------------------------------------------------------------
3832 CK_DLL_CGET( LiSaMulti_cget_lend )
3834 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3835 t_CKINT which = GET_NEXT_INT(ARGS);
3837 // return
3838 RETURN->v_dur = (t_CKDUR)d->loop_end[which];
3842 CK_DLL_CGET( LiSaMulti_cget_lend0 )
3844 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3846 // return
3847 RETURN->v_dur = (t_CKDUR)d->loop_end[0];
3851 //-----------------------------------------------------------------------------
3852 // name: LiSaMulti_ctrl_loop()
3853 // desc: CTRL function
3854 //-----------------------------------------------------------------------------
3855 CK_DLL_CTRL( LiSaMulti_ctrl_loop )
3857 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3858 t_CKINT which = GET_NEXT_INT(ARGS);
3859 d->loopplay[which] = (t_CKBOOL)GET_NEXT_INT(ARGS);
3863 CK_DLL_CTRL( LiSaMulti_ctrl_loop0 )
3865 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3866 d->loopplay[0] = (t_CKBOOL)GET_NEXT_INT(ARGS);
3868 RETURN->v_int = (t_CKINT)d->loopplay[0];
3872 //-----------------------------------------------------------------------------
3873 // name: LiSaMulti_cget_loop()
3874 // desc: CGET function
3875 //-----------------------------------------------------------------------------
3876 CK_DLL_CGET( LiSaMulti_cget_loop )
3878 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3879 t_CKINT which = GET_NEXT_INT(ARGS);
3881 // return
3882 RETURN->v_int = (t_CKINT)d->loopplay[which];
3886 CK_DLL_CGET( LiSaMulti_cget_loop0 )
3888 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3890 // return
3891 RETURN->v_int = (t_CKINT)d->loopplay[0];
3895 //-----------------------------------------------------------------------------
3896 // name: LiSaMulti_ctrl_bi()
3897 // desc: CTRL function
3898 //-----------------------------------------------------------------------------
3899 CK_DLL_CTRL( LiSaMulti_ctrl_bi )
3901 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3902 t_CKINT which = GET_NEXT_INT(ARGS);
3903 d->bi[which] = (t_CKBOOL)GET_NEXT_INT(ARGS);
3905 RETURN->v_int = (t_CKINT)d->bi[which];
3909 CK_DLL_CTRL( LiSaMulti_ctrl_bi0 )
3911 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3912 d->bi[0] = (t_CKBOOL)GET_NEXT_INT(ARGS);
3914 RETURN->v_int = (t_CKINT)d->bi[0];
3918 //-----------------------------------------------------------------------------
3919 // name: LiSaMulti_cget_bi()
3920 // desc: CGET function
3921 //-----------------------------------------------------------------------------
3922 CK_DLL_CGET( LiSaMulti_cget_bi )
3924 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3925 t_CKINT which = GET_NEXT_INT(ARGS);
3927 // return
3928 RETURN->v_int = (t_CKINT)d->bi[which];
3932 CK_DLL_CGET( LiSaMulti_cget_bi0 )
3934 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3936 // return
3937 RETURN->v_int = (t_CKINT)d->bi[0];
3941 //-----------------------------------------------------------------------------
3942 // name: LiSaMulti_ctrl_loop_end_rec()
3943 // desc: CTRL function
3944 //-----------------------------------------------------------------------------
3945 CK_DLL_CTRL( LiSaMulti_ctrl_loop_end_rec )
3947 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3948 d->loop_end_rec = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS);
3950 RETURN->v_dur = (t_CKDUR)d->loop_end_rec;
3954 //-----------------------------------------------------------------------------
3955 // name: LiSaMulti_cget_loop_end_rec()
3956 // desc: CGET function
3957 //-----------------------------------------------------------------------------
3958 CK_DLL_CGET( LiSaMulti_cget_loop_end_rec )
3960 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3962 // return
3963 RETURN->v_dur = (t_CKDUR)d->loop_end_rec;
3967 //-----------------------------------------------------------------------------
3968 // name: LiSaMulti_ctrl_loop_rec()
3969 // desc: CTRL function
3970 //-----------------------------------------------------------------------------
3971 CK_DLL_CTRL( LiSaMulti_ctrl_loop_rec )
3973 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3974 d->looprec = (t_CKBOOL)GET_NEXT_INT(ARGS);
3976 RETURN->v_int = (t_CKINT)d->looprec;
3980 //-----------------------------------------------------------------------------
3981 // name: LiSaMulti_cget_loop_rec()
3982 // desc: CGET function
3983 //-----------------------------------------------------------------------------
3984 CK_DLL_CGET( LiSaMulti_cget_loop_rec )
3986 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3988 // return
3989 RETURN->v_int = (t_CKINT)d->looprec;
3992 //-----------------------------------------------------------------------------
3993 // name: LiSaMulti_ctrl_sample(); put a sample directly into record buffer
3994 // desc: CTRL function
3995 //-----------------------------------------------------------------------------
3996 CK_DLL_CTRL( LiSaMulti_ctrl_sample )
3998 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
3999 SAMPLE sample_in = (SAMPLE)GET_NEXT_FLOAT(ARGS);
4000 int index_in = (t_CKINT)GET_NEXT_DUR(ARGS);
4002 d->pokeSample( sample_in, index_in );
4004 RETURN->v_float = (t_CKFLOAT)sample_in; //pass input through
4007 //-----------------------------------------------------------------------------
4008 // name: LiSaMulti_cget_sample(); grab a sample from the record buffer
4009 // desc: CGET function
4010 //-----------------------------------------------------------------------------
4011 CK_DLL_CGET( LiSaMulti_cget_sample )
4013 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4014 double index_in = (t_CKDOUBLE)GET_NEXT_DUR(ARGS);
4015 // return
4016 RETURN->v_float = (t_CKFLOAT)d->grabSample( index_in ); //change this to getSamp for interpolation
4020 //-----------------------------------------------------------------------------
4021 // name: LiSaMulti_ctrl_voicegain()
4022 // desc: CTRL function
4023 //-----------------------------------------------------------------------------
4024 CK_DLL_CTRL( LiSaMulti_ctrl_voicegain )
4026 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4027 t_CKINT which = GET_NEXT_INT(ARGS);
4028 d->voiceGain[which] = (t_CKDOUBLE)GET_NEXT_FLOAT(ARGS);
4030 RETURN->v_float = (t_CKFLOAT)d->coeff;
4034 //-----------------------------------------------------------------------------
4035 // name: LiSaMulti_cget_voicegain()
4036 // desc: CGET function
4037 //-----------------------------------------------------------------------------
4038 CK_DLL_CGET( LiSaMulti_cget_voicegain )
4040 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4041 t_CKINT which = GET_NEXT_INT(ARGS);
4043 // return
4044 RETURN->v_float = (t_CKFLOAT)d->voiceGain[which];
4048 //-----------------------------------------------------------------------------
4049 // name: LiSaMulti_ctrl_coeff()
4050 // desc: CTRL function
4051 //-----------------------------------------------------------------------------
4052 CK_DLL_CTRL( LiSaMulti_ctrl_coeff )
4054 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4055 d->coeff = (t_CKDOUBLE)GET_NEXT_FLOAT(ARGS);
4057 RETURN->v_float = (t_CKFLOAT)d->coeff;
4060 //-----------------------------------------------------------------------------
4061 // name: LiSaMulti_cget_coeff()
4062 // desc: CGET function
4063 //-----------------------------------------------------------------------------
4064 CK_DLL_CGET( LiSaMulti_cget_coeff )
4066 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4068 // return
4069 RETURN->v_float = (t_CKFLOAT)d->coeff;
4073 //-----------------------------------------------------------------------------
4074 // name: LiSaMulti_ctrl_clear()
4075 // desc: CTRL function
4076 //-----------------------------------------------------------------------------
4077 CK_DLL_CTRL( LiSaMulti_ctrl_clear )
4079 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4080 d->clear_buf();
4085 //-----------------------------------------------------------------------------
4086 // name: LiSaMulti_cget_voice()
4087 // desc: CGET function
4088 //-----------------------------------------------------------------------------
4089 CK_DLL_CGET( LiSaMulti_cget_voice )
4091 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4093 // return
4094 RETURN->v_int = (t_CKINT)d->get_free_voice();
4098 // ramp stuff
4099 //-----------------------------------------------------------------------------
4100 // name: LiSaMulti_ctrl_rampup()
4101 // desc: CTRL function
4102 //-----------------------------------------------------------------------------
4103 CK_DLL_CTRL( LiSaMulti_ctrl_rampup )
4105 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4106 t_CKINT voice = GET_NEXT_INT(ARGS);
4107 t_CKDUR len = GET_NEXT_DUR(ARGS);
4109 d->ramp_up(voice, len);
4111 RETURN->v_dur = (t_CKDUR)len;
4115 CK_DLL_CTRL( LiSaMulti_ctrl_rampup0 )
4117 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4118 t_CKDUR len = GET_NEXT_DUR(ARGS);
4120 d->ramp_up(0, len);
4122 RETURN->v_dur = (t_CKDUR)len;
4126 //-----------------------------------------------------------------------------
4127 // name: LiSaMulti_ctrl_rampdown()
4128 // desc: CTRL function
4129 //-----------------------------------------------------------------------------
4130 CK_DLL_CTRL( LiSaMulti_ctrl_rampdown )
4132 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4133 t_CKINT voice = GET_NEXT_INT(ARGS);
4134 t_CKDUR len = GET_NEXT_DUR(ARGS);
4136 d->ramp_down(voice, len);
4138 RETURN->v_dur = (t_CKDUR)len;
4142 CK_DLL_CTRL( LiSaMulti_ctrl_rampdown0 )
4144 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4145 t_CKDUR len = GET_NEXT_DUR(ARGS);
4147 d->ramp_down(0, len);
4149 RETURN->v_dur = (t_CKDUR)len;
4153 //-----------------------------------------------------------------------------
4154 // name: LiSaMulti_ctrl_rec_ramplen()
4155 // desc: CTRL function
4156 //-----------------------------------------------------------------------------
4157 CK_DLL_CTRL( LiSaMulti_ctrl_rec_ramplen )
4159 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4160 t_CKDUR newramplen = GET_NEXT_DUR(ARGS);
4161 d->set_rec_ramplen(newramplen);
4163 RETURN->v_dur = (t_CKDUR)newramplen;
4167 //-----------------------------------------------------------------------------
4168 // name: LiSaMulti_ctrl_maxvoices()
4169 // desc: CTRL function
4170 //-----------------------------------------------------------------------------
4171 CK_DLL_CTRL( LiSaMulti_ctrl_maxvoices )
4173 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4174 d->maxvoices = GET_NEXT_INT(ARGS);
4175 if( d->maxvoices > LiSa_MAXVOICES) {
4176 d->maxvoices = LiSa_MAXVOICES;
4177 fprintf(stderr, "LiSa: MAXVOICES limited to %d.\n", LiSa_MAXVOICES);
4179 RETURN->v_int = d->maxvoices;
4183 //-----------------------------------------------------------------------------
4184 // name: LiSaMulti_cget_maxvoices()
4185 // desc: CGET function
4186 //-----------------------------------------------------------------------------
4187 CK_DLL_CGET( LiSaMulti_cget_maxvoices )
4189 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4191 // return
4192 RETURN->v_int = d->maxvoices;
4196 //-----------------------------------------------------------------------------
4197 // name: LiSaMulti_cget_samp()
4198 // desc: CGET function
4199 //-----------------------------------------------------------------------------
4200 CK_DLL_CGET( LiSaMulti_cget_value )
4202 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4203 t_CKINT voice = GET_NEXT_INT(ARGS);
4204 t_CKDOUBLE where = (t_CKDOUBLE) GET_NEXT_DUR(ARGS);
4206 // return
4207 RETURN->v_dur = (t_CKDUR)d->getSamp(where, voice);
4211 CK_DLL_CGET( LiSaMulti_cget_value0 )
4213 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4215 t_CKDOUBLE where = (t_CKDOUBLE) GET_NEXT_DUR(ARGS);
4216 // return
4217 RETURN->v_dur = (t_CKDUR)d->getSamp(where, 0);
4221 //-----------------------------------------------------------------------------
4222 // name: LiSaMulti_ctrl_track()
4223 // desc: CTRL function
4224 //-----------------------------------------------------------------------------
4225 CK_DLL_CTRL( LiSaMulti_ctrl_track )
4227 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4228 d->track = (t_CKINT)GET_NEXT_INT(ARGS);
4230 RETURN->v_int = d->track;
4234 //-----------------------------------------------------------------------------
4235 // name: LiSaMulti_cget_sync()
4236 // desc: CGET function
4237 //-----------------------------------------------------------------------------
4238 CK_DLL_CGET( LiSaMulti_cget_track )
4240 LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data);
4242 // return
4243 RETURN->v_int = d->track;
4247 //-----------------------------------------------------------------------------
4248 // name: LiSaMulti_pmsg()
4249 // desc: PMSG function ...
4250 //-----------------------------------------------------------------------------
4251 CK_DLL_PMSG(LiSaMulti_pmsg )
4253 return FALSE;