2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 // some basic physical modeling ugens - julian rohrhuber 1/04
22 // these are very simple implementations with cartoonification aspects.
25 #include "SC_PlugIn.h"
27 static InterfaceTable
*ft
;
29 //////////////////////////////////////////////////////////////////////////////////////////////////
32 struct Spring
: public Unit
38 struct Friction : public Unit
46 struct Ball
: public Unit
53 struct TBall
: public Unit
65 void Spring_Ctor(Spring
*unit
);
66 void Spring_next(Spring
*unit
, int inNumSamples
);
68 //void Friction_Ctor(Friction *unit);
69 //void Friction_next(Friction *unit, int inNumSamples);
71 void Ball_Ctor(Ball
*unit
);
72 void Ball_next(Ball
*unit
, int inNumSamples
);
74 void TBall_Ctor(TBall
*unit
);
75 void TBall_next(TBall
*unit
, int inNumSamples
);
78 ////////////////////////////////////////////////////////////////////////////////////////////////////////
81 void Spring_Ctor(Spring
*unit
)
90 // in, spring, damping
92 void Spring_next(Spring
*unit
, int inNumSamples
)
94 float pos
= unit
->m_pos
;
95 float vel
= unit
->m_vel
;
96 float *out
= ZOUT(0); // out force
97 float *in
= ZIN(0); // in force
98 float spring
= ZIN0(1); // spring constant
99 float damping
= 1.f
- ZIN0(2);// damping
101 float rc
= SAMPLERATE
;
104 float force
= ZXP(in
) * c
- pos
* spring
;
105 vel
= (force
+ vel
) * damping
;
107 ZXP(out
) = force
* rc
;
115 //////////////////////////////////////////////////////////////////////////////////////////
118 void Friction_Ctor(Friction *unit)
120 SETCALC(Friction_next);
124 Friction_next(unit, 1);
128 // in, spring, damping
130 void Friction_next(Friction *unit, int inNumSamples)
132 float pos = unit->m_pos;
133 float vel = unit->m_vel;
134 int state = unit->m_state;
136 void Index_next_a(Index *unit, int inNumSamples)
140 float *table = bufData;
141 int32 maxindex = tableSize - 1;
143 float *out = ZOUT(0);
147 int32 index = (int32)ZXP(in);
148 index = sc_clip(index, 0, maxindex);
149 ZXP(out) = table[index];
155 float *out = ZOUT(0); // out force
156 float *in = ZIN(0); // in displacement
157 float spring = ZIN0(1); // spring constant
158 float damping = 1.f - ZIN0(2); // friction -> replace by buffer number for friction table
160 float rc = SAMPLERATE;
163 float inpos = ZXP(in) * c;
164 float force = inpos + pos * spring;
165 state = (vel > damping) ? 1 : 0; // friction table here
173 ZXP(out) = force * rc;
178 unit->m_state = state;
183 float fbufnum = ZIN0(0); \
184 if (fbufnum != unit->m_fbufnum) { \
185 uint32 bufnum = (uint32)fbufnum; \
186 World *world = unit->mWorld; \
187 if (bufnum >= world->mNumSndBufs) bufnum = 0; \
188 unit->m_buf = world->mSndBufs + bufnum; \
190 SndBuf *buf = unit->m_buf; \
192 ClearUnitOutputs(unit, inNumSamples); \
196 float *bufData __attribute__((__unused__)) = buf->data; \
198 ClearUnitOutputs(unit, inNumSamples); \
201 int tableSize = buf->samples;
204 //////////////////////////////////////////////////////////////////////////////////////////
207 void Ball_Ctor(Ball
*unit
)
211 unit
->m_pos
= ZIN0(0);
212 unit
->m_prev
= ZIN0(0);
217 void Ball_next(Ball
*unit
, int inNumSamples
)
219 float *out
= ZOUT(0);
220 float *in
= ZIN(0); // floor position
221 float g_in
= ZIN0(1); // gravity
222 float damping
= 1 - ZIN0(2); // damping
223 float k
= ZIN0(3); // friction
225 float pos
= unit
->m_pos
;
226 float vel
= unit
->m_vel
;
227 float prev_floor
= unit
->m_prev
;
229 float maxvel
= c
* 1000.f
;
230 float minvel
= 0.f
- maxvel
;
231 float inter
= c
* 1000.f
;
232 RGen
& rgen
= *unit
->mParent
->mRGen
;
235 k
*= g_in
; // stickyness proportional to gravity
236 #else //#ifdef _MSC_VER
237 k
= (double) k
* (double) g_in
; // stickyness proportional to gravity
238 #endif //#ifdef _MSC_VER
241 float floor
= ZXP(in
);
246 float dist
= pos
- floor
;
247 floorvel
= floor
- prev_floor
;
248 floorvel
= sc_clip(floorvel
, minvel
, maxvel
);
249 float vel_diff
= floorvel
- vel
;
250 if(sc_abs(dist
) < k
) { // sticky friction: maybe vel dependant?
252 if(sc_abs(dist
) < (k
*0.005)) {
256 vel
= vel_diff
* inter
+ vel
;
257 pos
= (floor
- pos
) * inter
+ pos
;
260 } else if(dist
<= 0.f
) {
266 dither
= rgen
.frand() * 0.00005f
* g_in
; // dither to reduce jitter
267 //if(sc_abs(dist) < 0.000001) { vel += dither; }
276 unit
->m_prev
= prev_floor
;
280 //////////////////////////////////////////////////////////////////////////////////////////
282 void TBall_Ctor(TBall
*unit
)
286 unit
->m_pos
= ZIN0(0);
287 unit
->m_prev
= ZIN0(0);
291 void TBall_next(TBall
*unit
, int inNumSamples
)
293 float *out
= ZOUT(0);
294 float *in
= ZIN(0); // floor position
295 float g_in
= ZIN0(1); // gravity
296 float damping
= 1 - ZIN0(2);// damping
297 float k
= ZIN0(3); // friction
299 double pos
= unit
->m_pos
;
300 float vel
= unit
->m_vel
;
301 double prev_floor
= unit
->m_prev
;
303 float maxvel
= c
* 1000.f
;
304 float minvel
= 0.f
- maxvel
;
305 float inter
= c
* 10000.f
;
306 RGen
& rgen
= *unit
->mParent
->mRGen
;
309 k
*= g_in
; // stickyness proportional to gravity
310 #else //#ifdef _MSC_VER
311 k
= (double) k
* (double) g_in
; // stickyness proportional to gravity
312 #endif //#ifdef _MSC_VER
315 double floor
= ZXP(in
);
321 double dist
= pos
- floor
;
322 floorvel
= floor
- prev_floor
;
323 floorvel
= sc_clip(floorvel
, minvel
, maxvel
);
324 float vel_diff
= floorvel
- vel
;
325 if(sc_abs(dist
) < k
) { // sticky friction: vel dependant?
326 if(sc_abs(dist
) < (k
*0.005)) {
330 vel
= vel_diff
* inter
+ vel
;
331 pos
= (floor
- pos
) * inter
+ pos
;
333 } else if(dist
<= 0.f
) {
335 vel
= floorvel
- vel
;
338 dither
= rgen
.frand() * 0.001f
* g_in
; // dither to reduce sampling jitter
339 //if(sc_abs(dist) < 0.003) { vel += dither; }
349 unit
->m_prev
= prev_floor
;
355 ////////////////////////////////////////////////////////////////////////////////////////////////////////
357 PluginLoad(PhysicalModeling
)
361 DefineSimpleUnit(Spring
);
362 // DefineSimpleUnit(Friction);
363 DefineSimpleUnit(Ball
);
364 DefineSimpleUnit(TBall
);