#include #include "munga.h" #pragma hdrstop #include "audio.h" #include "audrend.h" #include "app.h" #include "..\munga_l4\openal\al.h" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Audio Constants ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const Scalar AudioDoubleTriggerCutoff = 0.2f; const AudioControlValue MaxAudioVolume = 1.0f; const AudioControlValue MinAudioVolume = 0.0f; const AudioControlValue LowAudioVolumeThreshold = 0.3f; const AudioControlValue MaxAudioBrightness = 1.0f; const AudioControlValue MinAudioBrightness = 0.0f; const AudioControlValue MaxAudioAttack = 1.0f; const AudioControlValue MinAudioAttack = 0.0f; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHead ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // //############################################################################# //############################################################################# // AudioHead::AudioHead(): headEntitySocket(NULL) { // // Start frame counter at 0, other counts should be at // NullAudioFrameCount // audioFrameCount = 0; // // Other audio parameters // clippingRadius = 100.0f; distanceBetweenEars = 1.0f; amplitudeRollOffExponent = 1.0f; amplitudeRollOffKnee = 10.0f, amplitudeRollOffDistanceScale = 0.05f; highFrequencyRollOffExponent = 0.5f; highFrequencyRollOffKnee = 10.0f; highFrequencyRollOffDistanceScale = 0.05f; reverbToDryRatio = 0.1f; audioSoundSpeed = 345.0f; audioDopplerConstant = 20.0f; sourceCompressionExponent = 0.5f; sourceCompressionScale = 0.5f; Check_Fpu(); } // //############################################################################# //############################################################################# // AudioHead::~AudioHead() { Check(this); Check_Fpu(); } // //############################################################################# //############################################################################# // Logical AudioHead::TestInstance() const { Check(&headEntitySocket); return True; } // //############################################################################# //############################################################################# // void AudioHead::LinkToEntity(Entity *entity) { Check(this); Check(entity); // // Remove existing entity, add new one // if (headEntitySocket.GetCurrent() != NULL) { headEntitySocket.Remove(); } headEntitySocket.Add(entity); alDistanceModel(AL_LINEAR_DISTANCE); alDopplerFactor(0.3f); #if 0 // // Make the new clipping sphere // clippingSphere.SetCurrentOrigin(entity->localOrigin.linearPosition); #endif } // //############################################################################# //############################################################################# // LinearMatrix AudioHead::GetEarToWorld() { Check(this); Entity *entity = headEntitySocket.GetCurrent(); Check(entity); return entity->localToWorld; } // //############################################################################# //############################################################################# // void AudioHead::Execute() { Check(this); // // Increment frame counter // // AUDIO CLOCK CALIBRATION FIX: AudioTime consumers (sequence event timing, // compression curves) assume audioFrameCount advances at the renderer's // calibrationRate (DefaultRendererRate = 30 frames/sec: // Seconds_To_Frames = s * rate). The WinTesla port set raw Now().ticks here // (~hundreds/sec), running sequences ~18x off the authored timing -- the // AudioControlSequence events carrying the real footstep volumes never // landed where authored. Convert ticks -> calibrated frames properly. { double tps = (double)SystemClock::GetTicksPerSecond(); if (tps <= 0.0) tps = 1000.0; // GetTickCount ms fallback (static not yet measured) audioFrameCount = (AudioFrameCount)( (double)Now().ticks * (double)application->GetAudioRenderer()->GetCalibrationRate() / tps); } Verify(audioFrameCount < LONG_MAX); if (getenv("BT_AUDIO_SPATIAL")) { static long s_hx=0; if ((++s_hx % 300)==0) DEBUG_STREAM << "[audioclock] frame=" << audioFrameCount << " execs=" << s_hx << "\n" << std::flush; } //set current listener orientation Vector3D headVelocity; headVelocity.MultiplyByInverse(this->GetHeadEntity()->GetWorldLinearVelocity(), this->GetHeadEntity()->localToWorld); alListener3f(AL_VELOCITY, -headVelocity.x, -headVelocity.y, -headVelocity.z); #if 0 // // Get the entity // Entity *entity = headEntitySocket.GetCurrent(); Check(entity); // // Make the new clipping sphere // clippingSphere.SetCurrentOrigin(entity->localOrigin.linearPosition); #endif } // //############################################################################# //############################################################################# // void AudioHead::DefineClippingSphere(Scalar radius) { Check(this); clippingRadius = radius; #if 0 // // Get entity position // Entity *entity; Point3D position(0.0f, 0.0f, 0.0f); if ((entity = headEntitySocket.GetCurrent()) != NULL) { Check(entity); position = entity->localOrigin.linearPosition; } // // Make the new clipping sphere // clippingSphere.SetCurrentOrigin(position); clippingSphere.SetReferenceRadius(radius); #endif } // //############################################################################# //############################################################################# // Logical AudioHead::IsPointClipped(const Point3D &point) { Check(this); Entity *entity; Vector3D difference; entity = headEntitySocket.GetCurrent(); Check(entity); difference.Subtract(entity->localOrigin.linearPosition, point); return difference.LengthSquared() > clippingRadius*clippingRadius; } // //############################################################################# //############################################################################# // void AudioHead::ControlDopplerEffect( Scalar doppler_constant, Scalar sound_speed ) { Check(this); audioDopplerConstant = doppler_constant; audioSoundSpeed = sound_speed; Check_Fpu(); } // //############################################################################# //############################################################################# // void AudioHead::ControlAmplitudeRollOff( Scalar exponent, Scalar amplitude_rolloff_knee, Scalar distance_scale ) { Check(this); amplitudeRollOffExponent = exponent; amplitudeRollOffKnee = amplitude_rolloff_knee; amplitudeRollOffDistanceScale = distance_scale; Check_Fpu(); } // //############################################################################# //############################################################################# // void AudioHead::ControlHighFrequencyRollOff( Scalar exponent, Scalar high_frequency_rolloff_knee, Scalar distance_scale ) { Check(this); highFrequencyRollOffExponent = exponent; highFrequencyRollOffKnee = high_frequency_rolloff_knee; highFrequencyRollOffDistanceScale = distance_scale; Check_Fpu(); } // //############################################################################# //############################################################################# // void AudioHead::ControlSourceCompression( Scalar exponent, Scalar scale ) { Check(this); sourceCompressionExponent = exponent; sourceCompressionScale = scale; Check_Fpu(); } // //############################################################################# //############################################################################# // void AudioHead::SetPositionalCulling(Logical) { Check(this); Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioComponent ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // //############################################################################# //############################################################################# // const Receiver::HandlerEntry AudioComponent::MessageHandlerEntries[]= { { AudioComponent::ReceiveControlMessageID, "ReceiveControl", (AudioComponent::Handler)&AudioComponent::ReceiveControlMessageHandler } }; AudioComponent::MessageHandlerSet& AudioComponent::GetMessageHandlers() { static AudioComponent::MessageHandlerSet messageHandlers(ELEMENTS(AudioComponent::MessageHandlerEntries), AudioComponent::MessageHandlerEntries, Component::GetMessageHandlers()); return messageHandlers; } // //############################################################################# //############################################################################# // Derivation* AudioComponent::GetClassDerivations() { static Derivation classDerivations(Component::GetClassDerivations(), "AudioComponent"); return &classDerivations; } AudioComponent::SharedData AudioComponent::DefaultData( AudioComponent::GetClassDerivations(), AudioComponent::GetMessageHandlers() ); // //############################################################################# //############################################################################# // AudioComponent::AudioComponent( PlugStream *stream, SharedData &shared_data ): Component(stream, shared_data), audioWatcherSocket(NULL) { nextExecuteWatcherFrame = NullAudioFrameCount; } // //############################################################################# //############################################################################# // AudioComponent::~AudioComponent() { } // //############################################################################# //############################################################################# // Logical AudioComponent::TestInstance() const { if (!IsDerivedFrom(*GetClassDerivations())) { return False; } Check(&audioWatcherSocket); return True; } // //############################################################################# //############################################################################# // void AudioComponent::ExecuteWatchers() { Check(this); // // Execute watchers if this is the next watcher frame // AudioFrameCount audio_frame_count; Check(application); Check(application->GetAudioRenderer()); audio_frame_count = application->GetAudioRenderer()->GetAudioFrameCount(); if (nextExecuteWatcherFrame <= audio_frame_count) { nextExecuteWatcherFrame = audio_frame_count + DefaultAudioFrameDelay; // // Execute watchers // ChainIteratorOf iterator(&audioWatcherSocket); Component *component; while ((component = iterator.ReadAndNext()) != NULL) { Check(component); component->Execute(); } } } // //############################################################################# //############################################################################# // void AudioComponent::Execute() { Check(this); ExecuteWatchers(); Check_Fpu(); } // //############################################################################# //############################################################################# // void AudioComponent::ReceiveControl( AudioControlID, AudioControlValue ) { Fail("AudioComponent::ReceiveControl - Should never reach here"); } // //############################################################################# //############################################################################# // void AudioComponent::PostReceiveControl( AudioControlID control_ID, AudioControlValue control_value ) { Check(this); ReceiveControlMessage message(control_ID, control_value); Check(application); // ECH 1/26/96 - application->Post(HighEventPriority, this, &message); application->Post(DefaultEventPriority, this, &message); Check_Fpu(); } // //############################################################################# //############################################################################# // void AudioComponent::ReceiveControlMessageHandler(ReceiveControlMessage *message) { Check(this); Check(message); ReceiveControl(message->controlID, message->controlValue); Check_Fpu(); } //~~~~~~~~~~~~~~~~~~ AudioComponent__ReceiveControlMessage ~~~~~~~~~~~~~~~~~~~~ AudioComponent__ReceiveControlMessage::AudioComponent__ReceiveControlMessage( AudioControlID control_ID, AudioControlValue control_value ): Receiver::Message( AudioComponent::ReceiveControlMessageID, sizeof(AudioComponent__ReceiveControlMessage) ) { controlID = control_ID; controlValue = control_value; }