#include "munga.h" #pragma hdrstop #include "audrend.h" #include "audent.h" #include "jmover.h" #include "app.h" //############################################################################# //########################### AudioRenderer ############################# //############################################################################# // //############################################################################# // AudioRenderer //############################################################################# // AudioRenderer::AudioRenderer(RendererRate render_rate): Renderer( render_rate, MaxRendererComplexity, DefaultRendererPriority, AudioInterestType, DefaultInterestDepth, AudioRendererClassID ), audioEventSocket(NULL, False) { audioHead = NULL; #ifdef LAB_ONLY sourceClippedCount = 0; sourceStartCount = 0; sourceSuspendCount = 0; sourceResumeCount = 0; doubleTriggerCount = 0; resourceStealCount = 0; resourceStealPriorityCount = 0; resourceStealVolumeCount = 0; stealShortDurationCount = 0; #endif } // //############################################################################# // ~AudioRenderer //############################################################################# // AudioRenderer::~AudioRenderer() { Unregister_Object(audioHead); delete audioHead; #ifdef LAB_ONLY cout << "AudioRenderer::~AudioRenderer - sourceClippedCount=" << sourceClippedCount << "\n"; cout << "AudioRenderer::~AudioRenderer - sourceStartCount=" << sourceStartCount << "\n"; cout << "AudioRenderer::~AudioRenderer - sourceSuspendCount=" << sourceSuspendCount << "\n"; cout << "AudioRenderer::~AudioRenderer - sourceResumeCount=" << sourceResumeCount << "\n"; cout << "AudioRenderer::~AudioRenderer - doubleTriggerCount=" << doubleTriggerCount << "\n"; cout << "AudioRenderer::~AudioRenderer - resourceStealCount=" << resourceStealCount << "\n"; cout << "AudioRenderer::~AudioRenderer - resourceStealPriorityCount=" << resourceStealPriorityCount << "\n"; cout << "AudioRenderer::~AudioRenderer - resourceStealVolumeCount=" << resourceStealVolumeCount << "\n"; cout << "AudioRenderer::~AudioRenderer - stealShortDurationCount=" << stealShortDurationCount << "\n"; #endif } // //############################################################################# // Initialize //############################################################################# // void AudioRenderer::Initialize() { audioHead = MakeAudioHead(); Register_Object(audioHead); } // //############################################################################# // TestInstance //############################################################################# // Logical AudioRenderer::TestInstance() const { Renderer::TestInstance(); if (audioHead != NULL) { Check(audioHead); } Check(&audioEventSocket); return True; } // //############################################################################# // LinkToEntity //############################################################################# // void AudioRenderer::LinkToEntity(Entity *entity) { Check(this); Check(entity); // //-------------------------------------------------------------------------- // Link the head to the entity //-------------------------------------------------------------------------- // Check(audioHead); audioHead->LinkToEntity(entity); // //-------------------------------------------------------------------------- // Call inherited method //-------------------------------------------------------------------------- // Renderer::LinkToEntity(entity); } // //############################################################################# // ExecuteImplementation //############################################################################# // void AudioRenderer::ExecuteImplementation( RendererComplexity, RendererOrigin::InterestingEntityIterator* ) { Check(this); Check(audioHead); audioHead->Execute(); } // //############################################################################# // PostAudioRequestMessage //############################################################################# // void AudioRenderer::PostAudioRequestMessage( AudioSource *audio_source, AudioSource::RequestMessage *message ) { Check(this); Check(audio_source); Check(message); // //-------------------------------------------------------------------------- // If audio source is clipped and the source is transient // Then ignore // Else set priority and volume //-------------------------------------------------------------------------- // AudioSourcePriority audio_source_priority; AudioControlValue audio_source_volume_scale; if (audio_source->IsAudioSourceClipped(GetAudioHead())) { if (getenv("BT_AUDIO_SPATIAL")) { static int s_cl=0; if (s_cl++<40) DEBUG_STREAM << "[spatial] CLIPPED src=" << (void*)audio_source << " headPos=(" << GetAudioHead()->GetHeadEntity()->localOrigin.linearPosition.x << "," << GetAudioHead()->GetHeadEntity()->localOrigin.linearPosition.z << ")\n" << std::flush; } // // If it is a transient source then ignore request // if (audio_source->GetAudioRenderType() == TransientAudioRenderType) { #ifdef LAB_ONLY sourceClippedCount++; #endif return; } audio_source_priority = audio_source->GetAudioSourcePriority(); audio_source_volume_scale = 0.0f; } else { audio_source_priority = audio_source->GetAudioSourcePriority(); audio_source_volume_scale = audio_source->CalculateSourceVolumeScale(); if (getenv("BT_AUDIO_SPATIAL")) { static int s_vs=0; if ((s_vs++ % 120)==0) DEBUG_STREAM << "[spatial] request src=" << (void*)audio_source << " vol=" << audio_source_volume_scale << " headPos=(" << GetAudioHead()->GetHeadEntity()->localOrigin.linearPosition.x << "," << GetAudioHead()->GetHeadEntity()->localOrigin.linearPosition.z << ")\n" << std::flush; } } // //-------------------------------------------------------------------------- // If this a transient source and volume is lower than threshold // Then return //-------------------------------------------------------------------------- // if ( message->controlID == StartAudioControlID && audio_source->GetAudioRenderType() == TransientAudioRenderType && audio_source_volume_scale < LowAudioVolumeThreshold ) { if (getenv("BT_AUDIO_SPATIAL")) { static int s_dr=0; if (s_dr++<40) DEBUG_STREAM << "[spatial] DROP transient start src=" << (void*)audio_source << " vol=" << audio_source_volume_scale << " (below threshold " << LowAudioVolumeThreshold << ")\n" << std::flush; } #ifdef LAB_ONLY sourceClippedCount++; #endif return; } if (getenv("BT_AUDIO_SPATIAL") && message->controlID == StartAudioControlID) { static int s_st=0; if (s_st++<40) DEBUG_STREAM << "[spatial] START request src=" << (void*)audio_source << " vol=" << audio_source_volume_scale << "\n" << std::flush; } // //-------------------------------------------------------------------------- // Create audio weight based on priority and volume // Add audio event //-------------------------------------------------------------------------- // AudioWeighting audio_weight(audio_source_priority, audio_source_volume_scale); AudioEvent *audio_event; audio_event = new AudioEvent(audio_source, message); Register_Object(audio_event); audioEventSocket.AddValue(audio_event, audio_weight); } // //############################################################################# // ProcessAudioRequestMessage //############################################################################# // Logical AudioRenderer::ProcessAudioRequestMessage() { // // Process high priority, high volume event // AudioEventIterator iterator(&audioEventSocket); AudioEvent *audio_event; Logical stuff = False; while ((audio_event = iterator.GetCurrent()) != NULL) { stuff = True; Check(audio_event); audio_event->Process(); //return True; } return stuff; } // //############################################################################# // FlushAudioMessages //############################################################################# // void AudioRenderer::FlushAudioMessages(AudioSource *audio_source) { Check(this); Check(audio_source); // // Process matching events // AudioEventIterator iterator(&audioEventSocket); AudioEvent *audio_event; while ((audio_event = iterator.ReadAndNext()) != NULL) { Check(audio_event); if (audio_event->targetReceiver.GetCurrent() == audio_source) { if (audio_event->messageToSend->controlID == StopAudioControlID) { audio_event->Process(); } else { Unregister_Object(audio_event); delete audio_event; } } } } // //############################################################################# // MakeAudioHead //############################################################################# // AudioHead* AudioRenderer::MakeAudioHead() { return new AudioHead; } // //############################################################################# // StartEntityEffectImplementation //############################################################################# // void AudioRenderer::StartEntityEffectImplementation( Entity *parent_entity, DamageZone *damage_zone, ResourceDescription::ResourceID resource_ID ) { SET_AUDIO_RENDERER(); Check(this); Check(parent_entity); Check(damage_zone); Verify(resource_ID != ResourceDescription::NullResourceID); // //-------------------------------------------------------------------------- // Get the audio resource for this effect //-------------------------------------------------------------------------- // ResourceDescription *audio_resource_description; Check(application); Check(application->GetResourceFile()); audio_resource_description = application->GetResourceFile()->SearchList( resource_ID, ResourceDescription::AudioStreamListResourceType ); if (audio_resource_description == NULL) { CLEAR_AUDIO_RENDERER(); return; } Check(audio_resource_description); // //-------------------------------------------------------------------------- // Get the resource ID for the model resource for the audio effect entity //-------------------------------------------------------------------------- // ResourceDescription *model_resource_description; Check(application); Check(application->GetResourceFile()); Check(audio_resource_description); model_resource_description = application->GetResourceFile()->SearchList( audio_resource_description->resourceID, ResourceDescription::ModelListResourceType ); if (model_resource_description == NULL) { CLEAR_AUDIO_RENDERER(); return; } Check(model_resource_description); model_resource_description->Lock(); audio_resource_description->Lock(); // //-------------------------------------------------------------------------- // Get the entity segment //-------------------------------------------------------------------------- // Entity *linked_entity; AudioRepresentation audio_representation; EntitySegment *parent_entity_segment; linked_entity = GetLinkedEntity(); Check(linked_entity); audio_representation = (AudioRepresentation)parent_entity->GetAudioRepresentation( linked_entity ); parent_entity_segment = damage_zone->GetCurrentEffectSite( (audio_representation == InternalAudioRepresentation) ? DamageZone::InternalAudioEffectSite : DamageZone::ExternalAudioEffectSite ); Check(parent_entity_segment); // //-------------------------------------------------------------------------- // Create the audio effect entity with this resource //-------------------------------------------------------------------------- // JointedMover *jointed_mover; Verify(parent_entity->IsDerivedFrom(JointedMover::GetClassDerivations())); jointed_mover = Cast_Object(JointedMover*, parent_entity); Check(jointed_mover); AudioEntity::MakeMessage make_message( model_resource_description->resourceID, jointed_mover, parent_entity_segment ); #if DEBUG_LEVEL>0 AudioEntity *audio_entity = #endif AudioEntity::Make(&make_message); Register_Object(audio_entity); model_resource_description->Unlock(); audio_resource_description->Unlock(); CLEAR_AUDIO_RENDERER(); } //~~~~~~~~~~~~~~~~~~~~~~~~ AudioRenderer profile bits ~~~~~~~~~~~~~~~~~~~~~~~~~ #if defined(TRACE_AUDIO_RENDERER) BitTrace Audio_Renderer("Audio Renderer"); #endif #if defined(TRACE_AUDIO_RENDERER_CREATE_OBJECTS) BitTrace Audio_Renderer_Create_Objects("Audio Renderer Create Objects"); #endif #if defined(TRACE_AUDIO_RENDERER_DESTROY_OBJECTS) BitTrace Audio_Renderer_Destroy_Objects("Audio Renderer Destroy Objects"); #endif #if defined(TRACE_AUDIO_RENDERER_START_HANDLER) BitTrace Audio_Renderer_Start_Handler("Audio Renderer Start Handler"); #endif #if defined(TRACE_AUDIO_RENDERER_STOP_HANDLER) BitTrace Audio_Renderer_Stop_Handler("Audio Renderer Stop Handler"); #endif #if defined(TRACE_AUDIO_RENDERER_EXECUTE) BitTrace Audio_Renderer_Execute("Audio Renderer Execute"); #endif //############################################################################# //############################## AudioEvent ############################# //############################################################################# MemoryBlock *AudioEvent::GetAllocatedMemory() { static MemoryBlock allocatedMemory(sizeof(Event), AUDIOEVENT_MEMORYBLOCK_ALLOCATION, AUDIOEVENT_MEMORYBLOCK_ALLOCATION, "AudioEvents"); return &allocatedMemory; } // //############################################################################# //############################################################################# // AudioEvent::AudioEvent( AudioSource *target, AudioSource::RequestMessage *message ): targetReceiver(this) { Check(target); Check(message); // // Store the message // size_t long_size = (message->messageLength+3)>>2; messageToSend = (AudioSource::RequestMessage*)new long[long_size]; Check_Pointer(messageToSend); Register_Pointer(messageToSend); Mem_Copy( messageToSend, message, message->messageLength, long_size*sizeof(long) ); // // Store the target receiver // targetReceiver.Add(target); } // //############################################################################# //############################################################################# // AudioEvent::~AudioEvent() { Unregister_Pointer(messageToSend); delete messageToSend; } // //############################################################################# //############################################################################# // void AudioEvent::ReleaseLinkHandler( Socket*, Plug* ) { Unregister_Object(this); delete this; }