1 /*----------------------------------------------------------------------------
2 ChucK Concurrent, On-the-fly Audio Programming Language
3 Compiler and Virtual Machine
5 Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6 http://chuck.cs.princeton.edu/
7 http://soundlab.cs.princeton.edu/
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
32 //-----------------------------------------------------------------------------
46 //-----------------------------------------------------------------------------
49 //-----------------------------------------------------------------------------
50 DLL_QUERY
xxx_query( Chuck_DL_Query
* QUERY
)
52 g_srate
= QUERY
->srate
;
54 //! \section audio output
57 //! digital/analog converter
58 //! abstraction for underlying audio output device
59 QUERY
->ugen_add( QUERY
, "dac", NULL
);
61 QUERY
->ugen_func( QUERY
, NULL
, NULL
, dac_tick
, NULL
);
64 //! analog/digital converter
65 //! abstraction for underlying audio input device
66 QUERY
->ugen_add( QUERY
, "adc", NULL
);
68 QUERY
->ugen_func( QUERY
, NULL
, NULL
, dac_tick
, NULL
);
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
);
76 QUERY
->ugen_func( QUERY
, NULL
, NULL
, bunghole_tick
, NULL
);
79 //! sample rate sample sucker
80 //! ( like dac, ticks ugens, but no more )
81 QUERY
->ugen_add( QUERY
, "bunghole", NULL
);
83 QUERY
->ugen_func( QUERY
, NULL
, NULL
, bunghole_tick
, NULL
);
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
);
92 QUERY
->ugen_func( QUERY
, gain_ctor
, gain_dtor
, gain_tick
, NULL
);
94 QUERY
->ugen_ctrl( QUERY
, gain_ctrl_value
, gain_cget_value
, "float", "value" ); //! set gain ( all ugen's have this )
96 noise n => gain g => dac;
99 while( true ) { 100::ms => now; }
102 //! \section wave forms
105 //! white noise generator
106 //! see \example noise.ck \example powerup.ck
107 QUERY
->ugen_add( QUERY
, "noise", NULL
);
109 QUERY
->ugen_func( QUERY
, NULL
, NULL
, noise_tick
, NULL
);
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" );
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
);
123 QUERY
->ugen_func( QUERY
, impulse_ctor
, impulse_dtor
, impulse_tick
, NULL
);
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
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
);
142 QUERY
->ugen_func( QUERY
, step_ctor
, step_dtor
, step_tick
, NULL
);
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
150 // square wave using step
152 -amp => amp => s.next;
160 //! half wave rectifier
161 //! for half-wave rectification.
162 QUERY
->ugen_add( QUERY
, "halfrect", NULL
);
164 QUERY
->ugen_func( QUERY
, NULL
, NULL
, halfrect_tick
, NULL
);
167 //! full wave rectifier
168 QUERY
->ugen_add( QUERY
, "fullrect", NULL
);
170 QUERY
->ugen_func( QUERY
, NULL
, NULL
, fullrect_tick
, NULL
);
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
);
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
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
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
);
202 QUERY
->ugen_func( QUERY
, sndbuf_ctor
, sndbuf_dtor
, sndbuf_tick
, NULL
);
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
225 //-----------------------------------------------------------------------------
226 // name: noise_tick()
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
;
236 enum { NOISE_WHITE
=0, NOISE_PINK
, NOISE_BROWN
, NOISE_FBM
, NOISE_FLIP
, NOISE_XOR
};
259 scale
= 2.0 / (double) RAND_MAX
;
262 int randt
= RAND_MAX
;
264 fprob
= (int) ( (double)RAND_MAX
* 1.0 / 32.0 );
265 while ( randt
> 0 ) {
269 fprintf(stderr
, "random bits - %d", rand_bits
);
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
;
299 return noise_tick(now
,data
,in
,out
);
302 return d
->pink_tick(out
);
305 return d
->brown_tick(out
);
308 return d
->xor_tick(out
);
311 return d
->flip_tick(out
);
314 return d
->fbm_tick(out
);
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
);
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 ) );
331 fprintf( stderr
, "scale %f %f %d %d \n", scale
, bias
, RAND_MAX
, pink_depth
+ 1 );
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
;
347 *out
= bias
+ scale
* ( rand() + last
);
349 if ( pink_rand
) counter
= rand();
354 CNoise_Data::xor_tick( SAMPLE
* out
) {
357 for ( int i
= 0; i
< rand_bits
; i
++ )
358 if ( rand() <= fprob
)
361 *out
= bias
+ scale
* (SAMPLE
)last
;
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
;
376 CNoise_Data::brown_tick( SAMPLE
* out
) {
377 //brownian noise function..later!
383 CNoise_Data::fbm_tick( SAMPLE
* out
) {
384 //brownian noise function..later!
390 CNoise_Data::setMode( char * c
) {
391 if ( strcmp ( c
, "white" ) == 0 ) {
392 fprintf(stderr
, "white noise\n");
394 scale
= 2.0 / (t_CKFLOAT
)RAND_MAX
;
397 if ( strcmp ( c
, "pink" ) == 0 ) {
398 fprintf(stderr
, "pink noise\n");
400 scale
= 2.0 / (double)(RAND_MAX
* ( pink_depth
+ 1 ) );
403 if ( strcmp ( c
, "flip" ) == 0) {
404 fprintf(stderr
, "bitflip noise\n");
406 scale
= 2.0 / (t_CKFLOAT
)RAND_MAX
;
409 if ( strcmp ( c
, "xor" ) == 0) {
410 fprintf(stderr
, "xor noise\n");
412 scale
= 2.0 / (t_CKFLOAT
)RAND_MAX
;
415 if ( strcmp ( c
, "brown" ) == 0) {
416 fprintf(stderr
, "brownian noise\n");
418 scale
= 2.0 / (t_CKFLOAT
)RAND_MAX
;
421 if ( strcmp ( c
, "fbm" ) == 0) {
422 fprintf(stderr
, "fbm noise\n");
424 scale
= 2.0 / (t_CKFLOAT
)RAND_MAX
;
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
;
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
449 //-----------------------------------------------------------------------------
454 Pulse_Data( ) { value
= 1.0f
; when
= 0; }
458 //-----------------------------------------------------------------------------
459 // name: impulse_ctor()
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()
474 //-----------------------------------------------------------------------------
475 UGEN_DTOR
impulse_dtor( t_CKTIME now
, void * data
)
478 delete (Pulse_Data
*)data
;
484 //-----------------------------------------------------------------------------
485 // name: impulse_tick()
487 //-----------------------------------------------------------------------------
488 UGEN_TICK
impulse_tick( t_CKTIME now
, void * data
, SAMPLE in
, SAMPLE
* out
)
490 Pulse_Data
* d
= (Pulse_Data
*)data
;
504 //-----------------------------------------------------------------------------
505 // name: impulse_ctrl_value()
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
;
516 //-----------------------------------------------------------------------------
517 // name: impulse_cget_value()
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 //-----------------------------------------------------------------------------
531 //-----------------------------------------------------------------------------
532 UGEN_CTOR
step_ctor( t_CKTIME now
)
534 // return data to be used later
535 return new SAMPLE( 1.0f
);
539 //-----------------------------------------------------------------------------
542 //-----------------------------------------------------------------------------
543 UGEN_DTOR
step_dtor( t_CKTIME now
, void * data
)
546 delete (SAMPLE
*)data
;
550 //-----------------------------------------------------------------------------
553 //-----------------------------------------------------------------------------
554 UGEN_TICK
step_tick( t_CKTIME now
, void * data
, SAMPLE in
, SAMPLE
* out
)
556 SAMPLE
* d
= (SAMPLE
*)data
;
563 //-----------------------------------------------------------------------------
564 // name: step_ctrl_value()
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()
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 //-----------------------------------------------------------------------------
588 //-----------------------------------------------------------------------------
589 UGEN_CTOR
gain_ctor( t_CKTIME now
)
591 // return data to be used later
592 return new SAMPLE( 1.0f
);
596 //-----------------------------------------------------------------------------
599 //-----------------------------------------------------------------------------
600 UGEN_DTOR
gain_dtor( t_CKTIME now
, void * data
)
603 delete (SAMPLE
*)data
;
607 //-----------------------------------------------------------------------------
610 //-----------------------------------------------------------------------------
611 UGEN_TICK
gain_tick( t_CKTIME now
, void * data
, SAMPLE in
, SAMPLE
* out
)
613 SAMPLE
* d
= (SAMPLE
*)data
;
620 //-----------------------------------------------------------------------------
621 // name: gain_ctrl_value()
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()
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()
645 //-----------------------------------------------------------------------------
646 UGEN_TICK
halfrect_tick( t_CKTIME now
, void * data
, SAMPLE in
, SAMPLE
* out
)
648 *out
= in
> 0.0f
? in
: 0.0f
;
655 //-----------------------------------------------------------------------------
656 // name: fullrect_tick()
658 //-----------------------------------------------------------------------------
659 UGEN_TICK
fullrect_tick( t_CKTIME now
, void * data
, SAMPLE in
, SAMPLE
* out
)
661 *out
= in
>= 0.0f
? in
: -in
;
668 //-----------------------------------------------------------------------------
669 // name: zerox_ctor()
671 //-----------------------------------------------------------------------------
672 UGEN_CTOR
zerox_ctor( t_CKTIME now
)
674 return new SAMPLE( 0.0f
);
678 //-----------------------------------------------------------------------------
679 // name: zerox_dtor()
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()
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
);
706 //-----------------------------------------------------------------------------
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
716 //-----------------------------------------------------------------------------
717 // name: bunghole_tick
719 //-----------------------------------------------------------------------------
720 UGEN_TICK
bunghole_tick( t_CKTIME now
, void * data
, SAMPLE in
, SAMPLE
* out
)
735 double writepos
; // relative to readpos
739 double writeoff_start
;
740 double writeoff_target
;
741 double writeoff_target_time
; //target time
742 double writeoff_window_time
; //time we started shift
745 double writeoff_last
;
754 bufsize
= 2 * g_srate
;
755 buffer
= ( SAMPLE
* ) realloc ( NULL
, sizeof ( SAMPLE
) * bufsize
);
758 for ( i
= 0 ; i
< bufsize
; i
++ ) buffer
[i
] = 0;
759 for ( i
= 0 ; i
< 3 ; i
++ ) { acoeff
[i
] = 0; bcoeff
[i
] = 0; }
767 writeoff_last
= 1000.0;
768 writeoff_start
= 1000.0;
769 writeoff_target
= 1000.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
;
788 UGEN_PMSG
delayp_pmsg( t_CKTIME now
, void * data
, const char * msg
, void * value
)
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
;
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
;
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
;
837 //output should go through a dc blocking filter, for cases where
838 //we are zipping around in the buffer leaving a fairly constant
842 int rpos
= ( (int) d
->readpos
) % d
->bufsize
;
844 // *out = d->buffer[rpos];
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
863 while ( d
->readpos
> d
->bufsize
) d
->readpos
-= d
->bufsize
;
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
);
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
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 //-----------------------------------------------------------------------------
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 */
950 t_CKUINT num_samples
;
951 t_CKUINT num_channels
;
963 bool sinc_table_built
;
965 bool sinc_use_interp
;
966 int sinc_samples_per_zero_crossing
;
968 double * sinc_table
;
972 interp
= SNDBUF_INTERP
;
987 sinc_table_built
= false;
988 sinc_use_table
= USE_TABLE
;
989 sinc_use_interp
= USE_INTERP
;
991 sinc_samples_per_zero_crossing
= SAMPLES_PER_ZERO_CROSSING
;
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
;
1016 inline void sndbuf_setpos(sndbuf_data
*d
, double pos
)
1018 if( !d
->buffer
) return;
1022 //set curf within bounds
1026 while ( d
->curf
>= d
->num_frames
) d
->curf
-= d
->num_frames
;
1027 while ( d
->curf
< 0 ) d
->curf
+= d
->num_frames
;
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
) {
1041 int nf
= d
->num_frames
;
1043 while ( pos
>= nf
) pos
-= nf
;
1044 while ( pos
< 0 ) pos
+= nf
;
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
)
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;
1095 long time_i
= (long)time_now
;
1097 //bounds checking now in sampleAt function...
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
;
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
)
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
)
1142 if ( !d
->sinc_table_built
) sndbuf_make_sinc(d
);
1143 if (fabs(x
)>= d
->sinc_width
-1)
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
)
1161 if(d
->sinc_use_table
) return sndbuf_t_sinc(d
,x
);
1163 if (x
==0.0) return 1.0;
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 )
1180 if ( !d
->loop
&& d
->curr
>= d
->eob
) return FALSE
;
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
);
1201 sndbuf_setpos(d
, d
->curf
);
1206 #if defined(__CK_SNDFILE_NATIVE__)
1207 #include <sndfile.h>
1209 #include "util_sndfile.h"
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
;
1222 delete [] d
->buffer
;
1227 if( strstr(filename
, "special:") )
1229 SAMPLE
* rawdata
= NULL
;
1230 t_CKUINT rawsize
= 0;
1231 t_CKUINT srate
= 22050;
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;
1313 d
->samplerate
= srate
;
1314 d
->num_samples
= rawsize
;
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
);
1328 fprintf( stderr
, "[chuck](via sndbuf): cannot load '%s'\n", filename
);
1332 d
->buffer
[rawsize
] = d
->buffer
[0];
1338 if( stat( filename
, &s
) )
1340 fprintf( stderr
, "[chuck](via sndbuf): cannot stat file '%s'...\n", filename
);
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
;
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];
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
);
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
;
1389 delete [] d
->buffer
;
1394 if( stat( filename
, &s
) )
1396 fprintf( stderr
, "[chuck](via sndbuf): cannot stat file '%s'...\n", filename
);
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
) {
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
;
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
);