#include "mungal4.h" #pragma hdrstop #include "l4audres.h" #include "l4audhdw.h" #include "l4audio.h" #include "l4audlvl.h" #include "l4audwtr.h" #include "..\munga\audcmp.h" #include "..\munga\audseq.h" #include "..\munga\audrend.h" #include "..\munga\namelist.h" #include "..\munga\app.h" #include "..\munga\notation.h" #include "openal\al.h" #include "sndfile.h" ALuint *g_buffers; int g_numBuffers; //############################################################################# //####################### AudioObjectStream ############################# //############################################################################# // //############################################################################# // AudioObjectStream //############################################################################# // AudioObjectStream::AudioObjectStream( ResourceDescription *resource_description, Entity *the_entity ): PlugStream(resource_description) { entity = the_entity; } // //############################################################################# // AudioObjectStream //############################################################################# // AudioObjectStream::AudioObjectStream() { entity = NULL; } // //############################################################################# // ~AudioObjectStream //############################################################################# // AudioObjectStream::~AudioObjectStream() { } // //############################################################################# // TestInstance //############################################################################# // Logical AudioObjectStream::TestInstance() const { PlugStream::TestInstance(); if (entity != NULL) { Check(entity); } return True; } // //############################################################################# // MakeObjectImplementation //############################################################################# // RegisteredClass* AudioObjectStream::MakeObjectImplementation(Enumeration class_ID) { Check(this); Verify(class_ID != RegisteredClass::NullClassID); // //----------------------------------------------------------------------- // HACK - Constructors should be referenced through registration, for // now just use a switch statement //----------------------------------------------------------------------- // RegisteredClass *object; switch (class_ID) { // // Static resources ... // case RegisteredClass::PatchLevelOfDetailClassID: object = new PatchLevelOfDetail(this); break; case RegisteredClass::PatchResourceClassID: object = new PatchResource(this); break; case RegisteredClass::AudioResourceIndexClassID: object = new AudioResourceIndex(this); break; // // Location and sources ... // case RegisteredClass::L4AudioLocationClassID: object = new L4AudioLocation(this, entity); break; case RegisteredClass::DirectPatchSourceClassID: object = new DirectPatchSource(this, entity); break; case RegisteredClass::Dynamic3DPatchSourceClassID: object = new Dynamic3DPatchSource(this, entity); break; case RegisteredClass::Static3DPatchSourceClassID: object = new Static3DPatchSource(this, entity); break; // // Audio components ... // case RegisteredClass::AudioControlMixerClassID: object = new AudioControlMixer(this, entity); break; case RegisteredClass::AudioControlMultiplierClassID: object = new AudioControlMultiplier(this, entity); break; case RegisteredClass::AudioResourceSelectorClassID: object = new AudioResourceSelector(this, entity); break; case RegisteredClass::AudioControlSmootherClassID: object = new AudioControlSmoother(this, entity); break; case RegisteredClass::AudioSampleAndHoldClassID: object = new AudioSampleAndHold(this, entity); break; case RegisteredClass::AudioControlSendClassID: object = new AudioControlSend(this, entity); break; case RegisteredClass::AudioControlSequenceClassID: object = new AudioControlSequence(this, entity); break; case RegisteredClass::AudioControlSplitterClassID: object = new AudioControlSplitter(this, entity); break; case RegisteredClass::AudioLFOClassID: object = new AudioLFO(this, entity); break; // // Audio watchers ... // case RegisteredClass::AudioMotionTriggerClassID: object = new AudioMotionTrigger(this, entity); break; case RegisteredClass::AudioMotionScaleClassID: object = new AudioMotionScale(this, entity); break; case RegisteredClass::AudioHingeScaleClassID: object = new AudioHingeScale(this, entity); break; case RegisteredClass::AudioScalarTriggerClassID: object = new AudioScalarTrigger(this, entity); break; case RegisteredClass::AudioScalarScaleClassID: object = new AudioScalarScale(this, entity); break; case RegisteredClass::AudioLogicalTriggerClassID: object = new AudioLogicalTrigger(this, entity); break; case RegisteredClass::AudioEnumerationTriggerClassID: object = new AudioEnumerationTrigger(this, entity); break; case RegisteredClass::AudioIntegerTriggerClassID: object = new AudioIntegerTrigger(this, entity); break; case RegisteredClass::AudioControlsButtonTriggerClassID: object = new AudioControlsButtonTrigger(this, entity); break; case RegisteredClass::AudioStateTriggerClassID: object = new AudioStateTrigger(this, entity); break; case RegisteredClass::AudioIdleWatcherClassID: object = new AudioIdleWatcher(this, entity); break; case RegisteredClass::AudioEnumerationDeltaTriggerClassID: object = new AudioEnumerationDeltaTrigger(this, entity); break; case RegisteredClass::AudioScalarDeltaTriggerClassID: object = new AudioScalarDeltaTrigger(this, entity); break; case RegisteredClass::L4AudioCollisionTriggerClassID: object = new L4AudioCollisionTrigger(this, entity); break; case RegisteredClass::AudioMessageWatcherClassID: object = new AudioMessageWatcher(this, entity); break; case RegisteredClass::AudioControlsButtonMessageWatcherClassID: object = new AudioControlsButtonMessageWatcher(this, entity); break; // // Inherited behavior // default: object = PlugStream::MakeObjectImplementation(class_ID); break; } return object; } // //############################################################################# // CreatedObjectImplementation //############################################################################# // void AudioObjectStream::CreatedObjectImplementation( RegisteredClass *object, ObjectID object_ID ) { Check(this); Check(object); Verify(object_ID != NullObjectID); // // std::Decide which index to add object to // switch (object->GetClassID()) { case RegisteredClass::PatchLevelOfDetailClassID: case RegisteredClass::PatchResourceClassID: case RegisteredClass::AudioResourceIndexClassID: AddGlobalPlug(Cast_Object(Plug*, object), object_ID); break; default: AddLocalPlug(Cast_Object(Plug*, object), object_ID); break; } } // //############################################################################# // BuildFromPageImplementation //############################################################################# // void AudioObjectStream::BuildFromPageImplementation( NameList *name_list, Enumeration class_ID_enumeration, ObjectID object_ID ) { Check(this); Verify(class_ID_enumeration != RegisteredClass::NullClassID); Verify(object_ID != NullObjectID); // //----------------------------------------------------------------------- // HACK - Page interpreters should be referenced through registration, // for now just use a switch statement //----------------------------------------------------------------------- // RegisteredClass::ClassID class_ID = (RegisteredClass::ClassID)class_ID_enumeration; switch (class_ID) { // // Static resources ... // case RegisteredClass::PatchLevelOfDetailClassID: PatchLevelOfDetail::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::PatchResourceClassID: PatchResource::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioResourceIndexClassID: AudioResourceIndex::BuildFromPage(this, name_list, class_ID, object_ID); break; // // Location and sources ... // case RegisteredClass::L4AudioLocationClassID: L4AudioLocation::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::DirectPatchSourceClassID: DirectPatchSource::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::Dynamic3DPatchSourceClassID: Dynamic3DPatchSource::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::Static3DPatchSourceClassID: Static3DPatchSource::BuildFromPage(this, name_list, class_ID, object_ID); break; // // Audio components ... // case RegisteredClass::AudioControlMixerClassID: AudioControlMixer::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioControlMultiplierClassID: AudioControlMultiplier::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioResourceSelectorClassID: AudioResourceSelector::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioControlSmootherClassID: AudioControlSmoother::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioSampleAndHoldClassID: AudioSampleAndHold::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioControlSendClassID: AudioControlSend::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioControlSequenceClassID: AudioControlSequence::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioControlSplitterClassID: AudioControlSplitter::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioLFOClassID: AudioLFO::BuildFromPage(this, name_list, class_ID, object_ID); break; // // Audio watchers ... // case RegisteredClass::AudioMotionTriggerClassID: AudioMotionTrigger::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioMotionScaleClassID: AudioMotionScale::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioHingeScaleClassID: AudioHingeScale::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioScalarTriggerClassID: AudioScalarTrigger::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioScalarScaleClassID: AudioScalarScale::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioLogicalTriggerClassID: AudioLogicalTrigger::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioEnumerationTriggerClassID: AudioEnumerationTrigger::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioIntegerTriggerClassID: AudioIntegerTrigger::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioControlsButtonTriggerClassID: AudioControlsButtonTrigger::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioStateTriggerClassID: AudioStateTrigger::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioIdleWatcherClassID: AudioIdleWatcher::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioEnumerationDeltaTriggerClassID: AudioEnumerationDeltaTrigger::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioScalarDeltaTriggerClassID: AudioScalarDeltaTrigger::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::L4AudioCollisionTriggerClassID: L4AudioCollisionTrigger::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioMessageWatcherClassID: AudioMessageWatcher::BuildFromPage(this, name_list, class_ID, object_ID); break; case RegisteredClass::AudioControlsButtonMessageWatcherClassID: AudioControlsButtonMessageWatcher::BuildFromPage(this, name_list, class_ID, object_ID); break; // // Inherited behavior // default: PlugStream::BuildFromPageImplementation(name_list, class_ID, object_ID); break; } } // //############################################################################# // BuiltFromPageImplementation //############################################################################# // void AudioObjectStream::BuiltFromPageImplementation( Enumeration class_ID, ObjectID object_ID, const CString &object_name ) { Check(this); Verify(class_ID != RegisteredClass::NullClassID); Verify(object_ID != NullObjectID); Check(&object_name); // // std::Decide which index to add object to // if (object_name.Length() == 0) return; switch (class_ID) { case RegisteredClass::PatchLevelOfDetailClassID: case RegisteredClass::PatchResourceClassID: case RegisteredClass::AudioResourceIndexClassID: AddGlobalObjectID(object_ID, object_name); break; default: AddLocalObjectID(object_ID, object_name); break; } } //############################################################################# //###################### L4AudioResourceManager ######################### //############################################################################# // //############################################################################# // L4AudioResourceManager //############################################################################# // L4AudioResourceManager::L4AudioResourceManager() { g_buffers = NULL; g_numBuffers = 0; } // //############################################################################# // ~L4AudioResourceManager //############################################################################# // L4AudioResourceManager::~L4AudioResourceManager() { } // //############################################################################# // TestInstance //############################################################################# // Logical L4AudioResourceManager::TestInstance() const { Node::TestInstance(); return True; } // //############################################################################# // PreloadResources //############################################################################# // void L4AudioResourceManager::PreloadResources( NotationFile *notation_file ) { Check(this); Check(notation_file); //Check(audio_hardware); //Determine how many loadable samples exist g_numBuffers=0; for(int i=1; i <= 2; i++) { for (int j=0; j < 100; j++) { if (PRESET_isImplemented(i,j)) { g_numBuffers += PRESET_getNumSamples(i,j); } } } //Generate the buffers if (g_numBuffers > 0) { //Generate buffers alGetError(); g_buffers = new ALuint[g_numBuffers]; alGenBuffers(g_numBuffers,g_buffers); ALenum error; if ((error = alGetError()) != AL_NO_ERROR) { DEBUG_STREAM << "OpenAL has encountered an error while initializing the buffers." << std::endl; delete [] g_buffers; g_buffers = NULL; g_numBuffers = 0; } } int bufferInd = 0; //Load buffers for(int i=1; i<=2 && bufferInd < g_numBuffers; i++) { for(int j=0; j<100 && bufferInd < g_numBuffers; j++) { if (PRESET_isImplemented(i,j)) { for (int k=0; k < PRESET_getNumSamples(i,j) && bufferInd < g_numBuffers; k++) { SAMPLEINFO info = PRESET_getSampleInfo(i,j,k); //Load WAV to buffer char *data; int size; //Open WAV char fullname[50]; strcpy_s(fullname,50,"AUDIO\\"); strcat_s(fullname,50,info.file); SF_INFO *sfInfo = new SF_INFO[2]; //SF_INFO is working different than expected! sfInfo->format = 0; SNDFILE *file = sf_open(fullname,SFM_READ,sfInfo); if (file == NULL) { DEBUG_STREAM << "Failed to open." << std::endl; } unsigned long formatBits = 0; unsigned long sampleRate = sfInfo->samplerate; size = sfInfo->frames; bool isMono = (sfInfo->channels == 1); if (sfInfo->format & SF_FORMAT_PCM_S8) { formatBits = 8; } else if (sfInfo->format & SF_FORMAT_PCM_16) { formatBits = 16; } else { DEBUG_STREAM << "BAD FORMAT" << std::endl; } ALenum format; if (formatBits == 8) { if (isMono) { format = AL_FORMAT_MONO8; } else { size *= 2; format = AL_FORMAT_STEREO8; } } else if (formatBits == 16) { size *= 2; if (isMono) { format = AL_FORMAT_MONO16; } else { size *= 2; format = AL_FORMAT_STEREO16; } } ALsizei alSampleRate = sampleRate; //Load size & data delete [] sfInfo; data = new char[size]; sf_read_raw(file,data,size); sf_close(file); //Feed the buffer alBufferData(g_buffers[bufferInd],format,data,size,alSampleRate); PRESET_setBufferIndex(i,j,k,bufferInd); bufferInd++; delete [] data; } } } } // //---------------------------------------------------------------------- // Load the sound banks //---------------------------------------------------------------------- // /*NameList *name_list; NameList::Entry *entry; Verify(notation_file->EntryCount("AudioResources") >= 2); name_list = notation_file->MakeEntryList("AudioResources"); Register_Object(name_list); entry = name_list->GetFirstEntry(); Check(entry); while (entry != NULL) { Check(entry); if (entry->IsName("front_audio_resource")) { Check_Pointer(entry->GetChar()); Check(audio_hardware->GetFrontCard()); audio_hardware->GetFrontCard()->LoadSBK(entry->GetChar()); } else { Verify(entry->IsName("rear_audio_resource")); Check_Pointer(entry->GetChar()); Check(audio_hardware->GetRearCard()); audio_hardware->GetRearCard()->LoadSBK(entry->GetChar()); } entry = entry->GetNextEntry(); } Unregister_Object(name_list); delete name_list;*/ // //---------------------------------------------------------------------- // Create static audio objects //---------------------------------------------------------------------- // // // Get static audio stream resource // ResourceDescription *resource_description; Check(application); Check(application->GetResourceFile()); resource_description = application->GetResourceFile()->FindResourceDescription( "StaticAudioStream", ResourceDescription::StaticAudioStreamResourceType ); Check(resource_description); resource_description->Lock(); // // Parse the audio object stream // AudioObjectStream audio_object_stream(resource_description, NULL); Check(&audio_object_stream); audio_object_stream.CreateObjects(); resource_description->Unlock(); } ALuint AL_getBuffer(int index) { return g_buffers[index]; } // //############################################################################# // UnloadResources //############################################################################# // void L4AudioResourceManager::UnloadResources( ) { Check(this); // Check(audio_hardware); //Unload wav data if (g_numBuffers > 0) { alGetError(); alDeleteBuffers(g_numBuffers,g_buffers); ALenum error = alGetError(); if (error != AL_NO_ERROR) { DEBUG_STREAM << "OpenAL reached an error when attempting to delete its buffers." << std::endl; } } // //---------------------------------------------------------------------- // Release banks //---------------------------------------------------------------------- // // Check(audio_hardware->GetFrontCard()); // audio_hardware->GetFrontCard()->ReleaseAllBanks(); // Check(audio_hardware->GetRearCard()); // audio_hardware->GetRearCard()->ReleaseAllBanks(); } // //############################################################################# // CreateStaticAudioStreamResource //############################################################################# // ResourceDescription::ResourceID L4AudioResourceManager::CreateStaticAudioStreamResource( ResourceFile *resource_file ) { Check(resource_file); // //---------------------------------------------------------------------- // Open the notation file for the static stream resource //---------------------------------------------------------------------- // Tell("Opening Audio Script audio\\static.scp\n"); NotationFile notation_file("audio\\static.scp"); Check(¬ation_file); // //---------------------------------------------------------------------- // Build the static audio object stream //---------------------------------------------------------------------- // AudioObjectStream audio_object_stream; Check(&audio_object_stream); audio_object_stream.BuildFromNotationFile(¬ation_file, resource_file); Tell("Closed Audio Script\n"); // //---------------------------------------------------------------------- // Add the resource //---------------------------------------------------------------------- // ResourceDescription *res_description; res_description = resource_file->AddResourceMemoryStream( "StaticAudioStream", ResourceDescription::StaticAudioStreamResourceType, 1, ResourceDescription::Preload, &audio_object_stream ); Check(res_description); return res_description->resourceID; } // //############################################################################# // CreateEntityAudioObjects //############################################################################# // void L4AudioResourceManager::CreateEntityAudioObjects( Entity *entity, AudioRepresentation audio_representation ) { Check(this); Check(entity); Verify( audio_representation == InternalAudioRepresentation || audio_representation == ExternalAudioRepresentation ); // //------------------------------------------------------------------------ // Read the audio resource for this entity //------------------------------------------------------------------------ // ResourceDescription *audio_resource_description; Check(application); Check(application->GetResourceFile()); audio_resource_description = application->GetResourceFile()->SearchList( entity->GetResourceID(), ResourceDescription::AudioStreamListResourceType ); if (audio_resource_description == NULL) return; // //------------------------------------------------------------------------ // Read the appropriate resource for an internal or external // representation //------------------------------------------------------------------------ // ResourceDescription *stream_resource_description; Check(application); Check(application->GetResourceFile()); Check(audio_resource_description); stream_resource_description = application->GetResourceFile()->SearchList( audio_resource_description->resourceID, (audio_representation == InternalAudioRepresentation) ? ResourceDescription::InternalAudioStreamResourceType : ResourceDescription::ExternalAudioStreamResourceType ); if (stream_resource_description == NULL) return; Check(stream_resource_description); stream_resource_description->Lock(); audio_resource_description->Lock(); // //------------------------------------------------------------------------ // Make the audio object stream //------------------------------------------------------------------------ // AudioObjectStream audio_object_stream( stream_resource_description, entity ); Check(&audio_object_stream); audio_object_stream.CreateObjects(); stream_resource_description->Unlock(); audio_resource_description->Unlock(); } // //############################################################################# // DestroyEntityAudioObjects //############################################################################# // void L4AudioResourceManager::DestroyEntityAudioObjects(Entity *entity) { Check(this); Check(entity); // //-------------------------------------------------------------------------- // Stop and delete all audio objects //-------------------------------------------------------------------------- // Entity::AudioSocketIterator iterator(entity); Component *component; AudioComponent *audio_component; Check(&iterator); while ((component = iterator.ReadAndNext()) != NULL) { audio_component = Cast_Object(AudioComponent*, component); Check(audio_component); audio_component->ReceiveControl(StopAudioControlID, 0.0f); audio_component->ReceiveControl(FlushMessagesAudioControlID, 0.0f); } iterator.DeletePlugs(); } // //############################################################################# // CreateModelAudioResource //############################################################################# // ResourceDescription::ResourceID L4AudioResourceManager::CreateModelAudioStreamResource( ResourceFile *resource_file, const char *model_name, NotationFile *model_file, const ResourceDirectories* ) { Check(resource_file); Check_Pointer(model_name); Check(model_file); const char *script_name = NULL; ResourceDescription::ResourceID resource_id_list[3]; size_t list_length = 0; resource_id_list[0] = ResourceDescription::NullResourceID; resource_id_list[1] = ResourceDescription::NullResourceID; resource_id_list[2] = ResourceDescription::NullResourceID; // //-------------------------------------------------------------------------- // Check for the external audio script //-------------------------------------------------------------------------- // if (model_file->GetEntry("audio", "external", &script_name)) { // // See if the resource already exists // ResourceDescription *res_description = resource_file->FindResourceDescription( script_name, ResourceDescription::ExternalAudioStreamResourceType ); // //----------------------------------------------------------------------- // If not, create it //----------------------------------------------------------------------- // if (res_description == NULL) { // // Make the file name // CString file_name(script_name); CString prefix("audio\\"); file_name = prefix + file_name; // // Build the memory stream // Tell("Opening Audio Script " << file_name << "\n"); NotationFile script_file(file_name); AudioObjectStream audio_object_stream; Check(&script_file); Check(&audio_object_stream); audio_object_stream.BuildFromNotationFile(&script_file, resource_file); Tell("Closed Audio Script\n"); // // Add the resource // res_description = resource_file->AddResourceMemoryStream( script_name, ResourceDescription::ExternalAudioStreamResourceType, 1, ResourceDescription::Preload, &audio_object_stream ); } Check(res_description); resource_id_list[list_length++] = res_description->resourceID; } // //-------------------------------------------------------------------------- // Check for the internal audio script //-------------------------------------------------------------------------- // if (model_file->GetEntry("audio", "internal", &script_name)) { // // See if the resource already exists // ResourceDescription *res_description = resource_file->FindResourceDescription( script_name, ResourceDescription::InternalAudioStreamResourceType ); // // If not, create it // if (res_description == NULL) { // // Make the file name // CString file_name(script_name); CString prefix("audio\\"); file_name = prefix + file_name; // // Build the memory stream // Tell("Opening Audio Script " << file_name << "\n"); NotationFile script_file(file_name); AudioObjectStream audio_object_stream; Check(&script_file); Check(&audio_object_stream); audio_object_stream.BuildFromNotationFile(&script_file, resource_file); Tell("Closed Audio Script\n"); // // Add the resource // res_description = resource_file->AddResourceMemoryStream( script_name, ResourceDescription::InternalAudioStreamResourceType, 1, ResourceDescription::Preload, &audio_object_stream ); } Check(res_description); resource_id_list[list_length++] = res_description->resourceID; } // //-------------------------------------------------------------------------- // Check for the audio entity model //-------------------------------------------------------------------------- // const char *audio_entity_model = NULL; if (model_file->GetEntry("audio", "model", &audio_entity_model)) { // // The resource should already exist // ResourceDescription *res_description = resource_file->FindResourceDescription( audio_entity_model, ResourceDescription::ModelListResourceType ); if (res_description == NULL) { std::cout << "audio_entity_model == " << audio_entity_model; Fail("L4AudioResourceManager::CreateModelAudioStreamResource - model not found"); } Check(res_description); resource_id_list[list_length++] = res_description->resourceID; } // //-------------------------------------------------------------------------- // If either script has been created, then create the resource list //-------------------------------------------------------------------------- // if (list_length > 0) { ResourceDescription *res_description = resource_file->AddResourceList( model_name, ResourceDescription::AudioStreamListResourceType, 1, ResourceDescription::Preload, resource_id_list, list_length ); Check(res_description); return res_description->resourceID; } return ResourceDescription::NullResourceID; }