/* This is a documented WhiteCap 'config' file designed to explain them in the hopes that you can make you own. If you make your own configs and they turn out well, please send me them--I'll include what you send in a cool configs folder when i release the next version of WhiteCap (my email: aco5@cornell.edu). Check out other config files to see how the various parameters can be used in different ways. To make things easier, I put the stuff seen by WhiteCap in boldface type (ie. not the "comments" you're reading now). There's two ways to make comments (that is, have text ignored by WhiteCap): 1) "//" tells WhiteCap to ignore whatever text follows on that line, 2) Text enclosed within "/*" and "* /" is also ignored (like this big block of text you're reading now) In a config file, if you see something is quotes or just a number with an "=" in front of it, it's matched up to the 3 or 4 letter parameter name on its left. If you see something in quotes, it's called an expression and you can do all the things described below as well as use various other global values (A, B, C, D vars, dt, st, t, and mag()--all explained later). When you see a parameter not in quotes, it means that you can only put an numerical value there (ex, 4, -55, 4343--nothing but digits and a leading dash if it's negative). Also, be sure you don't forget key things like commas and quotes that signify where data stops and starts. Parameters are assumed to be 0 or "0" (depending on the type) if they are left out from a config file. A "config" file is any file like this for WhiteCap that contains textual commands (that we can edit) that WhiteCap interprets when it runs. Many parameters in a WhiteCap config are 'expressions'. Expressions are functions--they represent a single value that depends on a combonation of other numbers, variables, and functions. "3*b", "3.141", "sqrt(t+7)", and "(s+t+2.7)^dt" are all examples of expressions. The following mathematical functions are available: sin(), cos(), tan(), atan(), sqrt(), log(), exp(), tan(), abs(), and... pos(x) == x when x >= 0 and 0 when x < 0. abs(x) == |x| sqr(x) == x * x sgn(x) == 1 when x >= 0 and -1 when x < 0 rnd(x) == a random value from 0 to x (ex, rnd(1) returns a number in the range [0,1]) clip(x) == 0 when x < 0, 1 when x > 1, and x when 0 <= x <= 1 trnc(x) == x with everything right of the decimal point dropped flor(x) == the largest integer that's also less than x (ex, flor(3.2) == 3, flor(-2.7) == -3 ) wrap(x) == x - flor( x ) (ex, wrap( 4.124 ) = .124, wrap( - 2.7 ) = .3 ) sqwv(x) == 1 if |x| <= 1.0 and 0 otherwise. trwv(x) == |x| if |x| < 1 and trwv(|x| - 2) otherwise (if plotted starting from 0: /\/\/\/\... ) seed(x) seeds the random number generator to x, returns x An operator is a something that joins to numbers, like the + and - we're used to elementary school. Operators are used to combine two values into a single one, and the operators available in WhiteCap are: +,-,*,/,%,^ ( "a % b" means "the whole remainder when a is divided by b", and "a^b" means "a raised to the b"). Traditional order of operations apply and you may freely use parentheses. */ /* Resolution: When a sample is taken, another won't be taken until a certain period of time later. The time in the Resn parameter (in milliseconds) is this length of time. The higher this delay is, the less often samples will be recorded and thus the trail will appear more sparse. If you have a config where samples seem to be really crowded, raise this value by 30 or 40. */ Resn=10, /* Duration: This specifies how long a sample stays around until its considered expired. When a sample has been around longer than this time, it's deleted and disappears. So as this number increases, the more samples that will around each frame. */ Durn="1.3", /* Camera position: This tells WCs the position of the camera (WC needs to know this in order to render the scene). t is the system time (in seconds), and is the way to get the camera (or any expression) to do things though time (ex, change position or change viewing orientation) . CamX, Y, and X are the camera's coordinates in space. */ CamX="60 * sin( .5 * t )", CamY="20 * cos( .3 * t )", CamZ="14 + 6 * cos( .3 * t )", /* Camera Look Point: The point in space the camera looks at/towards. So the (absolute) direction the camera looks is (-(CamX-CmLX),-(CamY-CmLY),-(CamZ-CmLZ)). */ CmLX="20", CmLY="0", CmLZ="0", /* Camera 'Up' Direction: The direction of the following vector specifies the direction from the camera location that is 'up'--that is, it's the y direction in the camera's coordinate system. In other words, the segment from point CmL to point (CmL+CUp) draws as line starting from exact middle of your screen and goes perfectly upward vertically. In this config, since the camera rarely passes directly over the origin (sin(.5t) and cos(.3t) have to both equal zero), the direction (0,0,1) ensures the camera's oriented such that the z-axis is always vertical and points upward. Make sure this vector never crosses the precise direction as the Camera direction or else you'll cause an unsightly jump-discontinuity of camera up direction (as WhiteCap will be forced to choose an arbitrary 'up' direction). For example, as the camera's line of sight approaches the direction of CUp, the segment described above approaches a single pixel (in the middle of the screen). "Tunnel Vision" and "Canyon Chase" use CUp to make the camera change orientation in a cool way. */ CUpX="0", CUpY="0", CUpZ="1", /* If you didn't catch all that Camera stuff the first time around, don't sweat it. If you look a enough configs you can mimic some basic camera movement. */ /* Tail Position/Shape: WhiteCap gives you access to 3 principle variables and a function: - t: the system time index (in seconds) - st: the system time the current sample was recorded - s: a value that goes from 0 to 1 - mag(): The sound magnitude/amplitude of the current sample. mag( ) returns the magnitude of a frequency of the current sample. WhiteCap also computes a commonly used value for you, dt, 0 means the current sample was just recorded and 1 means it's about about to expire. Finally, WC let's you define temporary variables so that you can save time by not having to repeadly calculate values that don't change. In other words, WhiteCap allows you to compute commonly used values so that you can avoid having WhiteCap recompute things unnecessarily. For now, just know that A0, B0, B1, C1, etc, are temporary variables. Let's break WhiteCap down: begin { evaluate A0, A1, A2... for each frame { record a sample (ie, capture a freq spectrum for that moment in time) erase recorded samples older than Durn t = current system time (in secs) calculate B0, B1, B2... (they can depend on 't') calculate then apply BckR,BckG,BckB as the background color calculate CamXYZ, CmLXYZ, and CUpXYZ (the cam pos and orientation, 9 exprs total) for samp = step thru list of recorded samples from oldest to newest { st = time samp was recorded dt = ( t - st ) / Durn setPenWidth( LWdt ) calculate C0, C1, C2... for s = 0 to 1 step 1/Stps { calculate D0, D1, D2... screen_pt = getScrnCoordFor( X, Y, Z, CamXYZ, CmLXYZ, CUpXYZ ) if ( st == t ) setPenColor( LvlR, LvlG, LvlB ) else setPenColor( R, G, B ) if ( ConL == 0 AND ConB == 0 ) drawDot( screen_pt ) else drawLineTo( screen_pt ) } } } } Let's pretend we're currently watching the "(Default)" green config. The samp loop starts at the end of the tail and works toward the head. Each "step" works on a sample recorded at a specific time, and the s-loop is used to draw from one end of the spectrum to the other. Basically, the "(Default)" config uses t as the y coord, s for the x coord, and mag(s) as the z coord. It's difficult to explain, and seeing basic examples is the best way to learn what's goin on. If you feel lost, just skip ahead to the XYZ parameters. Using temporary variables is useful when you want to compute something once and use it multiple times (to avoid redundant computation). There are 4 groups of temporary variables available for use in WhiteCap: A, B, C and D. The A variables are evaluated once, when the config is loaded, the B variables are evaluated at the start if each frame, the C variables are evaluated each sample (for each frame), and the D variables are evaluated for each change in 's' (for each sample for each frame). The A variables are usually used as global config values when the config loads. For example, you could set A0, A1, A2 to be a random values that get used together to form an RGB color that's used for the config, so that each time the config loads it's would be a different color. The B variables are useful for computing things that depend on 't', such as the B0 parameter in Cosine Classic. The C variables are useful for computing things that depend on 'dt', that is, values that stay constant over s. For example, in this config we precompute a cosine in C0 because the cosine doesn't change with any change to s. D variables are useful for computing a value that's used multiple times and is dependent on s. The D variables are useful for computing values shared by the 6 expressions: X, Y, Z, R, G, B. For example, if the RGB all depend on some big function of s, it makes sense to do all the shared computation in D0 and just use D0 in R, G, and B. The way you denote declare a temporary variable is by counting up from zero, such as A0, A1, A2, etc. Most included configs make extensive use of temporary variables. Back to the WhiteCap main loop... Note how using the mag() function in an A or B variable wouldn't make any sense because they are values that constant for all the samples. There is one exception--if you use the mag() fcn inside a B var, it accesses the most recent sample (ie, dt == 0). This allows you set values (ie. B vars) that are universal for the entire frame. This is how could, say, make the background color beat with the music or make the camera jiggle with the bass beat. */ /* Until you get a feel for how to use temp variables, don't use them--just put everything in terms of t, st, dt, and/or s in the RGB and XYZ expressions. The only consequence will be that your config will run slow as WhiteCap evaluates those 6 expressions for each bin for each sample for each frame. Send me your config and I'll can show you how to make it faster. */ /* This is an oscillator than goes from -1.2 to .6, the 'wing' angle (in radians). Try taking changing the coefficient of dt or t to zero and observe the effects. */ C0="-1.2 + 1.8 * ( .5 * sin( t * 1.5 - 1.5 * dt ) + .5 )", C1="cos( c0 )", // We use this twice as well /* We need the following value twice, and it depends on s, so we can't make it any faster than a D var. Note how we access the sound level/magnitude. */ D0="13 * abs( mag( s ) )", /* If you want to check out XYZ expressions less complicated than this, check out "My Malia". In "(Default)" or "My Malia", the CYZ exprs look like: X="dt * 40", Y="60 * ( 2 * s - 1)", Z="20 * mag( s )", Watch one of these two configs until you see how the above XYZ expressions define what you're seeing. The only real differences between the two are the camera movement and the color scheme. Below, we use some fancy math to get the effect of bird-like flapping motion. Don't worry about figuring out what the math is doing, just understand that each point calculated in WhiteCap is determined by these functions. */ X="dt * 40", Y="165 * ( s - .5 ) * c1 - sin( sgn( s - .5 ) * c0 ) * d0", Z="165 * abs( s - .5 ) * sin( c0 ) + c1 * d0", /* Tail Color: This express the RGB for each point on the tail. The rules for the RGB expressions are the same as the XYZ expressions, and you're free to use temporary variables (although there's no need to use any in this example). Once WhiteCap calculates the coordinate of a point using the above XYZ expressions, it uses the these 3 expressions to know what color to draw in. A value of 1.0 signifies 100% of a component, 0.0 represents a complete absence of that color. Check out the pseudocode for WhiteCap above to see when these three expressions are evaluated. Again, check out "My Malia" to see a less complicated RGB set. */ R="( 1 - .7 * dt ) * ( .5 * cos( 18 * dt ) + .5 )", G="0", B=".3", /* Note that I didn't bother to put the expr for R in a C variable. This is because when whitecap goes to evaluate an expression for each change in s, it won't bother to revaluate an expression if it doesn't have an s or D variable in it. It's always critical that you always move whatever you can into C expressions--that's what's gonna make the key speed difference for your config. */ /* "Level" Color (the color of the "present" sample, in other words, the sample where st == t, dt = 0). This is the color painted on the front end of the tail. If these params are missing, the RGB of the front of the wave is determined by above RGB expressions. These are expressions, so you're free to use t, s, and mag(). */ LvlR=".4", LvlG=".4", LvlB="1", /* Background Color -- same param types as the Level color: Expressions that return a value from 0 to 1. You are free to access t, s, and mag() */ BckR="0", BckG="0", BckB="0", /* Connecting Lines: A 1 here tells WhiteCap to connect adjacent samples together with lines, 0 means you don't want those lines. Try changing this to 0 and see what happens. */ ConL=1, /* Set ConB to 1 if you want the points of the sample ("bins") to be connected. Set ConB to 0 if you don't want those lines. "Vortex" has the effect of 'particles' by setting ConL and ConB both equal to 0. If ConB is set to 2, WhiteCap draws as if it was set to 1 and draws a line from bin 0 to bin N. */ ConB=1, /* Line Width: This is an expression of the pen width, in pixels, evaluated for each sample. You're free to access t, dt, st, and mag() here. */ LWdt="1", /* Falloff: This number describes how "sticky" the magnitude levels are... Imagine a needle that moves to the volume of a song. Falloff is how fast the needle falls back to zero if you were to suddenly turn off the music. The higher this is, the faster the needle falls back to zero. Be careful, if you set it too close to zero, the level will too sticky and it will never change! Note if you set this above around .06, the level pretty much falls off instantly. */ Fall=".05", /* Gaussian Blur: Blrs represents how steps of blurs you want in the tail. For example, if Blrs=3 then after WhiteCap will blur the last 1/3 of the tail, then the last 2/3 of the tail, then the entire tail. BlrB is the blur "box" size. It's how much things are blurred. BlrB set to less than 2 doesn't blur at all. You tell WhiteCap you don't want any blurring of any kind by setting Blrs to 0. */ Blrs=0,BlrB=3, /* The height and width window this config fit into. WhiteCap uses these two params to shrink or expand your config based on the current window size. WhiteCap will always shrink your config, based on these values, such that *both* dimensions will fit in the window. For example, with the below values, and with a current window size of 100 wide and 400 tall, WhiteCap will shrink your config by 1/5 at all times. */ widt=500,heig=450, /* Scale: Directly scales the screen x and y coordinates. This param basically provides an easy way to shrink/expand your config painlessly. Note: doubling widh and heig will have exactly the same effect as halving Scal. */ Scal="500", /* Number of bins per sample: This tells WhiteCap how many pieces you want the interval [0,1] to be chopped up into as WhiteCap varies s. See the Extras documentation for more info. If you omit this parameter or make it < 1, WhiteCap uses the value of Stps found in the prefs file for your config. Finally, you can access the current value of the default number of bins per sample using the NUM_SAMPLE_BINS variable. */ Stps=-1, /* Scale with size: When this is 1, WhiteCap will scale your config so that it will fit nicely inside the current window. If this param is 0, WhiteCap will not scale your config in the way described in the descripion for widh and heig if it means your config will be made larger. Usually this is set to 1, but in Flame, for example, where blurring is used, WhiteCap would slow to a crawl if scaled Flame up to a particularly large window. */ ScSz=1, /* Perspective Scale: How much points obscure to the fringes based on their distance from the camera. WhiteCap uses the following formula to express screen coords: scrn_x = Scal * scrn_x / ( scrn_z + Pers ) The bigger you make this value, the more 'dimensionless' things will look. For example, the camera that records from the backside of the pitcher in a major league baseball game has a high Pers value because the camera is very far away (and has a high Scal from a telescopic lens). The result is that the pitcher looks the same size as the batter. On the other hand, if the camera was on 2nd base or you were standing at the foot of a skyscraper, the Pers is low because your eyes are near the object, causing high perspective-distortion for nearby features. So increasing Scal increases the power of your telescopic lens (making your object bigger), and increasing Pers walks you further away (making your object smaller and reducing distortion due to perspective). So to change the distortion due to perspective but keep your object the same size, you must change both Scal and Pers. */ Pers="150", /* This should always equal to the lowest version of WhiteCap the config is compatible with (times 10). WhiteCap makes sure the config it's about to show matches it's current version. If it doesn't match, WhiteCap will just display the built-in 'factory' config (it's green with a red level line). */ Vers=30