Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
336 lines
9.7 KiB
C++
336 lines
9.7 KiB
C++
//===========================================================================//
|
|
// 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<AudioCommand*> 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;
|
|
}
|
|
}
|