*** empty log message ***
[chuck-blob.git] / exile / v1 / src / chuck_ugen.cpp
bloba608025a9514cbc1fb7f0ba126b4395452c3520e
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 // name: chuck_ugen.h
27 // desc: chuck unit generator interface
29 // authors: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
31 // date: Spring 2004
32 //-----------------------------------------------------------------------------
33 #include "chuck_ugen.h"
34 #include "chuck_vm.h"
35 using namespace std;
40 //-----------------------------------------------------------------------------
41 // name: Chuck_UGen()
42 // desc: constructor
43 //-----------------------------------------------------------------------------
44 Chuck_UGen::Chuck_UGen()
46 this->init();
52 //-----------------------------------------------------------------------------
53 // name: ~Chuck_UGen()
54 // desc: ...
55 //-----------------------------------------------------------------------------
56 Chuck_UGen::~Chuck_UGen()
58 this->done();
64 //-----------------------------------------------------------------------------
65 // name: init()
66 // desc: ...
67 //-----------------------------------------------------------------------------
68 void Chuck_UGen::init()
70 // super init
71 Chuck_VM_Object::init();
73 ctor = NULL;
74 dtor = NULL;
75 tick = NULL;
76 pmsg = NULL;
78 m_num_src = 0;
79 m_num_dest = 0;
80 m_max_src = 0xffffffff;
81 m_time = 0;
82 m_valid = TRUE;
83 m_sum = 0.0f;
84 m_current = 0.0f;
85 m_last = 0.0f;
86 m_op = UGEN_OP_TICK;
87 m_gain = 1.0f;
89 state = NULL;
95 //-----------------------------------------------------------------------------
96 // name: done()
97 // desc: ...
98 //-----------------------------------------------------------------------------
99 void Chuck_UGen::done()
101 if( this->shred )
102 shred->remove( this );
104 assert( this->m_ref_count == 0 );
106 this->remove_all();
107 m_valid = FALSE;
113 //-----------------------------------------------------------------------------
114 // name: set_max_src()
115 // dsec: ...
116 //-----------------------------------------------------------------------------
117 t_CKBOOL Chuck_UGen::set_max_src( t_CKUINT num )
119 m_max_src = num;
120 return TRUE;
126 //-----------------------------------------------------------------------------
127 // name: get_num_src()
128 // desc: ...
129 //-----------------------------------------------------------------------------
130 t_CKUINT Chuck_UGen::get_num_src()
132 return m_num_src;
138 //-----------------------------------------------------------------------------
139 // name: add()
140 // dsec: ...
141 //-----------------------------------------------------------------------------
142 t_CKBOOL Chuck_UGen::add( Chuck_UGen * src )
144 if( m_num_src >= m_max_src )
145 return FALSE;
147 // append
148 m_num_src++;
149 m_src_list.push_back( src );
150 src->add_ref();
151 src->add_by( this );
153 return TRUE;
159 //-----------------------------------------------------------------------------
160 // name: add_by()
161 // dsec: ...
162 //-----------------------------------------------------------------------------
163 void Chuck_UGen::add_by( Chuck_UGen * dest )
165 // append
166 m_num_dest++;
167 m_dest_list.push_back( dest );
173 //-----------------------------------------------------------------------------
174 // name: remove()
175 // dsec: ...
176 //-----------------------------------------------------------------------------
177 t_CKBOOL Chuck_UGen::remove( Chuck_UGen * src )
179 if( m_num_src == 0 )
180 return FALSE;
182 // remove
183 for( unsigned int i = 0; i < m_num_src; i++ )
184 if( m_src_list[i] == src )
186 for( unsigned int j = i+1; j < m_num_src; j++ )
187 m_src_list[j-1] = m_src_list[j];
189 m_src_list[--m_num_src] = NULL;
190 m_src_list.pop_back();
191 src->remove_by( this );
192 src->release();
195 return TRUE;
201 //-----------------------------------------------------------------------------
202 // name: remove_by()
203 // dsec: ...
204 //-----------------------------------------------------------------------------
205 void Chuck_UGen::remove_by( Chuck_UGen * dest )
207 // remove
208 for( unsigned int i = 0; i < m_num_dest; i++ )
209 if( m_dest_list[i] == dest )
211 for( unsigned int j = i+1; j < m_num_dest; j++ )
212 m_dest_list[j-1] = m_dest_list[j];
214 m_dest_list[--m_num_dest] = NULL;
215 m_dest_list.pop_back();
222 //-----------------------------------------------------------------------------
223 // name: add()
224 // dsec: ...
225 //-----------------------------------------------------------------------------
226 void Chuck_UGen::remove_all( )
228 assert( this->m_num_dest == 0 );
230 // remove
231 for( unsigned int i = 0; i < m_num_src; i++ )
232 m_src_list[i]->release();
234 m_num_src = 0;
235 m_src_list.clear();
241 //-----------------------------------------------------------------------------
242 // name: disconnect()
243 // desc: ...
244 //-----------------------------------------------------------------------------
245 t_CKBOOL Chuck_UGen::disconnect( t_CKBOOL recursive )
247 // remove
248 for( unsigned int i = 0; i < m_num_dest; i++ )
249 m_dest_list[i]->remove( this );
251 m_num_dest = 0;
252 m_dest_list.clear();
254 // disconnect src too?
255 if( recursive )
256 this->remove_all();
258 return TRUE;
264 //-----------------------------------------------------------------------------
265 // name: tick()
266 // dsec: ...
267 //-----------------------------------------------------------------------------
268 t_CKBOOL Chuck_UGen::system_tick( t_CKTIME now )
270 if( m_time >= now )
271 return m_valid;
273 m_last = m_current;
274 // inc time
275 m_time = now;
276 m_sum = m_num_src && m_src_list[0]->system_tick( now ) ?
277 m_src_list[0]->m_current : 0.0f;
279 // tick the src list
280 for( t_CKUINT i = 1; i < m_num_src; i++ )
281 if( m_src_list[i]->system_tick( now ) )
283 if( m_op <= 1 )
284 m_sum += m_src_list[i]->m_current;
285 else // special ops
287 switch( m_op )
289 case 2: m_sum -= m_src_list[i]->m_current; break;
290 case 3: m_sum *= m_src_list[i]->m_current; break;
291 case 4: m_sum /= m_src_list[i]->m_current; break;
292 default: m_sum += m_src_list[i]->m_current; break;
297 if( m_op > 0 ) // UGEN_OP_TICK
299 // tick the ugen
300 if( tick ) m_valid = tick( now, state, m_sum, &m_current );
301 if( !m_valid ) m_current = 0.0f;
302 m_current *= m_gain;
303 return m_valid;
305 else if( m_op < 0 ) // UGEN_OP_PASS
307 // pass through
308 m_current = m_sum * m_gain;
309 return TRUE;
311 else // UGEN_OP_STOP
312 m_current = 0.0f;
314 return TRUE;