*** empty log message ***
[chuck-blob.git] / v1 / ugen_xxx.cpp
blob5ff1941f88a2afb6999febc96b4d407fb31c15cd
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 // date: Spring 2004
32 //-----------------------------------------------------------------------------
33 #include "ugen_xxx.h"
34 #include <math.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/stat.h>
39 #include <limits.h>
40 #include <fstream>
41 using namespace std;
43 t_CKUINT g_srate;
46 //-----------------------------------------------------------------------------
47 // name: xxx_query()
48 // desc: ...
49 //-----------------------------------------------------------------------------
50 DLL_QUERY xxx_query( Chuck_DL_Query * QUERY )
52 g_srate = QUERY->srate;
54 //! \section audio output
56 // add dac
57 //! digital/analog converter
58 //! abstraction for underlying audio output device
59 QUERY->ugen_add( QUERY, "dac", NULL );
60 // set funcs
61 QUERY->ugen_func( QUERY, NULL, NULL, dac_tick, NULL );
63 // add adc
64 //! analog/digital converter
65 //! abstraction for underlying audio input device
66 QUERY->ugen_add( QUERY, "adc", NULL );
67 // set funcs
68 QUERY->ugen_func( QUERY, NULL, NULL, dac_tick, NULL );
70 // add blackhole
71 //! sample rate sample sucker
72 //! ( like dac, ticks ugens, but no more )
73 //! see \example pwm.ck
74 QUERY->ugen_add( QUERY, "blackhole", NULL );
75 // set funcs
76 QUERY->ugen_func( QUERY, NULL, NULL, bunghole_tick, NULL );
78 // add bunghole
79 //! sample rate sample sucker
80 //! ( like dac, ticks ugens, but no more )
81 QUERY->ugen_add( QUERY, "bunghole", NULL );
82 // set funcs
83 QUERY->ugen_func( QUERY, NULL, NULL, bunghole_tick, NULL );
85 // add gain
86 //! gain control
87 //! (NOTE - all unit generators can themselves change their gain)
88 //! (this is a way to add N outputs together and scale them)
89 //! used in \example i-robot.ck
90 QUERY->ugen_add( QUERY, "gain", NULL );
91 // set funcs
92 QUERY->ugen_func( QUERY, gain_ctor, gain_dtor, gain_tick, NULL );
93 // ctrl func
94 QUERY->ugen_ctrl( QUERY, gain_ctrl_value, gain_cget_value, "float", "value" ); //! set gain ( all ugen's have this )
95 /*! \example
96 noise n => gain g => dac;
97 sinosc s => g;
98 .3 => g.gain;
99 while( true ) { 100::ms => now; }
102 //! \section wave forms
104 // add noise
105 //! white noise generator
106 //! see \example noise.ck \example powerup.ck
107 QUERY->ugen_add( QUERY, "noise", NULL );
108 // set funcs
109 QUERY->ugen_func( QUERY, NULL, NULL, noise_tick, NULL );
111 // add cnoise
112 QUERY->ugen_add( QUERY, "cnoise", NULL );
113 QUERY->ugen_func( QUERY, cnoise_ctor, cnoise_dtor, cnoise_tick, NULL );
114 QUERY->ugen_ctrl( QUERY, cnoise_ctrl_mode, NULL, "string", "mode" );
115 QUERY->ugen_ctrl( QUERY, cnoise_ctrl_fprob, NULL, "float", "fprob" );
118 // add impulse
119 //! pulse generator - can set the value of the current sample
120 //! default for each sample is 0 if not set
121 QUERY->ugen_add( QUERY, "impulse", NULL );
122 // set funcs
123 QUERY->ugen_func( QUERY, impulse_ctor, impulse_dtor, impulse_tick, NULL );
124 // ctrl func
125 QUERY->ugen_ctrl( QUERY, impulse_ctrl_value, impulse_cget_value, "float", "value" );
126 QUERY->ugen_ctrl( QUERY, impulse_ctrl_value, impulse_cget_value, "float", "next" ); //! set value of next sample
127 /*! \example
128 impulse i => dac;
130 while( true ) {
131 1.0 => i.next;
132 100::ms => now;
136 // add step
137 //! step generator - like impulse, but once a value is set,
138 //! it is held for all following samples, until value is set again
139 //! see \example step.ck
140 QUERY->ugen_add( QUERY, "step", NULL );
141 // set funcs
142 QUERY->ugen_func( QUERY, step_ctor, step_dtor, step_tick, NULL );
143 // ctrl func
144 QUERY->ugen_ctrl( QUERY, step_ctrl_value, step_cget_value, "float", "value" );
145 QUERY->ugen_ctrl( QUERY, step_ctrl_value, step_cget_value, "float", "next" ); //! set the step value
146 /*! \example
147 step s => dac;
148 -1.0 => float amp;
150 // square wave using step
151 while( true ) {
152 -amp => amp => s.next;
153 800::samp => now;
157 //! \section filters
159 // add halfrect
160 //! half wave rectifier
161 //! for half-wave rectification.
162 QUERY->ugen_add( QUERY, "halfrect", NULL );
163 // set funcs
164 QUERY->ugen_func( QUERY, NULL, NULL, halfrect_tick, NULL );
166 // add fullrect
167 //! full wave rectifier
168 QUERY->ugen_add( QUERY, "fullrect", NULL );
169 // set funcs
170 QUERY->ugen_func( QUERY, NULL, NULL, fullrect_tick, NULL );
172 // add zerox
173 //! zero crossing detector
174 //! emits a single pulse at the the zero crossing in the direction of the zero crossing.
175 //! (see \example zerox.ck)
176 QUERY->ugen_add( QUERY, "zerox", NULL );
177 // set funcs
178 QUERY->ugen_func( QUERY, zerox_ctor, zerox_dtor, zerox_tick, NULL );
180 //! \section delay lines
182 //! delay with varying write position ( instead of read position )
183 //! change to delay length will not affect the delay of samples already in
184 //! the buffer.
185 //! see \example delayp.ck
187 QUERY->ugen_add( QUERY, "delayp" , NULL);
188 QUERY->ugen_func ( QUERY, delayp_ctor, delayp_dtor, delayp_tick, delayp_pmsg);
189 QUERY->ugen_ctrl( QUERY, delayp_ctrl_delay, delayp_cget_delay , "dur", "delay" ); //! delay before subsequent values emerge
190 QUERY->ugen_ctrl( QUERY, delayp_ctrl_window, delayp_cget_window , "dur", "window" ); //! time for 'write head' to move
191 QUERY->ugen_ctrl( QUERY, delayp_ctrl_max, delayp_cget_max , "dur", "max" ); //! max delay possible. trashes buffer, so do it first!
194 //! \section sound files
196 // add sndbuf
197 //! sound buffer ( now interpolating )
198 //! reads from a variety of file formats
199 //! see \example sndbuf.ck
200 QUERY->ugen_add( QUERY, "sndbuf", NULL );
201 // set funcs
202 QUERY->ugen_func( QUERY, sndbuf_ctor, sndbuf_dtor, sndbuf_tick, NULL );
203 // set ctrl
204 QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_read, NULL, "string", "read" ); //! loads file for reading
205 QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_write, NULL, "string", "write" ); //! loads a file for writing ( or not )
206 QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_pos, sndbuf_cget_pos, "int", "pos" ); //! set position ( 0 < p < .samples )
207 QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_loop, sndbuf_cget_loop, "int", "loop" ); //! toggle looping
208 QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_interp, sndbuf_cget_interp, "int", "interp" ); //! set interpolation ( 0=drop, 1=linear, 2=sinc )
209 QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_rate, sndbuf_cget_rate, "float", "rate" ); //! playback rate ( relative to file's natural speed )
210 QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_rate, sndbuf_cget_rate, "float", "play" ); //! play (same as rate)
211 QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_freq, sndbuf_cget_freq, "float", "freq" ); //! playback rate ( file loops / second )
212 QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_phase, sndbuf_cget_phase, "float", "phase" ); //! set phase position ( 0-1 )
213 QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_channel, sndbuf_cget_channel, "int", "channel" ); //! select channel ( 0 < p < .channels )
214 QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_phase_offset, sndbuf_cget_phase, "float", "phase_offset" ); //! set a phase offset
215 QUERY->ugen_ctrl( QUERY, NULL, sndbuf_cget_samples, "int", "samples" ); //! fetch number of samples
216 QUERY->ugen_ctrl( QUERY, NULL, sndbuf_cget_length, "dur", "length" ); //! fetch length
217 QUERY->ugen_ctrl( QUERY, NULL, sndbuf_cget_channels, "int", "channels" ); //! fetch number of channels
219 return TRUE;
225 //-----------------------------------------------------------------------------
226 // name: noise_tick()
227 // desc: ...
228 //-----------------------------------------------------------------------------
229 UGEN_TICK noise_tick( t_CKTIME now, void * data, SAMPLE in, SAMPLE * out )
231 *out = -1.0 + 2.0 * (SAMPLE)rand() / RAND_MAX;
232 return TRUE;
236 enum { NOISE_WHITE=0, NOISE_PINK, NOISE_BROWN, NOISE_FBM, NOISE_FLIP, NOISE_XOR };
238 class CNoise_Data {
239 private:
240 SAMPLE value;
242 t_CKFLOAT fbmH;
243 int counter;
244 int* pink_array;
245 int pink_depth;
246 bool pink_rand;
247 int rand_bits;
248 double scale;
249 double bias;
251 long int last;
252 public:
253 CNoise_Data() {
254 value = 0;
255 mode = NOISE_PINK;
256 pink_depth = 24;
257 pink_array = NULL;
258 counter = 1;
259 scale = 2.0 / (double) RAND_MAX ;
260 bias = -1.0;
261 pink_rand = false;
262 int randt = RAND_MAX;
263 rand_bits = 0;
264 fprob = (int) ( (double)RAND_MAX * 1.0 / 32.0 );
265 while ( randt > 0 ) {
266 rand_bits++;
267 randt = randt >> 1;
269 fprintf(stderr, "random bits - %d", rand_bits );
270 setMode ( "pink" );
272 ~CNoise_Data() {}
274 int fprob;
275 t_CKUINT mode;
276 void tick( t_CKTIME now, SAMPLE * out );
277 void setMode(char * c);
279 int pink_tick( SAMPLE * out);
280 int brown_tick( SAMPLE * out);
281 int xor_tick( SAMPLE * out);
282 int flip_tick( SAMPLE * out);
283 int fbm_tick( SAMPLE * out);
287 UGEN_CTOR cnoise_ctor( t_CKTIME now ) {
288 return new CNoise_Data();
291 UGEN_DTOR cnoise_dtor ( t_CKTIME now, void * data ) {
292 delete ( CNoise_Data* )data ;
295 UGEN_TICK cnoise_tick ( t_CKTIME now, void * data, SAMPLE in, SAMPLE * out ) {
296 CNoise_Data * d = ( CNoise_Data * ) data;
297 switch( d->mode ) {
298 case NOISE_WHITE:
299 return noise_tick(now,data,in,out);
300 break;
301 case NOISE_PINK:
302 return d->pink_tick(out);
303 break;
304 case NOISE_BROWN:
305 return d->brown_tick(out);
306 break;
307 case NOISE_XOR:
308 return d->xor_tick(out);
309 break;
310 case NOISE_FLIP:
311 return d->flip_tick(out);
312 break;
313 case NOISE_FBM:
314 return d->fbm_tick(out);
315 break;
317 return TRUE;
321 CNoise_Data::pink_tick( SAMPLE * out) {
323 //based on Voss-McCartney
325 if ( pink_array == NULL ) {
326 pink_array = (int *) malloc ( sizeof ( int ) * pink_depth );
327 last = 0;
328 for ( int i = 0 ; i < pink_depth ; i++ ) { pink_array[i] = rand(); last += pink_array[i]; }
329 scale = 2.0 / ((double)RAND_MAX * ( pink_depth + 1.0 ) );
330 bias = 0.0;
331 fprintf( stderr, "scale %f %f %d %d \n", scale, bias, RAND_MAX, pink_depth + 1 );
334 int pind = 0;
336 //count trailing zeroes
337 while ( pind < pink_depth && ! (counter & ( 1 << pind ) ) ) pind++;
339 // fprintf (stderr, "counter %d pink - %d \n", counter, pind );
341 if ( pind < pink_depth ) {
342 int diff = rand() - pink_array[pind];
343 pink_array[pind] += diff;
344 last += diff;
347 *out = bias + scale * ( rand() + last );
348 counter++;
349 if ( pink_rand ) counter = rand();
350 return TRUE;
354 CNoise_Data::xor_tick( SAMPLE * out ) {
356 int mask = 0;
357 for ( int i = 0; i < rand_bits ; i++ )
358 if ( rand() <= fprob )
359 mask |= ( 1 << i );
360 last = last ^ mask;
361 *out = bias + scale * (SAMPLE)last;
362 return TRUE;
366 CNoise_Data::flip_tick( SAMPLE * out ) {
367 int ind = (int) ( (double) rand_bits * rand() / ( RAND_MAX + 1.0 ) );
369 last = last ^ ( 1 << ind );
370 // fprintf ( stderr, "ind - %d %d %f %f", ind, last, bias, scale );
371 *out = bias + scale * (SAMPLE)last;
372 return TRUE;
376 CNoise_Data::brown_tick( SAMPLE * out ) {
377 //brownian noise function..later!
378 *out = 0;
379 return TRUE;
383 CNoise_Data::fbm_tick( SAMPLE * out ) {
384 //brownian noise function..later!
385 *out = 0;
386 return TRUE;
389 void
390 CNoise_Data::setMode( char * c ) {
391 if ( strcmp ( c, "white" ) == 0 ) {
392 fprintf(stderr, "white noise\n");
393 mode = NOISE_WHITE;
394 scale = 2.0 / (t_CKFLOAT)RAND_MAX;
395 bias = -1.0;
397 if ( strcmp ( c, "pink" ) == 0 ) {
398 fprintf(stderr, "pink noise\n");
399 mode = NOISE_PINK;
400 scale = 2.0 / (double)(RAND_MAX * ( pink_depth + 1 ) );
401 bias = -1.0;
403 if ( strcmp ( c, "flip" ) == 0) {
404 fprintf(stderr, "bitflip noise\n");
405 mode = NOISE_FLIP;
406 scale = 2.0 / (t_CKFLOAT)RAND_MAX;
407 bias = -1.0;
409 if ( strcmp ( c, "xor" ) == 0) {
410 fprintf(stderr, "xor noise\n");
411 mode = NOISE_XOR;
412 scale = 2.0 / (t_CKFLOAT)RAND_MAX;
413 bias = -1.0;
415 if ( strcmp ( c, "brown" ) == 0) {
416 fprintf(stderr, "brownian noise\n");
417 mode = NOISE_BROWN;
418 scale = 2.0 / (t_CKFLOAT)RAND_MAX;
419 bias = -1.0;
421 if ( strcmp ( c, "fbm" ) == 0) {
422 fprintf(stderr, "fbm noise\n");
423 mode = NOISE_FBM;
424 scale = 2.0 / (t_CKFLOAT)RAND_MAX;
425 bias = -1.0;
430 UGEN_CTRL cnoise_ctrl_mode( t_CKTIME now, void * data, void * value )
432 CNoise_Data * d = (CNoise_Data *)data;
433 char * mode= *(char **)value;
434 d->setMode(mode);
437 UGEN_CTRL cnoise_ctrl_fprob( t_CKTIME now, void * data, void * value )
439 CNoise_Data * d = (CNoise_Data *)data;
440 t_CKFLOAT p= *(t_CKFLOAT *)value;
441 d->fprob = (int) ( (double)RAND_MAX * p );
446 //-----------------------------------------------------------------------------
447 // name: struct Pulse_Data
448 // desc: ...
449 //-----------------------------------------------------------------------------
450 struct Pulse_Data
452 SAMPLE value;
453 t_CKUINT when;
454 Pulse_Data( ) { value = 1.0f; when = 0; }
458 //-----------------------------------------------------------------------------
459 // name: impulse_ctor()
460 // desc: ...
461 //-----------------------------------------------------------------------------
462 UGEN_CTOR impulse_ctor( t_CKTIME now )
464 // return data to be used later
465 return new Pulse_Data;
471 //-----------------------------------------------------------------------------
472 // name: impulse_dtor()
473 // desc: ...
474 //-----------------------------------------------------------------------------
475 UGEN_DTOR impulse_dtor( t_CKTIME now, void * data )
477 // delete
478 delete (Pulse_Data *)data;
484 //-----------------------------------------------------------------------------
485 // name: impulse_tick()
486 // desc: ...
487 //-----------------------------------------------------------------------------
488 UGEN_TICK impulse_tick( t_CKTIME now, void * data, SAMPLE in, SAMPLE * out )
490 Pulse_Data * d = (Pulse_Data *)data;
491 if( d->when )
493 *out = d->value;
494 d->value = 0;
496 else
497 *out = 0.0f;
499 return TRUE;
504 //-----------------------------------------------------------------------------
505 // name: impulse_ctrl_value()
506 // desc: ...
507 //-----------------------------------------------------------------------------
508 UGEN_CTRL impulse_ctrl_value( t_CKTIME now, void * data, void * value )
510 Pulse_Data * d = (Pulse_Data *)data;
511 d->value = (SAMPLE)*(t_CKFLOAT *)value;
512 d->when = 1;
516 //-----------------------------------------------------------------------------
517 // name: impulse_cget_value()
518 // desc: ...
519 //-----------------------------------------------------------------------------
520 UGEN_CGET impulse_cget_value( t_CKTIME now, void * data, void * out )
522 Pulse_Data * d = (Pulse_Data *)data;
523 SET_NEXT_FLOAT( out, d->value );
528 //-----------------------------------------------------------------------------
529 // name: step_ctor()
530 // desc: ...
531 //-----------------------------------------------------------------------------
532 UGEN_CTOR step_ctor( t_CKTIME now )
534 // return data to be used later
535 return new SAMPLE( 1.0f );
539 //-----------------------------------------------------------------------------
540 // name: step_dtor()
541 // desc: ...
542 //-----------------------------------------------------------------------------
543 UGEN_DTOR step_dtor( t_CKTIME now, void * data )
545 // delete
546 delete (SAMPLE *)data;
550 //-----------------------------------------------------------------------------
551 // name: step_tick()
552 // desc: ...
553 //-----------------------------------------------------------------------------
554 UGEN_TICK step_tick( t_CKTIME now, void * data, SAMPLE in, SAMPLE * out )
556 SAMPLE * d = (SAMPLE *)data;
557 *out = *d;
559 return TRUE;
563 //-----------------------------------------------------------------------------
564 // name: step_ctrl_value()
565 // desc: ...
566 //-----------------------------------------------------------------------------
567 UGEN_CTRL step_ctrl_value( t_CKTIME now, void * data, void * value )
569 SAMPLE * d = (SAMPLE *)data;
570 *d = (SAMPLE)*(t_CKFLOAT *)value;
574 //-----------------------------------------------------------------------------
575 // name: step_cget_value()
576 // desc: ...
577 //-----------------------------------------------------------------------------
578 UGEN_CGET step_cget_value( t_CKTIME now, void * data, void * out )
580 SAMPLE * d = (SAMPLE *)data;
581 SET_NEXT_FLOAT( out, (t_CKFLOAT)*d );
585 //-----------------------------------------------------------------------------
586 // name: gain_ctor()
587 // desc: ...
588 //-----------------------------------------------------------------------------
589 UGEN_CTOR gain_ctor( t_CKTIME now )
591 // return data to be used later
592 return new SAMPLE( 1.0f );
596 //-----------------------------------------------------------------------------
597 // name: gain_dtor()
598 // desc: ...
599 //-----------------------------------------------------------------------------
600 UGEN_DTOR gain_dtor( t_CKTIME now, void * data )
602 // delete
603 delete (SAMPLE *)data;
607 //-----------------------------------------------------------------------------
608 // name: gain_tick()
609 // desc: ...
610 //-----------------------------------------------------------------------------
611 UGEN_TICK gain_tick( t_CKTIME now, void * data, SAMPLE in, SAMPLE * out )
613 SAMPLE * d = (SAMPLE *)data;
614 *out = in * (*d);
616 return TRUE;
620 //-----------------------------------------------------------------------------
621 // name: gain_ctrl_value()
622 // desc: ...
623 //-----------------------------------------------------------------------------
624 UGEN_CTRL gain_ctrl_value( t_CKTIME now, void * data, void * value )
626 SAMPLE * d = (SAMPLE *)data;
627 *d = (SAMPLE)*(t_CKFLOAT *)value;
631 //-----------------------------------------------------------------------------
632 // name: gain_cget_value()
633 // desc: ...
634 //-----------------------------------------------------------------------------
635 UGEN_CGET gain_cget_value( t_CKTIME now, void * data, void * out )
637 SAMPLE * d = (SAMPLE *)data;
638 SET_NEXT_FLOAT( out, (t_CKFLOAT)*d );
642 //-----------------------------------------------------------------------------
643 // name: halfrect_tick()
644 // desc: ...
645 //-----------------------------------------------------------------------------
646 UGEN_TICK halfrect_tick( t_CKTIME now, void * data, SAMPLE in, SAMPLE * out )
648 *out = in > 0.0f ? in : 0.0f;
649 return TRUE;
655 //-----------------------------------------------------------------------------
656 // name: fullrect_tick()
657 // desc: ...
658 //-----------------------------------------------------------------------------
659 UGEN_TICK fullrect_tick( t_CKTIME now, void * data, SAMPLE in, SAMPLE * out )
661 *out = in >= 0.0f ? in : -in;
662 return TRUE;
668 //-----------------------------------------------------------------------------
669 // name: zerox_ctor()
670 // desc: ...
671 //-----------------------------------------------------------------------------
672 UGEN_CTOR zerox_ctor( t_CKTIME now )
674 return new SAMPLE( 0.0f );
678 //-----------------------------------------------------------------------------
679 // name: zerox_dtor()
680 // desc: ...
681 //-----------------------------------------------------------------------------
682 UGEN_DTOR zerox_dtor( t_CKTIME now, void * data )
684 delete (SAMPLE *)data;
688 #define __SGN(x) (x >= 0.0f ? 1.0f : -1.0f)
689 //-----------------------------------------------------------------------------
690 // name: zerox_tick()
691 // desc: ...
692 //-----------------------------------------------------------------------------
693 UGEN_TICK zerox_tick( t_CKTIME now, void * data, SAMPLE in, SAMPLE * out )
695 SAMPLE * d = (SAMPLE *)data;
696 *out = __SGN(in) != __SGN(*d);
697 *out *= __SGN(in);
698 *d = in;
700 return TRUE;
706 //-----------------------------------------------------------------------------
707 // name: dac_tick
708 // desc: ...
709 //-----------------------------------------------------------------------------
710 UGEN_TICK dac_tick( t_CKTIME now, void * data, SAMPLE in, SAMPLE * out )
712 // this is a placeholder - the real tick is the VM
713 return 0;
716 //-----------------------------------------------------------------------------
717 // name: bunghole_tick
718 // desc: ...
719 //-----------------------------------------------------------------------------
720 UGEN_TICK bunghole_tick( t_CKTIME now, void * data, SAMPLE in, SAMPLE * out )
722 *out = 0.0f;
723 return 0;
727 struct delayp_data
729 SAMPLE * buffer;
730 int bufsize;
732 double now;
733 double readpos;
735 double writepos; // relative to readpos
737 double writeoff;
739 double writeoff_start;
740 double writeoff_target;
741 double writeoff_target_time; //target time
742 double writeoff_window_time; //time we started shift
744 SAMPLE sample_last;
745 double writeoff_last;
747 double acoeff[2];
748 double bcoeff[2];
749 SAMPLE outputs[3];
750 SAMPLE inputs[3];
752 delayp_data()
754 bufsize = 2 * g_srate;
755 buffer = ( SAMPLE * ) realloc ( NULL, sizeof ( SAMPLE ) * bufsize );
756 int i;
758 for ( i = 0 ; i < bufsize ; i++ ) buffer[i] = 0;
759 for ( i = 0 ; i < 3 ; i++ ) { acoeff[i] = 0; bcoeff[i] = 0; }
760 acoeff[0] = 1.0;
761 acoeff[1] = -.99;
762 bcoeff[0] = 1.0;
763 bcoeff[1] = -1.0;
764 readpos = 0.0;
766 writeoff = 1000.0;
767 writeoff_last = 1000.0;
768 writeoff_start = 1000.0;
769 writeoff_target = 1000.0;
770 sample_last = 0;
771 writeoff_window_time = 1.0;
772 writeoff_target_time = 0.0;
776 UGEN_CTOR delayp_ctor( t_CKTIME now )
779 return new delayp_data;
782 UGEN_DTOR delayp_dtor( t_CKTIME now, void * data )
784 delayp_data * d = (delayp_data *)data;
785 if( d->buffer ) delete [] d->buffer;
786 delete d;
788 UGEN_PMSG delayp_pmsg( t_CKTIME now, void * data, const char * msg, void * value )
790 return TRUE;
792 UGEN_TICK delayp_tick( t_CKTIME now, void * data, SAMPLE in, SAMPLE * out ) {
795 delayp_data * d = (delayp_data *)data;
796 if ( !d->buffer ) return FALSE;
798 //calculate new write-offset position
799 if ( now >= d->writeoff_target_time || d->writeoff_window_time == 0 ) d->writeoff = d->writeoff_target;
800 else {
801 double dt = ( now - d->writeoff_target_time ) / ( d->writeoff_window_time );
802 d->writeoff = d->writeoff_target + dt * ( d->writeoff_target - d->writeoff_start );
803 // fprintf (stderr, "dt %f, off %f , start %f target %f\n", dt, d->writeoff, d->writeoff_start, d->writeoff_target );
806 //find locations in buffer...
807 double lastpos = d->writeoff_last + d->readpos - 1.0 ;
808 double nowpos = d->writeoff + d->readpos;
810 //linear interpolation. will introduce some lowpass/aliasing.
812 double diff= nowpos - lastpos;
813 double d_samp = in - d->sample_last;
814 int i, smin, smax;
815 SAMPLE sampi;
816 if ( diff >= 0 ) { //forward.
817 smin = (int)ceil( lastpos );
818 smax = (int)floor( nowpos );
819 for ( i = smin ; i <= smax ; i++ ) {
820 sampi = d->sample_last + d_samp * ( (double) i - lastpos ) / diff ;
821 // fprintf( stderr, "new sample %d %f %f %f \n", i, in, sampi, d->sample_last );
822 d->buffer[i%d->bufsize] += sampi;
825 else { //moving in reverse
826 smin = (int)ceil( nowpos );
827 smax = (int)floor( lastpos );
828 for ( i = smin ; i <= smax ; i++ )
829 sampi = d->sample_last + d_samp * ( (double) i - lastpos ) / diff ;
830 d->buffer[i%d->bufsize] += sampi ;
833 d->writeoff_last = d->writeoff;
834 d->sample_last = in;
837 //output should go through a dc blocking filter, for cases where
838 //we are zipping around in the buffer leaving a fairly constant
839 //trail of samples
841 //output last sample
842 int rpos = ( (int) d->readpos ) % d->bufsize ;
844 // *out = d->buffer[rpos];
846 d->outputs[0] = 0.0;
847 d->inputs [0] = d->buffer[rpos];
849 d->outputs[0] += d->bcoeff[1] * d->inputs[1];
850 d->inputs [1] = d->inputs[0];
852 d->outputs[0] += d->bcoeff[0] * d->inputs[0];
854 d->outputs[0] += -d->acoeff[1] * d->outputs[1];
855 d->outputs[1] = d->outputs[0];
857 *out = d->outputs[0];
860 d->buffer[rpos] = 0; //clear once it's been read
861 d->readpos++;
863 while ( d->readpos > d->bufsize ) d->readpos -= d->bufsize;
864 return TRUE;
868 UGEN_CTRL delayp_ctrl_delay( t_CKTIME now, void * data, void * value )
870 delayp_data * d = ( delayp_data * ) data;
871 t_CKDUR target = * (t_CKDUR *) value; // rate
872 if ( target != d->writeoff_target ) {
873 if ( target > d->bufsize ) {
874 fprintf( stderr, "[chuck](via delayp): delay time %f over max! set max first!\n", target);
875 return;
877 d->writeoff_target = target;
878 d->writeoff_start = d->writeoff_last;
879 d->writeoff_target_time = now + d->writeoff_window_time;
883 UGEN_CGET delayp_cget_delay( t_CKTIME now, void * data, void * out )
885 delayp_data * d = ( delayp_data * ) data;
886 SET_NEXT_DUR( out, d->writeoff_last );
889 UGEN_CTRL delayp_ctrl_window( t_CKTIME now, void * data, void * value )
891 delayp_data * d = ( delayp_data * ) data;
892 t_CKDUR window = * (t_CKDUR *) value; // rate
893 if ( window >= 0 ) {
894 d->writeoff_window_time = window;
895 //fprintf ( stderr, "set window time %f , %f , %d \n", d->writeoff_window_time, d->writeoff, d->bufsize );
899 UGEN_CGET delayp_cget_window( t_CKTIME now, void * data, void * out )
901 delayp_data * d = ( delayp_data * ) data;
902 SET_NEXT_DUR( out, d->writeoff_last );
906 UGEN_CTRL delayp_ctrl_max( t_CKTIME now, void * data, void * value )
908 delayp_data * d = ( delayp_data * ) data;
909 t_CKDUR nmax = * (t_CKDUR *) value; // rate
910 if ( d->bufsize != (int)nmax && nmax > 1.0 ) {
911 d->bufsize = (int)(nmax+.5);
912 d->buffer = ( SAMPLE * ) realloc ( d->buffer, sizeof ( SAMPLE ) * d->bufsize );
913 for ( int i = 0; i < d->bufsize; i++ ) d->buffer[i] = 0;
918 UGEN_CGET delayp_cget_max( t_CKTIME now, void * data, void * out )
920 delayp_data * d = ( delayp_data * ) data;
921 SET_NEXT_DUR( out, (t_CKDUR) d->bufsize );
924 //-----------------------------------------------------------------------------
925 // name: sndbuf
926 // desc: ...
927 //-----------------------------------------------------------------------------
928 enum { SNDBUF_DROP = 0, SNDBUF_INTERP, SNDBUF_SINC};
931 #define WIDTH 16 /* this controls the number of neighboring samples
932 which are used to interpolate the new samples. The
933 processing time is linearly related to this width */
934 #define DELAY_SIZE 140
936 #define USE_TABLE TRUE /* this controls whether a linearly interpolated lookup
937 table is used for sinc function calculation, or the
938 sinc is calculated by floating point trig function calls. */
940 #define USE_INTERP TRUE /* this controls whether the table is linear
941 interpolated or not. If you re not using the
942 table, this has no effect */
944 #define SAMPLES_PER_ZERO_CROSSING 32 /* this defines how finely the sinc function
945 is sampled for storage in the table */
947 struct sndbuf_data
949 SAMPLE * buffer;
950 t_CKUINT num_samples;
951 t_CKUINT num_channels;
952 t_CKUINT num_frames;
953 t_CKUINT samplerate;
954 t_CKUINT chan;
955 double sampleratio;
956 float * eob;
957 float * curr;
958 double curf;
959 float rate;
960 int interp;
961 t_CKBOOL loop;
963 bool sinc_table_built;
964 bool sinc_use_table;
965 bool sinc_use_interp;
966 int sinc_samples_per_zero_crossing ;
967 int sinc_width ;
968 double * sinc_table ;
969 sndbuf_data()
971 buffer = NULL;
972 interp = SNDBUF_INTERP;
973 num_channels = 0;
974 num_frames = 0;
975 num_samples = 0;
977 samplerate = 0;
979 sampleratio = 1.0;
980 chan = 0;
981 curf = 0.0;
982 rate = 1.0;
984 eob = NULL;
985 curr = NULL;
987 sinc_table_built = false;
988 sinc_use_table = USE_TABLE;
989 sinc_use_interp = USE_INTERP;
990 sinc_width = WIDTH;
991 sinc_samples_per_zero_crossing = SAMPLES_PER_ZERO_CROSSING;
992 sinc_table = NULL;
994 loop = FALSE;
998 double sndbuf_sinc ( sndbuf_data * d, double x );
999 double sndbuf_t_sinc( sndbuf_data * d, double x );
1000 void sndbuf_make_sinc( sndbuf_data * d );
1001 void sndbuf_sinc_interpolate ( sndbuf_data * d, SAMPLE * out);
1004 UGEN_CTOR sndbuf_ctor( t_CKTIME now )
1006 return new sndbuf_data;
1009 UGEN_DTOR sndbuf_dtor( t_CKTIME now, void * data )
1011 sndbuf_data * d = (sndbuf_data *)data;
1012 if( d->buffer ) delete [] d->buffer;
1013 delete d;
1016 inline void sndbuf_setpos(sndbuf_data *d, double pos)
1018 if( !d->buffer ) return;
1020 d->curf = pos;
1022 //set curf within bounds
1024 if( d->loop )
1026 while ( d->curf >= d->num_frames ) d->curf -= d->num_frames;
1027 while ( d->curf < 0 ) d->curf += d->num_frames;
1029 else
1031 if( d->curf < 0 ) d->curf = 0;
1032 else if( d->curf >= d->num_frames ) d->curf = d->num_frames-1;
1034 //sets curr to correct position ( account for channels )
1035 d->curr = d->buffer + d->chan + (long) d->curf * d->num_channels;
1038 inline SAMPLE sndbuf_sampleAt( sndbuf_data * d, int pos ) {
1039 //boundary cases
1041 int nf = d->num_frames;
1042 if ( d->loop ) {
1043 while ( pos >= nf ) pos -= nf;
1044 while ( pos < 0 ) pos += nf;
1046 else {
1047 if ( pos >= nf ) pos = nf-1;
1048 if ( pos < 0 ) pos = 0;
1051 return d->buffer[d->chan + (long) d->curf * d->num_channels];
1055 inline double sndbuf_getpos(sndbuf_data *d)
1057 if( !d->buffer ) return 0;
1058 return floor(d->curf);
1062 UGEN_CTRL sndbuf_ctrl_loop( t_CKTIME now, void * data, void * value )
1064 sndbuf_data * d = (sndbuf_data *)data;
1065 d->loop = *(int *)value;
1068 UGEN_CGET sndbuf_cget_loop( t_CKTIME now, void * data, void * out )
1070 sndbuf_data * d = (sndbuf_data *)data;
1071 SET_NEXT_INT( out, d->loop );
1074 // PRC's sinc interpolation function.. as found
1075 // http://www.cs.princeton.edu/courses/archive/spring03/cs325/src/TimeStuf/srconvrt.c
1077 // there's probably a lot in there that could be optimized, if we care to..
1079 #define PI 3.14159265358979323846
1080 //wow... we are sensitive..
1082 inline double sndbuf_linear_interp (double * first, double * second, double * frac);
1083 bool sinc_table_built = false;
1085 void sndbuf_sinc_interpolate ( sndbuf_data *d, SAMPLE * out )
1087 signed long j;
1088 double factor = d->rate;
1089 double time_now = d->curf;
1090 double one_over_factor;
1091 double int_time = 0;
1092 double last_time = 0;
1093 double temp1 = 0.0;
1095 long time_i = (long)time_now;
1097 //bounds checking now in sampleAt function...
1098 if (factor<1.0) {
1099 for (j= -d->sinc_width + 1 ; j < d->sinc_width; j++)
1101 temp1 += sndbuf_sampleAt(d,time_i+j) * sndbuf_sinc(d,(double)j );
1103 *out = (SAMPLE) temp1;
1105 else {
1106 one_over_factor = 1.0 / factor;
1107 for (j= -d->sinc_width + 1; j< d->sinc_width; j++) {
1108 temp1 += sndbuf_sampleAt(d,time_i+j) * one_over_factor * sndbuf_sinc(d,one_over_factor * (double) j );
1110 *out = (SAMPLE) temp1;
1114 void sndbuf_make_sinc( sndbuf_data * d)
1116 int i;
1117 fprintf(stderr, "building sinc table\n" );
1118 double temp,win_freq,win;
1119 win_freq = PI / d->sinc_width / d->sinc_samples_per_zero_crossing;
1120 int tabsize = d->sinc_width * d->sinc_samples_per_zero_crossing;
1122 d->sinc_table = (double *) realloc ( d->sinc_table, tabsize * sizeof(double) );
1123 d->sinc_table[0] = 1.0;
1124 for (i=1;i< tabsize ;i++) {
1125 temp = (double) i * PI / d->sinc_samples_per_zero_crossing;
1126 d->sinc_table[i] = (float)(sin(temp) / temp);
1127 win = 0.5 + 0.5 * cos(win_freq * i);
1128 d->sinc_table[i] *= (float)win;
1130 d->sinc_table_built = true;
1133 inline double sndbuf_linear_interp(double first_number,double second_number,double fraction)
1135 return (first_number + ((second_number - first_number) * fraction));
1138 double sndbuf_t_sinc(sndbuf_data *d, double x)
1140 int low;
1141 double temp,delta;
1142 if ( !d->sinc_table_built ) sndbuf_make_sinc(d);
1143 if (fabs(x)>= d->sinc_width-1)
1144 return 0.0;
1145 else {
1146 temp = fabs(x) * (double) d->sinc_samples_per_zero_crossing;
1147 low = (int)temp; /* these are interpolation steps */
1148 if (d->sinc_use_interp) {
1149 delta = temp - low; /* and can be ommited if desired */
1150 return sndbuf_linear_interp(d->sinc_table[low],d->sinc_table[low + 1],delta);
1152 else return d->sinc_table[low];
1157 double sndbuf_sinc(sndbuf_data * d, double x)
1159 double temp;
1161 if(d->sinc_use_table) return sndbuf_t_sinc(d,x);
1162 else {
1163 if (x==0.0) return 1.0;
1164 else {
1165 temp = PI * x;
1166 return sin(temp) / (temp);
1172 UGEN_TICK sndbuf_tick( t_CKTIME now, void * data, SAMPLE in, SAMPLE * out )
1174 sndbuf_data * d = (sndbuf_data *)data;
1175 if( !d->buffer ) return FALSE;
1177 //we're ticking once per sample ( system )
1178 //curf in samples;
1180 if ( !d->loop && d->curr >= d->eob ) return FALSE;
1182 //calculate frame
1184 if( d->interp == SNDBUF_DROP )
1186 *out = (SAMPLE)( (*(d->curr)) ) ;
1188 else if( d->interp == SNDBUF_INTERP )
1189 { //samplewise linear interp
1190 double alpha = d->curf - floor(d->curf);
1191 *out = (SAMPLE)( (*(d->curr)) ) ;
1192 *out += (float)alpha * ( sndbuf_sampleAt(d, (long)d->curf+1 ) - *out );
1194 else if ( d->interp == SNDBUF_SINC ) {
1195 //do that fancy sinc function!
1196 sndbuf_sinc_interpolate(d, out);
1199 //advance
1200 d->curf += d->rate;
1201 sndbuf_setpos(d, d->curf);
1202 return TRUE;
1206 #if defined(__CK_SNDFILE_NATIVE__)
1207 #include <sndfile.h>
1208 #else
1209 #include "util_sndfile.h"
1210 #endif
1212 #include "util_raw.h"
1215 UGEN_CTRL sndbuf_ctrl_read( t_CKTIME now, void * data, void * value )
1217 sndbuf_data * d = (sndbuf_data *)data;
1218 char * filename = *(char **)value;
1220 if( d->buffer )
1222 delete [] d->buffer;
1223 d->buffer = NULL;
1226 // built in
1227 if( strstr(filename, "special:") )
1229 SAMPLE * rawdata = NULL;
1230 t_CKUINT rawsize = 0;
1231 t_CKUINT srate = 22050;
1233 // which
1234 if( strstr(filename, "special:sinewave") ) {
1235 rawsize = 256; rawdata = NULL;
1237 else if( strstr(filename, "special:ahh") ) {
1238 rawsize = ahh_size; rawdata = ahh_data;
1240 else if( strstr(filename, "special:britestk") ) {
1241 rawsize = britestk_size; rawdata = britestk_data;
1243 else if( strstr(filename, "special:dope") ) {
1244 rawsize = dope_size; rawdata = dope_data;
1246 else if( strstr(filename, "special:eee") ) {
1247 rawsize = eee_size; rawdata = eee_data;
1249 else if( strstr(filename, "special:fwavblnk") ) {
1250 rawsize = fwavblnk_size; rawdata = fwavblnk_data;
1252 else if( strstr(filename, "special:halfwave") ) {
1253 rawsize = halfwave_size; rawdata = halfwave_data;
1255 else if( strstr(filename, "special:impuls10") ) {
1256 rawsize = impuls10_size; rawdata = impuls10_data;
1258 else if( strstr(filename, "special:impuls20") ) {
1259 rawsize = impuls20_size; rawdata = impuls20_data;
1261 else if( strstr(filename, "special:impuls40") ) {
1262 rawsize = impuls40_size; rawdata = impuls40_data;
1264 else if( strstr(filename, "special:mand1") ) {
1265 rawsize = mand1_size; rawdata = mand1_data;
1267 else if( strstr(filename, "special:mandpluk") ) {
1268 rawsize = mandpluk_size; rawdata = mandpluk_data;
1270 else if( strstr(filename, "special:marmstk1") ) {
1271 rawsize = marmstk1_size; rawdata = marmstk1_data;
1273 else if( strstr(filename, "special:ooo") ) {
1274 rawsize = ooo_size; rawdata = ooo_data;
1276 else if( strstr(filename, "special:peksblnk") ) {
1277 rawsize = peksblnk_size; rawdata = peksblnk_data;
1279 else if( strstr(filename, "special:ppksblnk") ) {
1280 rawsize = ppksblnk_size; rawdata = ppksblnk_data;
1282 else if( strstr(filename, "special:silence") ) {
1283 rawsize = silence_size; rawdata = silence_data;
1285 else if( strstr(filename, "special:sineblnk") ) {
1286 rawsize = sineblnk_size; rawdata = sineblnk_data;
1288 else if( strstr(filename, "special:sinewave") ) {
1289 rawsize = sinewave_size; rawdata = sinewave_data;
1291 else if( strstr(filename, "special:snglpeak") ) {
1292 rawsize = snglpeak_size; rawdata = snglpeak_data;
1294 else if( strstr(filename, "special:twopeaks") ) {
1295 rawsize = twopeaks_size; rawdata = twopeaks_data;
1297 else if( strstr(filename, "special:glot_ahh") ) {
1298 rawsize = glot_ahh_size; rawdata = glot_ahh_data; srate = 44100;
1300 else if( strstr(filename, "special:glot_eee") ) {
1301 rawsize = glot_eee_size; rawdata = glot_eee_data; srate = 44100;
1303 else if( strstr(filename, "special:glot_ooo") ) {
1304 rawsize = glot_ooo_size; rawdata = glot_ooo_data; srate = 44100;
1306 else if( strstr(filename, "special:glot_pop") ) {
1307 rawsize = glot_pop_size; rawdata = glot_pop_data; srate = 44100;
1310 d->num_frames = rawsize;
1311 d->num_channels = 1;
1312 d->chan = 0;
1313 d->samplerate = srate;
1314 d->num_samples = rawsize;
1316 if( rawdata ) {
1317 d->buffer = new SAMPLE[rawsize+1];
1318 for( t_CKUINT j = 0; j < rawsize; j++ ) {
1319 d->buffer[j] = (SAMPLE)rawdata[j]/(SAMPLE)SHRT_MAX;
1322 else if( strstr(filename, "special:sinewave") ) {
1323 d->buffer = new SAMPLE[rawsize+1];
1324 for( t_CKUINT j = 0; j < rawsize; j++ )
1325 d->buffer[j] = sin(2*PI*j/rawsize);
1327 else {
1328 fprintf( stderr, "[chuck](via sndbuf): cannot load '%s'\n", filename );
1329 return;
1332 d->buffer[rawsize] = d->buffer[0];
1334 // read file
1335 else
1337 struct stat s;
1338 if( stat( filename, &s ) )
1340 fprintf( stderr, "[chuck](via sndbuf): cannot stat file '%s'...\n", filename );
1341 return;
1344 SF_INFO info;
1345 info.format = 0;
1346 char * format = strrchr ( filename, '.');
1347 if ( format && strcmp ( format, ".raw" ) == 0 ) {
1348 fprintf( stderr, "[chuck](via sndbuf) %s :: type is '.raw'...\n assuming 16 bit signed mono (PCM)\n", filename );
1349 info.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16 | SF_ENDIAN_CPU ;
1350 info.channels = 1;
1351 info.samplerate = 44100;
1354 SNDFILE* file = sf_open(filename, SFM_READ, &info);
1355 int er = sf_error(file);
1356 if(er) fprintf( stderr, "[chuck](via sndbuf): sndfile error '%i' opening '%s'...\n", er, filename );
1357 int size = info.channels * info.frames;
1358 d->buffer = new SAMPLE[size+1];
1359 d->chan = 0;
1360 d->num_frames = info.frames;
1361 d->num_channels = info.channels;
1362 sf_seek(file, 0, SEEK_SET );
1363 d->num_samples = sf_read_float(file, d->buffer, size) ;
1364 // fprintf ( stderr, "soundfile:read %d samples %d %d\n", d->num_samples, file->mode, file->error ) ;
1365 d->samplerate = info.samplerate;
1367 if( d->num_samples != size )
1369 fprintf( stderr, "[chuck](via sndbuf): read %d rather than %d frames from %s\n",
1370 d->num_samples, size, filename );
1371 return;
1373 // fprintf(stderr, "read file : %d frames %d chan %d rate\n", d->num_frames, d->num_channels, d->samplerate );
1376 // d->interp = SNDBUF_INTERP;
1377 d->sampleratio = (double)d->samplerate / (double)g_srate;
1378 d->curr = d->buffer;
1379 d->eob = d->buffer + d->num_samples;
1382 UGEN_CTRL sndbuf_ctrl_write( t_CKTIME now, void * data, void * value )
1384 sndbuf_data * d = (sndbuf_data *)data;
1385 char * filename = *(char **)value;
1387 if( d->buffer )
1389 delete [] d->buffer;
1390 d->buffer = NULL;
1393 struct stat s;
1394 if( stat( filename, &s ) )
1396 fprintf( stderr, "[chuck](via sndbuf): cannot stat file '%s'...\n", filename );
1397 return;
1400 d->curr = d->buffer;
1401 d->eob = d->buffer + d->num_samples;
1405 UGEN_CTRL sndbuf_ctrl_rate( t_CKTIME now, void * data, void * value )
1407 sndbuf_data * d = ( sndbuf_data * ) data;
1408 t_CKFLOAT rate = * (t_CKFLOAT *) value; // rate
1409 d->rate = rate * d->sampleratio;
1412 UGEN_CGET sndbuf_cget_rate( t_CKTIME now, void * data, void * out )
1414 sndbuf_data * d = (sndbuf_data *)data;
1415 SET_NEXT_FLOAT( out, d->rate / d->sampleratio );
1419 UGEN_CTRL sndbuf_ctrl_freq( t_CKTIME now, void * data, void * value )
1421 sndbuf_data * d = ( sndbuf_data * ) data;
1422 t_CKFLOAT freq = * (t_CKFLOAT *) value; //hz
1424 d->rate = ( freq * (double) d->num_frames / (double) g_srate );
1427 UGEN_CGET sndbuf_cget_freq( t_CKTIME now, void * data, void * out )
1429 sndbuf_data * d = (sndbuf_data *)data;
1430 SET_NEXT_FLOAT( out, d->rate * (t_CKFLOAT) g_srate / ( (t_CKFLOAT) d->num_frames ) );
1433 UGEN_CTRL sndbuf_ctrl_phase( t_CKTIME now, void * data, void * value ) {
1434 sndbuf_data * d = ( sndbuf_data * ) data;
1435 t_CKFLOAT phase = * (t_CKFLOAT *) value;
1436 sndbuf_setpos(d, phase * (double)d->num_frames);
1439 UGEN_CGET sndbuf_cget_phase( t_CKTIME now, void * data, void * out )
1441 sndbuf_data * d = (sndbuf_data *)data;
1442 SET_NEXT_FLOAT( out, (t_CKFLOAT) d->curf / (t_CKFLOAT)d->num_frames );
1445 UGEN_CTRL sndbuf_ctrl_channel( t_CKTIME now, void * data, void * value )
1447 sndbuf_data * d = ( sndbuf_data * ) data;
1448 unsigned int chan = * (int *) value;
1449 if ( chan >= 0 && chan < d->num_channels ) {
1450 d->chan = chan;
1454 UGEN_CGET sndbuf_cget_channel( t_CKTIME now, void * data, void * out )
1456 sndbuf_data * d = (sndbuf_data *)data;
1457 SET_NEXT_INT( out, d->chan );
1460 UGEN_CTRL sndbuf_ctrl_pos( t_CKTIME now, void * data, void * value )
1462 sndbuf_data * d = ( sndbuf_data * ) data;
1463 int pos = * (int *) value;
1464 sndbuf_setpos(d, pos);
1467 UGEN_CGET sndbuf_cget_pos( t_CKTIME now, void * data, void * out )
1469 sndbuf_data * d = (sndbuf_data *)data;
1470 SET_NEXT_INT( out, (int) sndbuf_getpos(d) );
1473 UGEN_CTRL sndbuf_ctrl_interp( t_CKTIME now, void * data, void * value )
1475 sndbuf_data * d = ( sndbuf_data * ) data;
1476 int interp = * (int *) value;
1477 d->interp = interp;
1480 UGEN_CGET sndbuf_cget_interp( t_CKTIME now, void * data, void * out )
1482 sndbuf_data * d = (sndbuf_data *)data;
1483 SET_NEXT_INT( out, d->interp );
1487 UGEN_CTRL sndbuf_ctrl_phase_offset( t_CKTIME now, void * data, void * value )
1489 sndbuf_data * d = (sndbuf_data *)data;
1490 t_CKFLOAT phase_offset = * (t_CKFLOAT *) value;
1491 sndbuf_setpos(d, d->curf + phase_offset * (t_CKFLOAT)d->num_frames );
1494 UGEN_CGET sndbuf_cget_samples( t_CKTIME now, void * data, void * out )
1496 sndbuf_data * d = (sndbuf_data *)data;
1497 SET_NEXT_INT( out, d->num_frames );
1500 UGEN_CGET sndbuf_cget_length( t_CKTIME now, void * data, void * out )
1502 sndbuf_data * d = (sndbuf_data *)data;
1503 SET_NEXT_DUR( out, (t_CKDUR)d->num_frames );
1506 UGEN_CGET sndbuf_cget_channels( t_CKTIME now, void * data, void * out )
1508 sndbuf_data * d = (sndbuf_data *)data;
1509 SET_NEXT_INT( out, d->num_channels );