1 #include <stdio.h>
2
3 #include "G-Force_Proj.h"
4
5 #include "WaveShape.h"
6
7 #include <math.h>
8 #include <stdlib.h>
9 #include <time.h>
10
11 #include "ArgList.h"
12 #include "UtilStr.h"
13 #include "EgOSUtils.h"
14 #include "PixPort.h"
15
16
17 long WaveShape::sXY[ 2 * MAX_WAVES_PER_SHAPE ];
18 long WaveShape::sStartXY[ 2 * MAX_WAVES_PER_SHAPE ];
19 float WaveShape::sS;
20
21
WaveShape(float * inTPtr)22 WaveShape::WaveShape( float* inTPtr ) {
23 UtilStr str;
24
25 mNumWaves = 0;
26 mMouseX = 0;
27 mMouseY = 0;
28
29 mNumFFTBins = 255;
30
31 mDict.AddVar( "S", &sS );
32 mDict.AddVar( "T", inTPtr );
33 mDict.AddVar( "NUM_SAMPLE_BINS", &mNumSampleBins );
34 // FIXME, use fft here!
35 mDict.AddVar( "NUM_FFT_BINS", &mNumFFTBins );
36 mDict.AddVar( "MOUSEX", &mMouseX );
37 mDict.AddVar( "MOUSEY", &mMouseY );
38
39 mTPtr = inTPtr;
40 mPI = 3.14159265358979;
41
42 mDict.AddVar( "PI", &mPI );
43 }
44
45
46
SetMagFcn(ExprUserFcn ** inMagFcn)47 void WaveShape::SetMagFcn( ExprUserFcn** inMagFcn ) {
48
49 mDict.AddFcn( "MAG", inMagFcn );
50 }
51
SetFFTFcn(ExprUserFcn ** inFFTFcn)52 void WaveShape::SetFFTFcn( ExprUserFcn** inFFTFcn ) {
53
54 mDict.AddFcn( "FFT", inFFTFcn );
55 }
56 #define _assignOrig( field ) field##Orig = field;
57
58
59
Load(ArgList & inArgs,long inDefaultNumSteps)60 void WaveShape::Load( ArgList& inArgs, long inDefaultNumSteps ) {
61 UtilStr str;
62
63 // Mix up the rnd seed
64 srand( clock() );
65
66 // Calculate mNumSampleBins -- How many pieces we chop the 0-1 s interval into
67 inArgs.GetArg( 'Stps', str );
68
69 mNum_S_Steps.Compile( str, mDict );
70 CalcNumS_Steps( 0, inDefaultNumSteps );
71
72 // Compile and link all the temp exprs. By their spec, A vars can be evaluated now
73 mA.Compile( inArgs, 'A', mDict );
74 mA.Evaluate();
75 mB.Compile( inArgs, 'B', mDict );
76 mC.Compile( inArgs, 'C', mDict );
77
78 // The intensity fcn allows drawing of arbitrary intensity
79 if ( ! inArgs.GetArg( 'Pen', str ) )
80 str.Assign( "1" );
81 mIntensity.Compile( str, mDict );
82
83 // If a user doesn't enter a line widh for a wave, assume width 1
84 if ( ! inArgs.GetArg( 'LWdt', str ) )
85 str.Assign( "1" );
86 mLineWidth.Compile( str, mDict );
87
88 mPen_Dep_S = mIntensity.IsDependent( "s" ) || mIntensity.IsDependent( "c" ) || mIntensity.IsDependent( "rnd" );
89 mLineWidth_Dep_S = mLineWidth.IsDependent( "s" ) || mLineWidth.IsDependent( "c" ) || mLineWidth.IsDependent( "rnd" );
90
91 // Compile and link waves
92 mWaveX.Compile( inArgs, 'X', mDict );
93 mWaveY.Compile( inArgs, 'Y', mDict );
94
95 // Init all the wave shape var counters
96 mNumWaves = mWaveX.Count();
97
98 mConnectBins = inArgs.GetArg( 'ConB' );
99 mConnectFirstLast = inArgs.GetArg( 'ConB' ) > 1;
100
101 // Make copies/save original values (morph will write over the nonOrg vars)
102 _assignOrig( mConnectBins )
103 _assignOrig( mConnectFirstLast )
104
105 mAspect1to1 = inArgs.GetArg( 'Aspc' );
106 }
107
108
109
110 /*
111 void WaveShape::SetSize( long inWidth, long inHeight ) {
112
113 mXScale = inWidth / 2;
114 mYScale = inHeight / 2;
115
116 if ( mAspect1to1 ) {
117
118 // Keep the xy aspect ratio to 1, change the dim that will get stretched
119 if ( mYScale < mXScale )
120 mXScale = mYScale;
121 else
122 mYScale = mXScale;
123 }
124 }
125 */
126
127
SetupTransition(WaveShape * inDest)128 void WaveShape::SetupTransition( WaveShape* inDest ) {
129
130 mIntensity.Weight( inDest -> mIntensity, &mShapeTrans, 0 );
131 mLineWidth.Weight( inDest -> mLineWidth, &mShapeTrans, 0 );
132
133 mPen_Dep_S = mPen_Dep_S || inDest -> mPen_Dep_S;
134 mLineWidth_Dep_S = mLineWidth_Dep_S|| inDest -> mLineWidth_Dep_S;
135 }
136
137
138
139 #define __evalIntensity( var ) clr = 65535.0 * mIntensity.Evaluate() * inFader; \
140 var = clr; \
141 if ( clr < 0 ) var = 0; \
142 else if ( clr > 0xFFFF ) var = 0xFFFF;
143
144
145
CalcNumS_Steps(WaveShape * inWave2,long inDefaultNumBins)146 void WaveShape::CalcNumS_Steps( WaveShape* inWave2, long inDefaultNumBins ) {
147 int n;
148
149 // See if this shape has an overriding number of s steps
150 mNumSampleBins = inDefaultNumBins;
151 mNumSampleBins = mNum_S_Steps.Evaluate();
152 if ( mNumSampleBins <= 0 )
153 mNumSampleBins = inDefaultNumBins;
154
155
156 if ( inWave2 ) {
157 n = inWave2 -> mNum_S_Steps.Evaluate();
158 if ( n <= 0 )
159 n = inDefaultNumBins;
160
161 mNumSampleBins = ( 1 - mShapeTrans ) * n + mShapeTrans * mNumSampleBins;
162 }
163 }
164
165
Draw(long inNumSteps,PixPort & inDest,float inFader,WaveShape * inWave2,float inMorphPct)166 void WaveShape::Draw( long inNumSteps, PixPort& inDest, float inFader, WaveShape* inWave2, float inMorphPct ) {
167 long i, x, y;
168 long xoff = inDest.GetX() >> 1;
169 long yoff = inDest.GetY() >> 1;
170 long maxWaves, w2Waves, clr;
171 float dialate, tx, ty, stepSize;
172 float xscale, yscale, xscaleW2, yscaleW2 ;
173 RGBColor rgb, rgbPrev, rgbStart;
174
175 // Calc the x and y scale factors
176 xscale = xoff;
177 yscale = yoff;
178 if ( mAspect1to1 ) {
179 if ( yscale < xscale )
180 xscale = yscale;
181 else
182 yscale = xscale;
183 }
184
185 // See if this shape has an overriding number of s steps
186 CalcNumS_Steps( inWave2, inNumSteps );
187
188 // Setup default step size--inv of how many bins are available
189 if ( mNumSampleBins > 1 )
190 stepSize = 1.0 / ( mNumSampleBins - 1.0 );
191 else
192 stepSize = 1;
193
194 // If we're not in a transition/morph
195 if ( ! inWave2 ) {
196 dialate = 1;
197 maxWaves = mNumWaves;
198 w2Waves = 0;
199 }
200
201 // If we're transitioning from one waveshape to another
202 else {
203 w2Waves = inWave2 -> mNumWaves;
204 dialate = inMorphPct;
205 mShapeTrans = pow( dialate, SHAPE_MORPH_ALPHA );
206 SetupFrame( inWave2, mShapeTrans );
207
208 if ( mNumWaves > w2Waves ) {
209 maxWaves = mNumWaves;
210 dialate = 1.0 - dialate; }
211 else
212 maxWaves = w2Waves;
213
214 // Set the wave scale factor to the wave leaving/arriving
215 dialate = 20.0 * pow( dialate, 4.0 ) + 1.0;
216
217 // Calc the x and y scale factors for wave 2
218 xscaleW2 = xoff;
219 yscaleW2 = yoff;
220 if ( inWave2 -> mAspect1to1 ) {
221 if ( yscaleW2 < xscaleW2 )
222 xscaleW2 = yscaleW2;
223 else
224 yscaleW2 = xscaleW2;
225 }
226 }
227
228 // Setup/store the mouse position for possible virtual machine access
229 Point mousePt;
230 EgOSUtils::GetMouse( mousePt );
231 mMouseX = ( (float) mousePt.h ) / xscale;
232 mMouseY = ( (float) mousePt.v ) / yscale;
233
234 // Evaluate the expressions dependent on 't'/the current frame
235 mB.Evaluate();
236 if ( inWave2 )
237 inWave2 -> mB.Evaluate();
238
239 // Calc linewidth, add a little to make .999 into 1. If it's not dep on s, we can evaluate it now
240 if ( ! mLineWidth_Dep_S )
241 inDest.SetLineWidth( mLineWidth.Evaluate() + 0.001 );
242
243 // Calc pen intensity. If it's not dep on s, we can evaluate it now.
244 if ( ! mPen_Dep_S ) {
245 __evalIntensity( rgb.red );
246 rgbPrev = rgb;
247 }
248
249 // Step thru s (the xy exprs will give us the cords)
250 for ( sS = 0; sS <= 1.0; sS += stepSize ) {
251
252 // Evaluate the expressions dependent on 's'
253 mC.Evaluate();
254 if ( inWave2 )
255 inWave2 -> mC.Evaluate();
256
257 // Calc linewidth, add a little to make .999 into 1.
258 if ( mLineWidth_Dep_S )
259 inDest.SetLineWidth( mLineWidth.Evaluate() + 0.001 );
260
261 // Calc pen intensity
262 if ( mPen_Dep_S ) {
263 rgbPrev = rgb;
264 __evalIntensity( rgb.red );
265 }
266
267 // Draw all the waves
268 for ( i = 0; i < maxWaves; i++ ) {
269
270 if ( i < mNumWaves ) {
271
272 // Find the cords for waveshape1, wave number i
273 tx = xscale * mWaveX.Evaluate( i );
274 ty = yscale * mWaveY.Evaluate( i );
275
276 // If we have two waves to mix...
277 if ( i < w2Waves ) {
278 tx = mShapeTrans * tx + ( 1.0 - mShapeTrans ) * xscaleW2 * inWave2 -> mWaveX.Evaluate( i );
279 ty = mShapeTrans * ty + ( 1.0 - mShapeTrans ) * yscaleW2 * inWave2 -> mWaveY.Evaluate( i ); }
280 else {
281 tx *= dialate;
282 ty *= dialate;
283 } }
284 else {
285
286 // Find the cords for waveshape2, wave number i
287 tx = dialate * xscaleW2 * inWave2 -> mWaveX.Evaluate( i );
288 ty = dialate * yscaleW2 * inWave2 -> mWaveY.Evaluate( i );
289 }
290
291 // Switch to screen cords, baby, and draw the line segment
292 x = xoff + tx;
293 y = yoff - ty;
294
295 if ( mConnectBins ) {
296 if ( sS > 0 )
297 inDest.Line( sXY[ 2 * i ], sXY[ 2 * i + 1 ], x, y, rgbPrev, rgb );
298 else {
299 sStartXY[ 2 * i ] = x;
300 sStartXY[ 2 * i + 1 ] = y;
301 rgbStart = rgb;
302 }
303 sXY[ 2 * i ] = x;
304 sXY[ 2 * i + 1 ] = y; }
305 else
306 inDest.Line( x, y, x, y, rgb, rgb );
307 }
308 }
309
310 // Draw all the first-last segments for each wave
311 if ( mConnectFirstLast ) {
312 for ( i = 0; i < maxWaves; i++ )
313 inDest.Line( sXY[ 2 * i ], sXY[ 2 * i + 1 ], sStartXY[ 2 * i ], sStartXY[ 2 * i + 1 ], rgb, rgbStart );
314 }
315
316 // Make sure we restore a random seed (one of the virtual machines could be seeding to the same value)
317 srand( *((long*) mTPtr) );
318
319 }
320
321
322
323
324 #define __weightFLT( field ) field = ( inW * ( (float) field##Orig ) + w1 * ( (float) inDest -> field ) );
325 #define __weightINT( field ) field = ( 0.5 + inW * ( (float) field##Orig ) + w1 * ( (float) inDest -> field ) );
326 #define __weightBOL( field ) field = .5 < ( inW * ( field##Orig ? 1.0 : 0.0 ) + w1 * ( inDest -> field ? 1.0 : 0.0 ) );
327
328
SetupFrame(WaveShape * inDest,float inW)329 void WaveShape::SetupFrame( WaveShape* inDest, float inW ) {
330 float w1 = 1.0 - inW;
331
332 __weightBOL( mConnectBins )
333 __weightBOL( mConnectFirstLast )
334 }
335
336