--- linden/doc/contributions.txt.orig	2008-03-06 17:02:22.000000000 +0000
+++ linden/doc/contributions.txt	2008-03-06 17:00:34.000000000 +0000
@@ -11,6 +11,7 @@
 Aimee Trescothick
 	VWR-3903
 	VWR-4803
+	VWR-5308
 Alejandro Rosenthal
 	VWR-1184
 Alissa Sabre
@@ -126,6 +127,7 @@
 	VWR-1987
 	VWR-2065
 	VWR-2502
+	VWR-5308
 Ginko Bayliss
 	VWR-4
 Grazer Kline
--- linden/indra/llmath/llmath.h.orig	2008-03-06 17:12:26.000000000 +0000
+++ linden/indra/llmath/llmath.h	2008-03-06 15:00:47.000000000 +0000
@@ -48,12 +48,12 @@
 #endif
 
 // Single Precision Floating Point Routines
-#ifndef fsqrtf
-#define fsqrtf(x)		((F32)sqrt((F64)(x)))
-#endif
 #ifndef sqrtf
 #define sqrtf(x)		((F32)sqrt((F64)(x)))
 #endif
+#ifndef fsqrtf
+#define fsqrtf(x)		sqrtf(x)
+#endif
 
 #ifndef cosf
 #define cosf(x)		((F32)cos((F64)(x)))
@@ -71,6 +71,9 @@
 #ifndef powf
 #define powf(x,y) ((F32)pow((F64)(x),(F64)(y)))
 #endif
+#ifndef expf
+#define expf(x) ((F32)exp((F64)(x)))
+#endif
 
 const F32	GRAVITY			= -9.8f;
 
--- linden/indra/llaudio/audioengine_fmod.cpp.orig	2008-03-05 21:58:38.000000000 +0000
+++ linden/indra/llaudio/audioengine_fmod.cpp	2008-03-08 04:56:23.000000000 +0000
@@ -54,21 +54,9 @@
 FSOUND_DSPUNIT *gWindDSP = NULL;
 
 // These globals for the wind filter.  Blech!
-F64 gbuf0 = 0.0;
-F64 gbuf1 = 0.0;
-F64 gbuf2 = 0.0;
-F64 gbuf3 = 0.0;
-F64 gbuf4 = 0.0;
-F64 gbuf5 = 0.0;
-F64 gY0 = 0.0;
-F64 gY1 = 0.0;
-
 F32 gTargetGain = 0.f;
-F32 gCurrentGain = 0.f;
 F32 gTargetFreq = 100.f;
-F32 gCurrentFreq = 100.f;
 F32 gTargetPanGainR = 0.5f;
-F32 gCurrentPanGainR = 0.5f;
 
 
 // Safe strcpy
@@ -348,8 +336,8 @@
 void LLAudioEngine_FMOD::updateWind(LLVector3 wind_vec, F32 camera_height_above_water)
 {
 	LLVector3 wind_pos;
-	F64 pitch;
-	F64 center_freq;
+	F32 pitch;
+	F32 center_freq;
 
 	if (!mEnableWind)
 	{
@@ -367,10 +355,10 @@
 
 		// cerr << "Wind update" << endl;
 
-		pitch = 1.0 + mapWindVecToPitch(wind_vec);
-		center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0));
+		pitch = 1.0f + mapWindVecToPitch(wind_vec);
+		center_freq = 80.0f * powf(pitch,2.5f*((F32)mapWindVecToGain(wind_vec)+1.0f));
 		
-		gTargetFreq = (F32)center_freq;
+		gTargetFreq = center_freq;
 		gTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain;
 		gTargetPanGainR = (F32)mapWindVecToPan(wind_vec);
   	}
@@ -1087,7 +1075,7 @@
 	#define MIXBUFFERFORMAT S16
 #endif
 
-inline MIXBUFFERFORMAT clipSample(MIXBUFFERFORMAT sample, MIXBUFFERFORMAT min, MIXBUFFERFORMAT max)
+inline MIXBUFFERFORMAT clipSample(F32 sample, MIXBUFFERFORMAT min, MIXBUFFERFORMAT max)
 {
 	if (sample > max)
 		sample = max;
@@ -1097,6 +1085,10 @@
 	return sample;
 }
 
+
+//NOTE: This function gets called a *lot*.  
+//The inner loop runs 44,100 times per second.
+//Keep performance in mind if you mess with this.
 void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void*)
 {
 // originalbuffer = fsounds original mixbuffer.
@@ -1106,67 +1098,121 @@
 //
 // modify the buffer in some fashion
 
+	//this turns off wind synth if it is muted or very very low volume
+	if (gTargetGain < 0.0005f)
+		return newbuffer;
+
+	static F32 gbuf0 = 0.0f;
+	static F32 gbuf1 = 0.0f;
+	static F32 gbuf2 = 0.0f;
+	static F32 gY0 = 0.0f;
+	static F32 gY1 = 0.0f;
+	static F32 last_sample = 0.0f;
+	static F32 current_freq;
+	static F32 current_gain;
+	static F32 current_pan_gain_r;
+
 	U8 *cursamplep = (U8*)newbuffer;
-	U8   wordsize = 2;
+	U8 wordsize = 2;
+	bool clip = TRUE;
 
 #if LL_DARWIN
 	wordsize = sizeof(MIXBUFFERFORMAT);
+	clip = (wordsize == 2);
+
 #else
-    int		mixertype = FSOUND_GetMixer();
-    if (mixertype == FSOUND_MIXER_BLENDMODE || mixertype == FSOUND_MIXER_QUALITY_FPU)
-    {
+	int mixertype = FSOUND_GetMixer();
+	if (mixertype == FSOUND_MIXER_BLENDMODE || mixertype == FSOUND_MIXER_QUALITY_FPU)
+	{
 		wordsize = 4;
+		clip = FALSE;
     }
 #endif
 
-    double bandwidth = 50;
-    double inputSamplingRate = 44100;
-	double a0,b1,b2;
- 
+	U8 subsamples = 2;
+	F32 filter_sample_period = (F32)subsamples / 44100.0f;
+	F32 bandwidth = 50.0f;
+	F32 a0 = 0.0f, b1 = 0.0f, b2 = 0.0f;
+
+	bool interp_freq = false; 
+
 	// calculate resonant filter coeffs
-    b2 = exp(-(F_TWO_PI) * (bandwidth / inputSamplingRate));
+	b2 = expf(-(F_TWO_PI) * (bandwidth * filter_sample_period));
 
-	while (length--)
+	//if the frequency isn't changing much, we don't need to interpolate in the inner loop
+	if (llabs(gTargetFreq - current_freq) > 200.0f)
 	{
-		gCurrentFreq = (float)((0.999 * gCurrentFreq) + (0.001 * gTargetFreq));
-		gCurrentGain = (float)((0.999 * gCurrentGain) + (0.001 * gTargetGain));
-		gCurrentPanGainR = (float)((0.999 * gCurrentPanGainR) + (0.001 * gTargetPanGainR));
-		b1 = (-4.0 * b2) / (1.0 + b2) * cos(F_TWO_PI * (gCurrentFreq / inputSamplingRate));
-	    a0 = (1.0 - b2) * sqrt(1.0 - (b1 * b1) / (4.0 * b2));
-		double nextSample;
+		interp_freq = true;
+	}
+	else
+	{
+		current_freq = gTargetFreq;
+		b1 = (-4.0f * b2) / (1.0f + b2) * cosf(F_TWO_PI * (current_freq * filter_sample_period));
+		a0 = (1.0f - b2) * sqrtf(1.0f - (b1 * b1) / (4.0f * b2));
+	}
+
+
+	while (length)
+	{
+		current_gain = (0.999f * current_gain) + (0.001f * gTargetGain);
+		current_pan_gain_r = (0.999f * current_pan_gain_r) + (0.001f * gTargetPanGainR);
+		
+		if (interp_freq)
+		{
+			current_freq = (0.999f * current_freq) + (0.001f * gTargetFreq);
+			b1 = (-4.0f * b2) / (1.0f + b2) * cosf(F_TWO_PI * (current_freq * filter_sample_period));
+			a0 = (1.0f - b2) * sqrtf(1.0f - (b1 * b1) / (4.0f * b2));
+		}
 
-	    // start with white noise
-		nextSample = ll_frand(2.0f) - 1.0f;
+		F32 next_sample;
+
+	    // start with white noise [-0.125, 0.125]
+		// next_sample = ll_frand(0.25f) - 0.125f;
+		next_sample = (F32)rand() * 0.25f / ((F32)RAND_MAX + 1.0f) - 0.125f;
 									 
-#if 1 // LLAE_WIND_PINK apply pinking filter
-		gbuf0 = 0.997f * gbuf0 + 0.0126502f * nextSample; 
-        gbuf1 = 0.985f * gbuf1 + 0.0139083f * nextSample;
-        gbuf2 = 0.950f * gbuf2 + 0.0205439f * nextSample;
-        gbuf3 = 0.850f * gbuf3 + 0.0387225f * nextSample;
-        gbuf4 = 0.620f * gbuf4 + 0.0465932f * nextSample;
-        gbuf5 = 0.250f * gbuf5 + 0.1093477f * nextSample;
-			  
-        nextSample = gbuf0 + gbuf1 + gbuf2 + gbuf3 + gbuf4 + gbuf5;
-#endif
+		// Pinking filter
+		gbuf0 = 0.99765f * gbuf0 + next_sample * 0.0990460f;
+		gbuf1 = 0.96300f * gbuf1 + next_sample * 0.2965164f;
+		gbuf2 = 0.57000f * gbuf2 + next_sample * 1.0526913f;
+		
+		next_sample = gbuf0 + gbuf1 + gbuf2 + next_sample * 0.1848f;
 			
-#if 1 //LLAE_WIND_RESONANT // do a resonant filter on the noise
-        nextSample = (double)( a0 * nextSample - b1 * gY0 - b2 * gY1 );
+		// do a resonant filter on the noise
+        next_sample = ( a0 * next_sample - b1 * gY0 - b2 * gY1 );
 
         gY1 = gY0;
-        gY0 = nextSample;
-#endif
+        gY0 = next_sample;
 
-	    nextSample *= gCurrentGain;
+	    next_sample *= current_gain * 32768.f;
+		F32 delta = (next_sample - last_sample) / (F32)subsamples;
 		
-		MIXBUFFERFORMAT	sample;
+		F32	sample_left;
+		F32	sample_right;
+
+		for (U8 i=0; i < subsamples && length; i++, length--) 
+		{
+			last_sample = last_sample + delta;
+			
+			sample_right = llfloor(last_sample * current_pan_gain_r + 0.5f);
+			sample_left = last_sample - sample_right;
+
+			if (clip)
+			{
+				*(MIXBUFFERFORMAT*)cursamplep = clipSample((*(MIXBUFFERFORMAT*)cursamplep) + sample_left, -32768, 32767);
+				cursamplep += wordsize;
+
+				*(MIXBUFFERFORMAT*)cursamplep = clipSample((*(MIXBUFFERFORMAT*)cursamplep) + sample_right, -32768, 32767);
+				cursamplep += wordsize;
+			}
+			else
+			{
+				*(MIXBUFFERFORMAT*)cursamplep = (*(MIXBUFFERFORMAT*)cursamplep) + sample_left;
+				cursamplep += wordsize;
 
-		sample = llfloor(((F32)nextSample*32768.f*(1.0f - gCurrentPanGainR))+0.5f);
-		*(MIXBUFFERFORMAT*)cursamplep = clipSample((*(MIXBUFFERFORMAT*)cursamplep) + sample, -32768, 32767);
-		cursamplep += wordsize;
-
-		sample = llfloor(((F32)nextSample*32768.f*gCurrentPanGainR)+0.5f);
-		*(MIXBUFFERFORMAT*)cursamplep = clipSample((*(MIXBUFFERFORMAT*)cursamplep) + sample, -32768, 32767);
-		cursamplep += wordsize;
+				*(MIXBUFFERFORMAT*)cursamplep = (*(MIXBUFFERFORMAT*)cursamplep) + sample_right;
+				cursamplep += wordsize;
+			}
+		}
 	}
 
 	return newbuffer;
