Archival snapshot of the Virtual World Entertainment Tesla cockpit software, 1994-1996: MUNGA engine and L4 pod layer source (Borland C++ 5.0), BT/RP game code, and game content (models, audio, maps, gauges, Division renderer data). Includes third-party libraries: Division dVS/DPL graphics, HMI SOS audio, WATTCP networking. Files are preserved byte-for-byte (.gitattributes disables all line-ending conversion). README.md documents the layout, target hardware, and toolchain. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
481 lines
12 KiB
C++
481 lines
12 KiB
C++
//===========================================================================//
|
|
// File: audio.hh //
|
|
// Project: MUNGA Brick: Audio manager //
|
|
// Contents: //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 01/30/95 ECH Initial coding. //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include <munga.hpp>
|
|
#pragma hdrstop
|
|
|
|
#if !defined(AUDLVL_HPP)
|
|
# include <audlvl.hpp>
|
|
#endif
|
|
|
|
#if !defined(OBJSTRM_HPP)
|
|
#include <objstrm.hpp>
|
|
#endif
|
|
|
|
#if !defined(NAMELIST_HPP)
|
|
#include <namelist.hpp>
|
|
#endif
|
|
|
|
#if !defined(APP_HPP)
|
|
#include <app.hpp>
|
|
#endif
|
|
|
|
#if !defined(AUDREND_HPP)
|
|
#include <audrend.hpp>
|
|
#endif
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioLevelOfDetail ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
AudioLevelOfDetail::AudioLevelOfDetail(PlugStream *stream):
|
|
Plug(stream)
|
|
{
|
|
#if 0
|
|
amplitudeRadiationProfile = 0.0f;
|
|
filterRadiationProfile = 0.0f;
|
|
#endif
|
|
|
|
//
|
|
// Read fields
|
|
//
|
|
MemoryStream_Read(stream, &voiceCount);
|
|
MemoryStream_Read(stream, &audioRenderType);
|
|
|
|
//
|
|
// Read suspend seconds and calculate suspendDelay
|
|
//
|
|
Scalar
|
|
suspend_delay_seconds;
|
|
|
|
MemoryStream_Read(stream, &suspend_delay_seconds);
|
|
Check(application);
|
|
Check(application->GetAudioRenderer());
|
|
suspendDelay = suspend_delay_seconds *
|
|
application->GetAudioRenderer()->GetCalibrationRate() + 0.5f;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioLevelOfDetail::BuildFromPage(
|
|
PlugStream *stream,
|
|
NameList *name_list,
|
|
ClassID class_ID,
|
|
ObjectID object_ID
|
|
)
|
|
{
|
|
Plug::BuildFromPage(stream, name_list, class_ID, object_ID);
|
|
|
|
//
|
|
// Store fields
|
|
//
|
|
MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioVoiceCount, voice_count);
|
|
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, render_type);
|
|
|
|
//
|
|
// Store suspend delay
|
|
//
|
|
CString suspend_delay_string("suspend_delay");
|
|
Scalar suspend_delay_seconds = 0.33f; // HACK - should come from somewhere else
|
|
|
|
if (name_list->FindData(suspend_delay_string) != NULL)
|
|
{
|
|
Check_Pointer(name_list->FindData(suspend_delay_string));
|
|
Convert_From_Ascii(
|
|
(const char *)name_list->FindData(suspend_delay_string),
|
|
&suspend_delay_seconds
|
|
);
|
|
}
|
|
MemoryStream_Write(stream, &suspend_delay_seconds);
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
AudioLevelOfDetail::~AudioLevelOfDetail()
|
|
{
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
Logical
|
|
AudioLevelOfDetail::TestInstance() const
|
|
{
|
|
Plug::TestInstance();
|
|
return True;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioResource ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
AudioResource::AudioResource(PlugStream *stream):
|
|
Node(stream),
|
|
audioLevelOfDetailSocket(NULL, True)
|
|
{
|
|
//
|
|
// Read the table
|
|
//
|
|
CollectionSize i, number_of_entries;
|
|
|
|
MemoryStream_Read(stream, &number_of_entries);
|
|
for (i = 0; i < number_of_entries; i++)
|
|
{
|
|
Scalar distance;
|
|
AudioLevelOfDetail *audio_level_of_detail;
|
|
|
|
MemoryStream_Read(stream, &distance);
|
|
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_level_of_detail);
|
|
Check(audio_level_of_detail);
|
|
audioLevelOfDetailSocket.AddValue(audio_level_of_detail, distance);
|
|
}
|
|
|
|
//
|
|
// Verify that there is at least one entry and the first one is at 0.0f
|
|
//
|
|
#if DEBUG_LEVEL>0
|
|
{
|
|
TableIteratorOf<AudioLevelOfDetail*, Scalar> iterator(&audioLevelOfDetailSocket);
|
|
Check(&iterator);
|
|
Verify(iterator.GetSize() > 0);
|
|
Verify(iterator.GetCurrent() != NULL);
|
|
Verify(iterator.GetValue() == 0.0f);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Select the first entry
|
|
//
|
|
TableIteratorOf<AudioLevelOfDetail*, Scalar> iterator(&audioLevelOfDetailSocket);
|
|
|
|
audioLevelOfDetail = iterator.GetCurrent();
|
|
Check(audioLevelOfDetail);
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioResource::BuildFromPage(
|
|
PlugStream *stream,
|
|
NameList *name_list,
|
|
ClassID class_ID,
|
|
ObjectID object_ID
|
|
)
|
|
{
|
|
Node::BuildFromPage(stream, name_list, class_ID, object_ID);
|
|
|
|
//
|
|
// Count number of entries
|
|
//
|
|
int number_of_entries = 0;
|
|
NameList::Entry *entry;
|
|
|
|
Check(name_list);
|
|
entry = name_list->GetFirstEntry();
|
|
while (entry != NULL)
|
|
{
|
|
Check(entry);
|
|
if (entry->IsName("audio_level_of_detail"))
|
|
number_of_entries++;
|
|
entry = entry->GetNextEntry();
|
|
}
|
|
|
|
//
|
|
// Store entries
|
|
//
|
|
MemoryStream_Write(stream, &number_of_entries);
|
|
|
|
Check(name_list);
|
|
entry = name_list->GetFirstEntry();
|
|
while (entry != NULL)
|
|
{
|
|
Check(entry);
|
|
if (entry->IsName("audio_level_of_detail"))
|
|
{
|
|
CString object_string;
|
|
Scalar distance;
|
|
ObjectID object_ID;
|
|
|
|
Check_Pointer(entry->GetChar());
|
|
object_string = entry->GetChar();
|
|
|
|
Check_Pointer(object_string.GetNthToken(0));
|
|
Convert_From_Ascii(object_string.GetNthToken(0), &distance);
|
|
MemoryStream_Write(stream, &distance);
|
|
|
|
Check(stream);
|
|
Check_Pointer(object_string.GetNthToken(1));
|
|
object_ID = stream->FindObjectID(object_string.GetNthToken(1));
|
|
Verify(object_ID != NullObjectID);
|
|
MemoryStream_Write(stream, &object_ID);
|
|
}
|
|
entry = entry->GetNextEntry();
|
|
}
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
AudioResource::~AudioResource()
|
|
{
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
Logical
|
|
AudioResource::TestInstance() const
|
|
{
|
|
Node::TestInstance();
|
|
Check(&audioLevelOfDetailSocket);
|
|
return True;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioResource::SetDistance(Scalar distance)
|
|
{
|
|
Check(this);
|
|
Verify(distance >= 0.0f);
|
|
|
|
//
|
|
// Goto the last entry
|
|
//
|
|
TableIteratorOf<AudioLevelOfDetail*, Scalar>
|
|
iterator(&audioLevelOfDetailSocket);
|
|
|
|
Check(&iterator);
|
|
iterator.Last();
|
|
|
|
//
|
|
// While the distance is less than the distance of the entry
|
|
//
|
|
while (distance < iterator.GetValue())
|
|
{
|
|
iterator.Previous();
|
|
}
|
|
audioLevelOfDetail = iterator.GetCurrent();
|
|
Check(audioLevelOfDetail);
|
|
|
|
//
|
|
// Verify that the distance is greater than this entry, and less than
|
|
// the next
|
|
//
|
|
#if DEBUG_LEVEL>0
|
|
Verify(distance >= iterator.GetValue());
|
|
iterator.Next();
|
|
if (iterator.GetCurrent() != NULL)
|
|
{
|
|
Verify(distance < iterator.GetValue());
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Dump the LOD of the resource
|
|
//
|
|
#if 0
|
|
CollectionSize i = 0;
|
|
iterator.First();
|
|
while (iterator.GetCurrent() != NULL)
|
|
{
|
|
Check(iterator.GetCurrent());
|
|
if (audioLevelOfDetail == iterator.GetCurrent() /* && i > 0 */ )
|
|
{
|
|
Tell(
|
|
"AudioLOD:" << i <<
|
|
" d:" << distance <<
|
|
" t:" << iterator.GetValue() <<
|
|
"\n"
|
|
);
|
|
break;
|
|
}
|
|
iterator.Next();
|
|
i++;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioResourceIndex ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
AudioResourceIndex::AudioResourceIndex(PlugStream *stream):
|
|
Node(stream),
|
|
audioResourceSocket(NULL, True)
|
|
{
|
|
CollectionSize i, number_of_entries;
|
|
|
|
MemoryStream_Read(stream, &number_of_entries);
|
|
for (i = 0; i < number_of_entries; i++)
|
|
{
|
|
AudioResource *audio_resource;
|
|
|
|
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_resource);
|
|
Check(audio_resource);
|
|
AddAudioResource(audio_resource, i);
|
|
}
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioResourceIndex::BuildFromPage(
|
|
PlugStream *stream,
|
|
NameList *name_list,
|
|
ClassID class_ID,
|
|
ObjectID object_ID
|
|
)
|
|
{
|
|
Node::BuildFromPage(stream, name_list, class_ID, object_ID);
|
|
|
|
//
|
|
// Count number of entries
|
|
//
|
|
int number_of_entries = 0;
|
|
NameList::Entry *entry;
|
|
|
|
Check(name_list);
|
|
entry = name_list->GetFirstEntry();
|
|
while (entry != NULL)
|
|
{
|
|
Check(entry);
|
|
if (entry->IsName("audio_resource"))
|
|
number_of_entries++;
|
|
entry = entry->GetNextEntry();
|
|
}
|
|
|
|
//
|
|
// Store entries
|
|
//
|
|
MemoryStream_Write(stream, &number_of_entries);
|
|
|
|
Check(name_list);
|
|
entry = name_list->GetFirstEntry();
|
|
while (entry != NULL)
|
|
{
|
|
Check(entry);
|
|
if (entry->IsName("audio_resource"))
|
|
{
|
|
CString object_name;
|
|
ObjectID object_ID;
|
|
|
|
Check_Pointer(entry->GetChar());
|
|
object_name = entry->GetChar();
|
|
|
|
Check(stream);
|
|
object_ID = stream->FindObjectID(object_name);
|
|
Verify(object_ID != NullObjectID);
|
|
MemoryStream_Write(stream, &object_ID);
|
|
}
|
|
entry = entry->GetNextEntry();
|
|
}
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
AudioResourceIndex::~AudioResourceIndex()
|
|
{
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
Logical
|
|
AudioResourceIndex::TestInstance() const
|
|
{
|
|
Node::TestInstance();
|
|
Check(&audioResourceSocket);
|
|
return True;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
void
|
|
AudioResourceIndex::AddAudioResource(
|
|
AudioResource *audio_resource,
|
|
Enumeration index
|
|
)
|
|
{
|
|
Check(this);
|
|
audioResourceSocket.AddValue(audio_resource, index);
|
|
|
|
#if DEBUG_LEVEL>0
|
|
TableIteratorOf<AudioResource*, Enumeration> iterator(&audioResourceSocket);
|
|
Check(&iterator);
|
|
for (int i = 0; i < iterator.GetSize(); i++)
|
|
{
|
|
Verify(iterator.GetNth(i) == audioResourceSocket.Find(i));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
AudioResource*
|
|
AudioResourceIndex::GetAudioResource(Enumeration index)
|
|
{
|
|
Check(this);
|
|
|
|
TableIteratorOf<AudioResource*, Enumeration> iterator(&audioResourceSocket);
|
|
Check(&iterator);
|
|
Verify(iterator.GetNth(index) == audioResourceSocket.Find(index));
|
|
|
|
return iterator.GetNth(index);
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
//#############################################################################
|
|
//
|
|
CollectionSize
|
|
AudioResourceIndex::GetSize()
|
|
{
|
|
Check(this);
|
|
|
|
TableIteratorOf<AudioResource*, Enumeration> iterator(&audioResourceSocket);
|
|
Check(&iterator);
|
|
|
|
return iterator.GetSize();
|
|
}
|
|
|
|
|