Files
firestorm/Gameleap/code/mw4/Libraries/Adept/AudioChannel.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
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.
2026-06-24 21:28:16 -05:00

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;
}
}