
Index: trunk/indra/llaudio/audioengine_openal.cpp
===================================================================
--- trunk.orig/indra/llaudio/audioengine_openal.cpp	2008-01-23 14:34:36.000000000 +0000
+++ trunk/indra/llaudio/audioengine_openal.cpp	2008-01-23 19:03:16.000000000 +0000
@@ -4,6 +4,9 @@
 
 #include "audioengine_openal.h"
 #include "listener_openal.h"
+#include "llmath.h"
+#include "llrand.h"
+
 
 LLAudioEngine_OpenAL::LLAudioEngine_OpenAL(){
 
@@ -192,19 +195,6 @@
 
 // ------------
 
-void LLAudioEngine_OpenAL::initWind(){
-}
-
-void LLAudioEngine_OpenAL::cleanupWind(){
-}
-
-void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude){
-	//llinfos << "LLAudioEngine_OpenAL::updateWind() Direction: "
-	//	<< wind_vec << " Altitude: " << camera_altitude << llendl;
-}
-
-// ------------
-
 void LLAudioEngine_OpenAL::initInternetStream(){
 	mInternetStreamURL.erase();
 	
@@ -284,4 +274,255 @@
 	return mInternetStreamURL.c_str();
 }
 
+
+// ------------
+
+
+#define NO_WIND_BUFFERS 20
+static ALuint wind_buffers[NO_WIND_BUFFERS];
+static ALuint wind_sources[1];
+static S16 *winddata=NULL;
+
+static BOOL first_wind=TRUE;
+
+ALfloat source0Vel[]={ 0.0, 0.0, 0.0};
+
+// 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;
+
+void LLAudioEngine_OpenAL::initWind()
+{
+	ALenum error;	
+	llinfos << "LLAudioEngine_OpenAL::initWind() start" << llendl;
+
+	alGetError(); /* clear error */
+	alGenBuffers(NO_WIND_BUFFERS,wind_buffers);
+	if((error=alGetError()) != AL_NO_ERROR)
+	{
+		llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind buffers: "<<error<<llendl; 
+	}
+	
+	alGenSources(1,wind_sources);
+
+	if((error=alGetError()) != AL_NO_ERROR)
+	{
+		llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind sources: "<<error<<llendl; 
+	}
+
+	winddata=(S16*)malloc(sizeof(S16)*44100*0.2*2*2); //200ms @44100Hz Stereo
+
+	if(winddata==NULL)
+	{
+		llerrs << "LLAudioEngine_OpenAL::initWind() Error creating wind memory buffer" << llendl;
+		mEnableWind=FALSE;
+	}
+	
+	llinfos << "LLAudioEngine_OpenAL::initWind() done" << llendl;
+}
+
+void LLAudioEngine_OpenAL::cleanupWind()
+{
+	llinfos << "LLAudioEngine_OpenAL::cleanupWind()" << llendl;
+
+	alDeleteBuffers(NO_WIND_BUFFERS,wind_buffers);
+
+	alDeleteSources(1, wind_sources);
+
+	if(winddata)
+		free(winddata);
+}
+
+void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_height_above_water)
+{
+	LLVector3 wind_pos;
+	F64 pitch;
+	F64 center_freq;
+	ALenum error;
+
+	mMaxWindGain=1.0;
+
+	if (!mEnableWind)
+		return;
+
+	if(!winddata)
+		return;
+
+	if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL))
+	{
+	
+		// wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up)
+		// need to convert this to the conventional orientation DS3D and OpenAL use
+		// where +X = right, +Y = up, +Z = backwards
+
+		wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]);
+
+		// cerr << "Wind update" << endl;
+
+		pitch = 1.0 + mapWindVecToPitch(wind_vec);
+		center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0));
+		
+		gTargetFreq = (F32)center_freq;
+		gTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain;
+		gTargetPanGainR = (F32)mapWindVecToPan(wind_vec);
+
+		ALfloat source0Pos[]={mListenerp->getPosition().mV[0],mListenerp->getPosition().mV[1],mListenerp->getPosition().mV[2]};
+  	
+		alSourcef(wind_sources[0], AL_GAIN, gTargetGain);
+		alSourcef(wind_sources[0], AL_PITCH, pitch);
+    		alSourcefv(wind_sources[0], AL_POSITION, source0Pos);
+    		alSourcefv(wind_sources[0], AL_VELOCITY, source0Vel);
+    		alSourcei(wind_sources[0], AL_LOOPING, AL_FALSE);
+
+	}
+
+	// ok lets make a wind buffer now
+
+	if(first_wind==TRUE)
+	{
+		llinfos << "LLAudioEngine_OpenAL::updateWind() making first buffer" << llendl;
+		alGetError(); /* clear error */
+		
+		for(int counter=0;counter<NO_WIND_BUFFERS;counter++)
+		{
+			alBufferData(wind_buffers[counter],AL_FORMAT_STEREO16,windDSP((void*)winddata,2*44100*0.02),2*44100*0.02*sizeof(U16),44100);
+			if((error=alGetError()) != AL_NO_ERROR)
+			{
+				llwarns << "LLAudioEngine_OpenAL::initWind() Error creating INITAL WIND BUFFER 1: "<<error<<llendl; 
+			}
+		}
+
+		alSourceQueueBuffers(wind_sources[0], NO_WIND_BUFFERS, wind_buffers);
+
+		alSourcePlay(wind_sources[0]);
+		if((error=alGetError()) != AL_NO_ERROR)
+		{
+			llwarns << "LLAudioEngine_OpenAL::initWind() Error inital wind play: "<<error<<llendl; 
+		}
+
+		first_wind=FALSE;	
+		llinfos << "LLAudioEngine_OpenAL::updateWind() making first buffer DONE!" << llendl;
+
+	}
+	else
+	{
+		int processed;
+ 		alGetSourcei(wind_sources[0], AL_BUFFERS_PROCESSED, &processed);
+		
+		while(processed--)
+    		{
+        		ALuint buffer;
+			int error; 
+			alSourceUnqueueBuffers(wind_sources[0], 1, &buffer);		
+			error = alGetError();
+ 			if(error != AL_NO_ERROR)
+  				llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping buffers" << llendl;
+
+			alBufferData(buffer,AL_FORMAT_STEREO16,windDSP((void*)winddata,44100*0.2),2*44100*0.2*sizeof(U16),44100);
+			error = alGetError();
+ 			if(error != AL_NO_ERROR)
+  				llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping buffers" << llendl;		
+
+			alSourceQueueBuffers(wind_sources[0], 1, &buffer);
+			error = alGetError();
+ 			if(error != AL_NO_ERROR)
+  				llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping buffers" << llendl;		
+
+		}
+		
+		int playing;
+ 		alGetSourcei(wind_sources[0], AL_SOURCE_STATE, &playing);
+	
+		if(playing==AL_STOPPED)
+			alSourcePlay(wind_sources[0]);
+	
+	}
+
+}
+
+inline S16 clipSample(S16 sample, S16 min, S16 max)
+{
+	if (sample > max)
+		sample = max;
+	else if (sample < min)
+		sample = min;
+	
+	return sample;
+}
+
+void * LLAudioEngine_OpenAL::windDSP(void *newbuffer, int length)
+{
+	// newbuffer = the buffer passed from the previous DSP unit.
+	// length = length in samples at this mix time.
+
+	U8 *cursamplep = (U8*)newbuffer;
+	U8   wordsize = 2;
+
+    	double bandwidth = 50;
+    	double inputSamplingRate = 44100;
+    	double a0,b1,b2;
+
+	// calculate resonant filter coeffs
+    	b2 = exp(-(F_TWO_PI) * (bandwidth / inputSamplingRate));
+
+	while (length--)
+	{
+		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;
+
+	    // start with white noise
+		nextSample = ll_frand(2.0f) - 1.0f;
+									 
+#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
+			
+#if 1 //LLAE_WIND_RESONANT // do a resonant filter on the noise
+        	nextSample = (double)( a0 * nextSample - b1 * gY0 - b2 * gY1 );
+
+        	gY1 = gY0;
+        	gY0 = nextSample;
+#endif
+		nextSample *= gCurrentGain;
+		
+		S16	sample;
+
+		sample = llfloor(((F32)nextSample*32768.f*(1.0f - gCurrentPanGainR))+0.5f);
+		*(S16*)cursamplep = clipSample(sample, -32768, 32767);
+
+		cursamplep += wordsize;
+
+		sample = llfloor(((F32)nextSample*32768.f*gCurrentPanGainR)+0.5f);
+		*(S16*)cursamplep = clipSample(sample, -32768, 32767);
+		cursamplep += wordsize;
+	}
+
+	return newbuffer;
+}
+
+
 #endif // #LL_OPENAL
Index: trunk/indra/llaudio/audioengine_openal.h
===================================================================
--- trunk.orig/indra/llaudio/audioengine_openal.h	2008-01-23 14:37:22.000000000 +0000
+++ trunk/indra/llaudio/audioengine_openal.h	2008-01-23 14:54:43.000000000 +0000
@@ -45,6 +45,8 @@
 	protected:
 		std::string mInternetStreamURL;
 		LLMediaImplGStreamer * m_streamer;
+		void * windDSP(void *newbuffer, int length);
+
 
 };
 
