//===========================================================================// // File: AudioRenderer.cpp // // Project: MUNGA Brick: Video Renderer // // Contents: Abstracted Base Video Renderer // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 03/04/97 JTR Initial coding. // //---------------------------------------------------------------------------// // Copyright (C) 1997, Virtual World Entertainment, Inc. // // All Rights reserved worldwide // // This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // //===========================================================================// #include "AdeptHeaders.hpp" #include "AudioChannel.hpp" #include "AudioSample.hpp" #include "AudioRenderer.hpp" #include "AudioCommand.hpp" //########################################################################## //############################ AudioChannel ########################## //########################################################################## AudioChannel::ClassData* AudioChannel::DefaultData = NULL; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void AudioChannel::InitializeClass() { Verify(!DefaultData); DefaultData = new ClassData( AudioChannelClassID, "Adept::AudioChannel", BaseClass::DefaultData ); Register_Object(DefaultData); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void AudioChannel::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void AudioChannel::TestInstance() const { Verify(IsDerivedFrom(DefaultData)); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // AudioChannel::AudioChannel(ClassData *class_data, int channel, int type, DWORD properties): Plug(class_data), m_channel(channel), m_type(type), m_sample(NULL), m_playMode(gosAudio_Stop), m_properties(properties), m_startTime(0.0), m_command(NULL) { Check_Pointer(this); // //------------------------------- // Initialize the various sliders //------------------------------- // gosAudio_AssignResourceToChannel(m_channel, NULL); gosAudio_AllocateChannelSliders(m_channel, m_properties); SetVolume(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // AudioChannel::~AudioChannel() { Check_Object(this); Stop(); gosAudio_AssignResourceToChannel(m_channel, NULL); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void AudioChannel::Play(AudioCommand *command) { Check_Object(this); Check_Object(command); Verify(m_playMode == gosAudio_Stop); m_startTime = gos_GetElapsedTime(); m_playMode = command->GetPlayMode(); m_command = command; SetVolume(); gosAudio_SetChannelPlayMode(m_channel, m_playMode); m_command->SetChannel(this); m_energy = command->m_energy; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void AudioChannel::Stop() { Check_Object(this); if (m_playMode != gosAudio_Stop) { gosAudio_SetChannelPlayMode(m_channel, gosAudio_Stop); Deactivate(); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void AudioChannel::SetVolume() { Check_Object(this); // //--------------------------------------------------- // If there is no command attached, we have no volume //--------------------------------------------------- // if (!m_command) m_volume = 0.0f; // //---------------------------------------------------------- // Otherwise, multiply the command volume by the type volume //---------------------------------------------------------- // else { ChannelType &type = AudioRenderer::Instance->m_channelTypes[m_type]; Check_Object(&type); m_volume = m_command->m_volume * type.GetVolume(); } // //---------------------------- // Now tell gos the new volume //---------------------------- // gosAudio_SetChannelSlider(m_channel, gosAudio_Volume, m_volume); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void AudioChannel::Activate(AudioCommand *command) { Check_Object(this); Check_Object(command); Verify(m_playMode == gosAudio_Stop); // //------------------- // Start the sound up //------------------- // Play(command); // //---------------------------- // Attach to the active chains //---------------------------- // Check_Object(m_sample); m_sample->SetChannelActive(this); Check_Object(AudioRenderer::Instance); AudioRenderer::Instance->SetChannelActive(this); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void AudioChannel::Deactivate() { Check_Object(this); Verify(m_playMode != gosAudio_Stop); // //------------------------------------------------------------------------------- // Kill the command, and delete the object from any chains/sockets it might be on //------------------------------------------------------------------------------- // if (m_command) { Check_Object(m_command); // //----------------------------------------------------------------------------------- // If this is a loop, we don't destroy the command. Rather, we put it on the pending // loop list in the audio renderer //----------------------------------------------------------------------------------- // if (m_playMode == gosAudio_PlayOnce) delete m_command; else { Verify(m_playMode == gosAudio_Loop); m_command->m_channel = NULL; Check_Object(AudioRenderer::Instance); AudioRenderer::Instance->m_executingCommands.RemovePlug(m_command); } m_command = NULL; } // //---------------------------------------------------------------------------------- // Attach to the inactive chain in the sample. If the sample is a stream and is not // play once, delete it //---------------------------------------------------------------------------------- // m_playMode = gosAudio_Stop; Check_Object(m_sample); m_sample->SetChannelInactive(this); AudioRenderer::Instance->SetChannelInactive(this); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void AudioChannel::SetSample(AudioSample *sample) { Check_Object(this); Verify(m_sample != sample); Verify(m_playMode == gosAudio_Stop); #if defined(LAB_ONLY) if (((m_properties&(gosAudio_Position|gosAudio_MinMaxDistance))!=0) != sample->m_3D) { if (sample->m_3D) PAUSE(("3-D sound \"%s\" is being used as a 2-D sound!", sample->m_sampleResource.GetName())); else PAUSE(("2-D sound \"%s\" is being used as a 3-D sound!", sample->m_sampleResource.GetName())); } #endif if (m_sample) { if (m_command) { Verify(m_sample->m_activeChannels.IsPlugMember(this)); m_sample->m_activeChannels.RemovePlug(this); } else { Verify(m_sample->m_inactiveChannels.IsPlugMember(this)); m_sample->m_inactiveChannels.RemovePlug(this); } gosAudio_AssignResourceToChannel(m_channel, NULL); } // // Causes a load, which needs a heap. // Verify(AudioRenderer::s_Heap); gos_PushCurrentHeap(AudioRenderer::s_Heap); sample->Load(); gosAudio_AssignResourceToChannel(m_channel, sample->m_gosSample); gos_PopCurrentHeap(); m_sample = sample; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void AudioChannel::Execute(Stuff::Time till) { Check_Object(this); Verify(m_playMode != gosAudio_Stop); Verify(!m_sample->m_3D); AUDIO_RENDER("Execute::AudioChannel"); // //----------------------------------------- // If we have stopped, deactivate the sound //----------------------------------------- // gosAudio_PlayMode play_mode = gosAudio_GetChannelPlayMode(m_channel); switch (play_mode) { case gosAudio_Pause: return; case gosAudio_Stop: { // //----------------------------------------------------------- // If we lost focus, I guess we gotta start up our loop again //----------------------------------------------------------- // if (m_playMode == gosAudio_Loop) { gosAudio_SetChannelPlayMode(m_channel, m_playMode); goto Still_Playing; } Deactivate(); // //------------------------------------------------------------------- // But if this is a queued channel type, play the next queued command //------------------------------------------------------------------- // Check_Object(AudioRenderer::Instance); ChannelType &type = AudioRenderer::Instance->m_channelTypes[m_type]; if (type.IsQueued()) { ChainIteratorOf commands(&type.m_queuedCommands); AudioCommand *command = commands.GetCurrent(); if (command) { Check_Object(command); commands.Remove(); command->Play(); } } } break; // //----------------------------------------------------------------- // Otherwise, update the energy of the channel for culling purposes //----------------------------------------------------------------- // default: Verify(m_playMode == play_mode); Still_Playing: m_energy = m_command->ComputeEnergy(this); break; } }