Files
CydandClaude Opus 4.8 4abbf8879f Initial import of Red Planet v4.10 Win32 source
Imports the current Win32 source for the pod-racing game 'Red Planet',
built on the MUNGA engine and its L4 (Win32/DirectX) platform layer:

- MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend
- RP / RP_L4: Red Planet game logic and Win32 application
- DivLoader, Setup1: asset loader and installer project
- lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies

Removed stale Subversion metadata and added .gitignore/.gitattributes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 07:59:51 -05:00

2191 lines
58 KiB
C++

#include "mungal4.h"
#pragma hdrstop
#include "l4audio.h"
#include "l4audlvl.h"
#include "l4app.h"
#include "l4audrnd.h"
#include "..\munga\namelist.h"
#include "..\munga\player.h"
#include "..\rp\vtv.h"
//#############################################################################
//####################### L4AudioSpatialization #########################
//#############################################################################
//
//#############################################################################
//#############################################################################
//
L4AudioSpatialization::L4AudioSpatialization()
{
azimuthOfSource = 0.0f;
frontLeftScale = 0.0f;
frontRightScale = 0.0f;
rearLeftScale = 0.0f;
rearRightScale = 0.0f;
frontLeftDelay = 0.0f;
frontRightDelay = 0.0f;
rearLeftDelay = 0.0f;
rearRightDelay = 0.0f;
quadrant = Quadrant1;
}
//
//#############################################################################
//#############################################################################
//
L4AudioSpatialization::~L4AudioSpatialization()
{
}
//
//#############################################################################
//#############################################################################
//
Logical
L4AudioSpatialization::TestInstance() const
{
return True;
}
//
//#############################################################################
//#############################################################################
//
void
L4AudioSpatialization::CalculateSpatialization(Radian azimuth_of_source)
{
azimuthOfSource = azimuth_of_source;
//
//---------------------------------------------------------------
// Make azimuth usable for channel volume calculations
//---------------------------------------------------------------
//
#define DEG_90 (90.0f*(RAD_PER_DEG))
#define DEG_180 (180.0f*(RAD_PER_DEG))
#define DEG_360 (360.0f*(RAD_PER_DEG))
azimuthOfSource = DEG_180 + azimuthOfSource;
if (azimuthOfSource > DEG_180)
azimuthOfSource = azimuthOfSource - DEG_360;
Verify(
azimuthOfSource <= DEG_180 &&
azimuthOfSource >= -DEG_180
);
//
//---------------------------------------------------------------
// Channel volume scale and ITD calculations
//---------------------------------------------------------------
//
//
// Get audio head constants
//
L4AudioRenderer *audio_renderer;
AudioHead *audio_head;
Check(application);
audio_renderer =
Cast_Object(L4AudioRenderer*, application->GetAudioRenderer());
Check(audio_renderer);
audio_head = audio_renderer->GetAudioHead();
Check(audio_head);
//
// Init channel volume scale variables
//
const Radian azimuth_max = 45.0*RAD_PER_DEG; // HACK - should come from audio.ini
Scalar tangent_ratio;
frontLeftScale = 0.0f;
frontRightScale = 0.0f;
rearLeftScale = 0.0f;
rearRightScale = 0.0f;
//
// Init ITD parameters
//
const Scalar itd_delay = audio_head->GetITDDifference();
frontLeftDelay = 0.0f;
frontRightDelay = 0.0f;
rearLeftDelay = 0.0f;
rearRightDelay = 0.0f;
//
//---------------------------------------------------------------
// Quadrant 1
//---------------------------------------------------------------
//
if (
azimuthOfSource > -azimuth_max &&
azimuthOfSource < azimuth_max
)
{
quadrant = Quadrant1;
// volume scale
Verify(!Small_Enough(tan(azimuth_max)));
tangent_ratio =
(tan(azimuthOfSource) / tan(azimuth_max)) * 0.5f;
frontLeftScale = Sqrt(0.5f + tangent_ratio);
frontRightScale = Sqrt(0.5f - tangent_ratio);
Verify(frontLeftScale >= 0.0f && frontLeftScale <= 1.0f);
Verify(frontRightScale >= 0.0f && frontRightScale <= 1.0f);
// pitch offset
if (azimuthOfSource > 0.0f)
{
frontLeftDelay = itd_delay * tangent_ratio * 2.0f;
}
else
{
frontRightDelay = itd_delay * -tangent_ratio * 2.0f;
}
}
//
//---------------------------------------------------------------
// Quadrant 2
//---------------------------------------------------------------
//
else if (
azimuthOfSource > azimuth_max &&
azimuthOfSource < (DEG_180 - azimuth_max)
)
{
quadrant = Quadrant2;
// volume scale
azimuthOfSource = azimuthOfSource - DEG_90;
Verify(!Small_Enough(tan(DEG_90 - azimuth_max)));
tangent_ratio =
(tan(azimuthOfSource) / tan(DEG_90 - azimuth_max)) * 0.5f;
rearLeftScale = Sqrt(0.5f + tangent_ratio);
frontLeftScale = Sqrt(0.5f - tangent_ratio);
Verify(rearLeftScale >= 0.0f && rearLeftScale <= 1.0f);
Verify(frontLeftScale >= 0.0f && frontLeftScale <= 1.0f);
// pitch offset
if (azimuthOfSource > 0.0f)
{
rearLeftDelay = itd_delay * tangent_ratio * 2.0f;
}
else
{
frontLeftDelay = itd_delay * -tangent_ratio * 2.0f;
}
}
//
//---------------------------------------------------------------
// Quadrant 3
//---------------------------------------------------------------
//
else if (
azimuthOfSource > (DEG_180 - azimuth_max) ||
azimuthOfSource < (-DEG_180 + azimuth_max)
)
{
quadrant = Quadrant3;
// volume scale
azimuthOfSource = azimuthOfSource - DEG_180;
Verify(!Small_Enough(tan(azimuth_max)));
tangent_ratio =
(tan(azimuthOfSource) / tan(azimuth_max)) * 0.5f;
rearRightScale = Sqrt(0.5f + tangent_ratio);
rearLeftScale = Sqrt(0.5f - tangent_ratio);
Verify(rearRightScale >= 0.0f && rearRightScale <= 1.0f);
Verify(rearLeftScale >= 0.0f && rearLeftScale <= 1.0f);
// pitch offset
if (azimuthOfSource > -azimuth_max)
{
rearLeftDelay = -(itd_delay * tangent_ratio * 2.0f);
}
else
{
rearRightDelay = -(itd_delay * -tangent_ratio * 2.0f);
}
#if 0
Tell(
"azimuthOfSource " << azimuthOfSource <<
" rearRightDelay " << rearRightDelay <<
" rearLeftDelay " << rearLeftDelay <<
"\n"
);
#endif
}
//
//---------------------------------------------------------------
// Quadrant 4
//---------------------------------------------------------------
//
else
{
quadrant = Quadrant4;
Verify(
azimuthOfSource > (-DEG_180 + azimuth_max) &&
azimuthOfSource < -azimuth_max
);
// volume scale
azimuthOfSource = azimuthOfSource + DEG_90;
Verify(!Small_Enough(tan(DEG_90 - azimuth_max)));
tangent_ratio =
(tan(azimuthOfSource) / tan(DEG_90 - azimuth_max)) * 0.5f;
frontRightScale = Sqrt(0.5f + tangent_ratio);
rearRightScale = Sqrt(0.5f - tangent_ratio);
Verify(frontRightScale >= 0.0f && frontRightScale <= 1.0f);
Verify(rearRightScale >= 0.0f && rearRightScale <= 1.0f);
// pitch offset
if (azimuthOfSource > 0.0f)
{
frontRightDelay = itd_delay * tangent_ratio * 2.0f;
}
else
{
rearRightDelay = itd_delay * -tangent_ratio * 2.0f;
}
}
#if 0
Tell(
"FL " << frontLeftScale <<
" FR " << frontRightScale <<
" RL " << rearLeftScale <<
" RR " << rearRightScale <<
"\n"
);
#endif
#if 0
Tell(
"Quadrant " << quadrant <<
" FL " << frontLeftDelay <<
" FR " << frontRightDelay <<
" RL " << rearLeftDelay <<
" RR " << rearRightDelay <<
"\n"
);
#endif
Verify(frontLeftScale >= 0.0f && frontLeftScale <= 1.0f);
Verify(frontRightScale >= 0.0f && frontRightScale <= 1.0f);
Verify(rearLeftScale >= 0.0f && rearLeftScale <= 1.0f);
Verify(rearRightScale >= 0.0f && rearRightScale <= 1.0f);
}
//#############################################################################
//######################### L4AudioLocation #############################
//#############################################################################
//
//#############################################################################
//#############################################################################
//
L4AudioLocation::L4AudioLocation(
PlugStream *stream,
Entity *entity
):
AudioLocation(stream, entity)
{
L4AudioLocationX();
}
//
//#############################################################################
//#############################################################################
//
void
L4AudioLocation::L4AudioLocationX()
{
//
// Get audio renderer frame duration
//
Check(application)
L4AudioRenderer *audio_renderer =
Cast_Object(L4AudioRenderer*, application->GetAudioRenderer());
Check(audio_renderer);
Time frame_duration =
audio_renderer->GetCalibrationFrameDuration();
//
// Init ITD pitch offset variables
//
lastITDFrameTime = Now();
lastITDFrameTime -= frame_duration;
currentFrontLeftDelay = 0.0f;
currentFrontRightDelay = 0.0f;
currentRearLeftDelay = 0.0f;
currentRearRightDelay = 0.0f;
frontLeftITDPitchOffset = 0.0f;
frontRightITDPitchOffset = 0.0f;
rearLeftITDPitchOffset = 0.0f;
rearRightITDPitchOffset = 0.0f;
}
//
//#############################################################################
//#############################################################################
//
L4AudioLocation::~L4AudioLocation()
{
}
//
//#############################################################################
//#############################################################################
//
Logical
L4AudioLocation::TestInstance() const
{
AudioLocation::TestInstance();
Check(&spatialization);
return True;
}
//
//#############################################################################
//#############################################################################
//
void
L4AudioLocation::UpdateSpatialModelImplementation(AudioHead *audio_head)
{
Check(this);
Check(audio_head);
//
//---------------------------------------------------------------
// Call inherited method
//---------------------------------------------------------------
//
AudioLocation::UpdateSpatialModelImplementation(audio_head);
//
//---------------------------------------------------------------
// Catch case of head == source
//---------------------------------------------------------------
//
if (IsHeadSource())
{
spatialization.frontLeftScale = 1.0f;
spatialization.frontRightScale = 1.0f;
spatialization.rearLeftScale = 1.0f;
spatialization.rearRightScale = 1.0f;
frontLeftITDPitchOffset = 0.0f;
frontRightITDPitchOffset = 0.0f;
rearLeftITDPitchOffset = 0.0f;
rearRightITDPitchOffset = 0.0f;
return;
}
//
//---------------------------------------------------------------
// Calculate channel spatialization
//---------------------------------------------------------------
//
spatialization.CalculateSpatialization(GetAzimuthOfSource());
//
//---------------------------------------------------------------
// Calculate ITD pitch offsets
//---------------------------------------------------------------
//
const Scalar itd_pitch_offset_constant =
0.003831f / 0.000002f; // period / delay // HACK - should come from audio head
Time itd_delta_time;
itd_delta_time = Now();
itd_delta_time -= lastITDFrameTime;
lastITDFrameTime = Now();
frontLeftITDPitchOffset = 0.0f;
frontRightITDPitchOffset = 0.0f;
rearLeftITDPitchOffset = 0.0f;
rearRightITDPitchOffset = 0.0f;
if (!Small_Enough((Scalar)itd_delta_time))
{
if (currentFrontLeftDelay != spatialization.frontLeftDelay)
{
Verify(!Small_Enough((Scalar)itd_delta_time));
frontLeftITDPitchOffset =
itd_pitch_offset_constant *
(spatialization.frontLeftDelay - currentFrontLeftDelay) /
(Scalar)itd_delta_time;
currentFrontLeftDelay = spatialization.frontLeftDelay;
}
if (currentFrontRightDelay != spatialization.frontRightDelay)
{
Verify(!Small_Enough((Scalar)itd_delta_time));
frontRightITDPitchOffset =
itd_pitch_offset_constant *
(spatialization.frontRightDelay - currentFrontRightDelay) /
(Scalar)itd_delta_time;
currentFrontRightDelay = spatialization.frontRightDelay;
}
if (currentRearLeftDelay != spatialization.rearLeftDelay)
{
Verify(!Small_Enough((Scalar)itd_delta_time));
rearLeftITDPitchOffset =
itd_pitch_offset_constant *
(spatialization.rearLeftDelay - currentRearLeftDelay) /
(Scalar)itd_delta_time;
currentRearLeftDelay = spatialization.rearLeftDelay;
}
if (currentRearRightDelay != spatialization.rearRightDelay)
{
Verify(!Small_Enough((Scalar)itd_delta_time));
rearRightITDPitchOffset =
itd_pitch_offset_constant *
(spatialization.rearRightDelay - currentRearRightDelay) /
(Scalar)itd_delta_time;
currentRearRightDelay = spatialization.rearRightDelay;
}
}
#if 0
Tell(
"Quadrant " << spatialization.quadrant <<
" FL " << frontLeftITDPitchOffset <<
" FR " << frontRightITDPitchOffset <<
" RL " << rearLeftITDPitchOffset <<
" RR " << rearRightITDPitchOffset <<
"\n"
);
#endif
//
//---------------------------------------------------------------
// Check for source "between ears"
//---------------------------------------------------------------
//
const Scalar ear_radius =
audio_head->GetDistanceBetweenEars() * 0.5;
Scalar distance_to_source_listener_plane =
GetDistanceToSourceListenerPlane();
if (distance_to_source_listener_plane < ear_radius)
{
Verify(!Small_Enough(ear_radius));
const Scalar proportion =
0.5f *
(ear_radius - distance_to_source_listener_plane) /
ear_radius;
Scalar powerA, powerB;
#if DEBUG_LEVEL>0
if (!(proportion >= 0.0f && proportion <= 1.0f))
{
Dump(ear_radius);
Dump(distance_to_source_listener_plane);
Dump(proportion);
}
Verify(proportion >= 0.0f && proportion <= 1.0f);
#endif
powerA = Sqrt(1.0f - proportion);
powerB = Sqrt(proportion);
Verify(powerA >= 0.0f && powerA <= 1.0f);
Verify(powerB >= 0.0f && powerB <= 1.0f);
switch (spatialization.quadrant)
{
case L4AudioSpatialization::Quadrant1:
spatialization.rearLeftScale = spatialization.frontLeftScale * powerB;
spatialization.rearRightScale = spatialization.frontRightScale * powerB;
spatialization.frontLeftScale *= powerA;
spatialization.frontRightScale *= powerA;
break;
case L4AudioSpatialization::Quadrant2:
spatialization.rearRightScale = spatialization.rearLeftScale * powerB;
spatialization.frontRightScale = spatialization.frontLeftScale * powerB;
spatialization.rearLeftScale *= powerA;
spatialization.frontLeftScale *= powerA;
break;
case L4AudioSpatialization::Quadrant3:
spatialization.frontRightScale = spatialization.rearRightScale * powerB;
spatialization.frontLeftScale = spatialization.rearLeftScale * powerB;
spatialization.rearRightScale *= powerA;
spatialization.rearLeftScale *= powerA;
break;
case L4AudioSpatialization::Quadrant4:
spatialization.frontLeftScale = spatialization.frontRightScale * powerB;
spatialization.rearLeftScale = spatialization.rearRightScale * powerB;
spatialization.frontRightScale *= powerA;
spatialization.rearRightScale *= powerA;
break;
}
#if 0
Tell(
"FL " << spatialization.frontLeftScale <<
" FR " << spatialization.frontRightScale <<
" RL " << spatialization.rearLeftScale <<
" RR " << spatialization.rearRightScale <<
"\n"
);
#endif
}
Verify(spatialization.frontLeftScale >= 0.0f && spatialization.frontLeftScale <= 1.0f);
Verify(spatialization.frontRightScale >= 0.0f && spatialization.frontRightScale <= 1.0f);
Verify(spatialization.rearLeftScale >= 0.0f && spatialization.rearLeftScale <= 1.0f);
Verify(spatialization.rearRightScale >= 0.0f && spatialization.rearRightScale <= 1.0f);
}
//#############################################################################
//######################### AudioChannelSet #############################
//#############################################################################
//AudioChannelSet AudioChannelSet::Null;
//
//#############################################################################
//#############################################################################
//
/*AudioChannelSet::AudioChannelSet()
{
for (int i = 0; i < AudioChannelSetSize; i++)
{
channels[i] = NULL;
enables[i] = False;
}
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioChannelSet::TestInstance() const
{
for (int i = 0; i < AudioChannelSetSize; i++)
{
if (channels[i] != NULL)
{
Verify(enables[i] == True);
Check(channels[i]);
}
}
return True;
}
//
//#############################################################################
//#############################################################################
//
void
AudioChannelSet::EnableAll()
{
//
// Must set all channels to null and all enables to True
//
for (int i = 0; i < AudioChannelSetSize; i++)
{
channels[i] = NULL;
enables[i] = True;
}
}
//
//#############################################################################
//#############################################################################
//
void
AudioChannelSet::ReleaseAll()
{
//
// Must release all channels without changing enable values
//
for (int i = 0; i < AudioChannelSetSize; i++)
{
if (channels[i] != NULL)
{
Check(channels[i]);
channels[i]->Release();
channels[i] = NULL;
}
}
}*/
//#############################################################################
//########################## L4AudioSource ##############################
//#############################################################################
//
//#############################################################################
//#############################################################################
//
L4AudioSource::L4AudioSource(
PlugStream *stream,
Entity *entity
):
AudioSource(stream, entity)
{
channelSet.count = GetAudioVoiceCount();
L4AudioSourceX();
}
//
//#############################################################################
//#############################################################################
//
void
L4AudioSource::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AudioSource::BuildFromPage(stream, name_list, class_ID, object_ID);
}
//
//#############################################################################
//#############################################################################
//
void
L4AudioSource::L4AudioSourceX()
{
}
//
//#############################################################################
//#############################################################################
//
L4AudioSource::~L4AudioSource()
{
}
//
//#############################################################################
//#############################################################################
//
Logical
L4AudioSource::TestInstance() const
{
AudioSource::TestInstance();
Check(&channelSet);
return True;
}
//
//#############################################################################
//#############################################################################
//
void
L4AudioSource::StopMessageImplementation()
{
Check(this);
AudioSource::StopMessageImplementation();
//
// Request stop from renderer
//
Check(application);
Cast_Object(L4AudioRenderer*, application->GetAudioRenderer())->
StopRequest(this);
}
//
//#############################################################################
//#############################################################################
//
void
L4AudioSource::SetAudioChannelSet(const SourceSet &audio_channel_set)
{
Check(this);
channelSet = audio_channel_set;
}
//
//#############################################################################
//#############################################################################
//
SourceSet*
L4AudioSource::GetAudioChannelSet()
{
Check(this);
return &channelSet;
}
//
//#############################################################################
//#############################################################################
//
void
L4AudioSource::ReleaseChannels()
{
Check(this);
//How do I release the sources, man?
application->GetAudioRenderer()->ReleaseSourceSet(channelSet);
for (int i=0; i < channelSet.count; i++)
{
channelSet.sources[i] = 0;
}
//channelSet.ReleaseAll();
}
//#############################################################################
//######################## DirectPatchSource ############################
//#############################################################################
//
//#############################################################################
//#############################################################################
//
DirectPatchSource::DirectPatchSource(
PlugStream *stream,
Entity *entity
):
L4AudioSource(stream, entity)
{
MemoryStream_Read(stream, &audioPosition);
// channel = NULL;
}
//
//#############################################################################
//#############################################################################
//
void
DirectPatchSource::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
L4AudioSource::BuildFromPage(stream, name_list, class_ID, object_ID);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, position);
}
//
//#############################################################################
//#############################################################################
//
DirectPatchSource::~DirectPatchSource()
{
}
//
//#############################################################################
//#############################################################################
//
Logical
DirectPatchSource::TestInstance() const
{
L4AudioSource::TestInstance();
/* if (channel != NULL)
{
Check(channel);
}*/
return True;
}
//
//#############################################################################
//#############################################################################
//
void
DirectPatchSource::StartMessageImplementation()
{
Check(this);
L4AudioSource::StartMessageImplementation();
//
//--------------------------------------------------------------------------
// Init channel set to requested channels
//--------------------------------------------------------------------------
//
/* channelSet = AudioChannelSet::Null;
switch (audioPosition)
{
case FrontDirectPatchPosition:
case FrontLeftDirectPatchPosition:
case FrontRightDirectPatchPosition:
channelSet.EnableFrontLeft(True);
break;
case RearDirectPatchPosition:
case RearLeftDirectPatchPosition:
case RearRightDirectPatchPosition:
channelSet.EnableRearLeft(True);
break;
}*/
//
//--------------------------------------------------------------------------
// Request start from renderer
//--------------------------------------------------------------------------
//
Check(application);
Cast_Object(L4AudioRenderer*, application->GetAudioRenderer())->
StartRequest(this);
}
//
//#############################################################################
//#############################################################################
//
void
DirectPatchSource::StartImplementation()
{
Check(this);
//
//--------------------------------------------------------------------------
// Call inherited method
//--------------------------------------------------------------------------
//
L4AudioSource::StartImplementation();
//
//--------------------------------------------------------------------------
// Remember the channel
//--------------------------------------------------------------------------
//
/* Verify(channel == NULL);
switch (audioPosition)
{
case FrontDirectPatchPosition:
case FrontLeftDirectPatchPosition:
case FrontRightDirectPatchPosition:
channel = channelSet.GetFrontLeft();
break;
case RearDirectPatchPosition:
case RearLeftDirectPatchPosition:
case RearRightDirectPatchPosition:
channel = channelSet.GetRearLeft();
break;
}
Check(channel);*/
//
//--------------------------------------------------------------------------
// Setup the channel
//--------------------------------------------------------------------------
//
ExecuteWatchers();
//
// Turn the volume down while setting up the channel
//
// channel->SendController(MIDI_VOLUME_CONTROL, MIDI_MIN_CONTROL_VALUE);
//
// Set the channel to the bank and program
//
PatchResource *patch_resource;
patch_resource = Cast_Object(PatchResource*, GetAudioResource());
Check(patch_resource);
patch_resource->SetDistance(GetDistanceToSource());
patch_resource->SetupPatch(channelSet);
//
// Set the channel to default control values
//
// channel->SendController(MIDI_REVERB_CONTROL, MIDI_MIN_CONTROL_VALUE);
// channel->SendController(MIDI_CHORUS_CONTROL, MIDI_MIN_CONTROL_VALUE);
/* switch (audioPosition)
{
case FrontDirectPatchPosition:
case RearDirectPatchPosition:
channel->SendController(MIDI_PAN_CONTROL, MIDI_CENTER_PAN_VALUE);
break;
case FrontLeftDirectPatchPosition:
case RearLeftDirectPatchPosition:
channel->SendController(MIDI_PAN_CONTROL, MIDI_LEFT_PAN_VALUE);
break;
case FrontRightDirectPatchPosition:
case RearRightDirectPatchPosition:
channel->SendController(MIDI_PAN_CONTROL, MIDI_RIGHT_PAN_VALUE);
break;
}*/
//
// Set midi history to default control values
//
lastMIDIVolume = MIDI_MIN_CONTROL_VALUE;
lastMIDIPitchBend = 0; // Set by force update
lastMIDIFilterCutoff = MIDI_MAX_CONTROL_VALUE; // Set by patch load
//
//--------------------------------------------------------------------------
// Calculate attack time, velocity, and execute model
//--------------------------------------------------------------------------
//
MIDIValue midi_velocity =
CalculateSourceAttackVolumeScale() *
(Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f;
if (UseSourceAttackTime())
{
MIDINRPNValue midi_attack_time =
CalculateSourceAttackTime() *
(Scalar)AWE_VOL_ATTACK_TIME_RANGE + 0.5f;
// channel->SendNRPN(AWE_VOL_ATTACK_TIME_NRPN, midi_attack_time);
}
ExecuteModel(True);
//
//--------------------------------------------------------------------------
// Start note
//--------------------------------------------------------------------------
//
//TODO: Start OpenAL source playing
// channel->SendNoteOn(GetCurrentNoteValue(), midi_velocity);
patch_resource->PlayNote(channelSet);
#if 0
Tell("On " << (int)GetCurrentNoteValue() << "\n");
#endif
}
//
//#############################################################################
//#############################################################################
//
void
DirectPatchSource::StopImplementation()
{
Check(this);
//TODO: Stop OpenAL source playing
PatchResource *patch_resource;
patch_resource = Cast_Object(PatchResource*, GetAudioResource());
Check(patch_resource);
patch_resource->StopNote(channelSet);
//
// Stop note
//
// Check(channel);
// channel->SendNoteOff(GetCurrentNoteValue(), MIDI_MIN_CONTROL_VALUE);
// channel = NULL;
}
//
//#############################################################################
//#############################################################################
//
void
DirectPatchSource::ExecuteModel(Logical force_update)
{
Check(this);
//TODO: Probably don't have to do anything in this function- maybe watch
//to mess with looping appropriately.
//
//--------------------------------------------------------------------------
// Apply pitch offset
//--------------------------------------------------------------------------
//
const MIDIPitchBend pitch_resolution = 12; // HACK - should come from audio.ini
AudioPitchCents pitch_offset;
pitch_offset = CalculateSourcePitchOffset();
double relativePitch = pow(2.0,pitch_offset/1200.0);
Clamp(relativePitch,0.5,2.0);
//
//--------------------------------------------------------------------------
// Apply filter scale
//--------------------------------------------------------------------------
//
if (UseSourceBrightnessScale())
{
const MIDINRPNValue filter_resolution = 2;// HACK - should come from audio.ini
Scalar filter_scale;
PatchResource *patch_resource;
MIDINRPNValue max_midi_filter_cutoff;
MIDINRPNValue midi_filter_cutoff;
MIDINRPNValue filter_difference;
filter_scale = CalculateSourceBrightnessScale();
patch_resource = Cast_Object(PatchResource*, GetAudioResource());
max_midi_filter_cutoff = patch_resource->GetMaxMIDIFilterCutoff();
midi_filter_cutoff = filter_scale * (Scalar)max_midi_filter_cutoff + 0.5f;
filter_difference = lastMIDIFilterCutoff - midi_filter_cutoff;
if (Abs(filter_difference) >= filter_resolution)
{
lastMIDIFilterCutoff = midi_filter_cutoff;
}
}
//
//--------------------------------------------------------------------------
// Apply volume scale
//--------------------------------------------------------------------------
//
Scalar volume_scale;
const MIDIValue volume_resolution = 2; // HACK - should come from audio.ini
volume_scale = CalculateSourceVolumeScale();
L4AudioLocation *audio_location = Cast_Object(L4AudioLocation*, GetAudioLocation());
Check(application);
L4AudioRenderer *audio_renderer =
Cast_Object(L4AudioRenderer*, application->GetAudioRenderer());
Check(audio_renderer);
AudioHead *audio_head = audio_renderer->GetAudioHead();
Check(audio_head);
for (int i=0; i < channelSet.count; i++)
{
alSourcef(channelSet.sources[i],AL_MAX_DISTANCE,audio_location->getMaxDistance(audio_head));
alSourcef(channelSet.sources[i], AL_GAIN, volume_scale);
}
}
//#############################################################################
//###################### Dynamic3DPatchSource ###########################
//#############################################################################
//
//#############################################################################
//#############################################################################
//
Dynamic3DPatchSource::Dynamic3DPatchSource(
PlugStream *stream,
Entity *entity
):
L4AudioSource(stream, entity)
{
}
Logical
Dynamic3DPatchSource::IsAudioSourceClipped(AudioHead *audio_head)
{
if (AudioSource::IsAudioSourceClipped(audio_head) || l4_application->GetMissionPlayer()->GetPlayerVehicle()->GetSimulationState() == VTV::BurningState)
{
return true;
} else
{
return false;
}
}
//
//#############################################################################
//#############################################################################
//
Dynamic3DPatchSource::~Dynamic3DPatchSource()
{
}
//
//#############################################################################
//#############################################################################
//
Logical
Dynamic3DPatchSource::TestInstance() const
{
L4AudioSource::TestInstance();
return True;
}
//
//#############################################################################
//#############################################################################
//
void
Dynamic3DPatchSource::StartMessageImplementation()
{
Check(this);
L4AudioSource::StartMessageImplementation();
//
// Init channel set to requested channels
//
// channelSet.EnableAll();
//
// Request start from renderer
//
Check(application);
Cast_Object(L4AudioRenderer*, application->GetAudioRenderer())->
StartRequest(this);
}
//
//#############################################################################
//#############################################################################
//
void
Dynamic3DPatchSource::StartImplementation()
{
Check(this);
//
//--------------------------------------------------------------------------
// Call inherited method
//--------------------------------------------------------------------------
//
L4AudioSource::StartImplementation();
//
//--------------------------------------------------------------------------
// Get application, renderer and head pointers
//--------------------------------------------------------------------------
//
L4AudioRenderer *audio_renderer;
AudioHead *audio_head;
Check(application);
audio_renderer =
Cast_Object(L4AudioRenderer*, application->GetAudioRenderer());
Check(audio_renderer);
audio_head = audio_renderer->GetAudioHead();
Check(audio_head);
//
//--------------------------------------------------------------------------
// Setup the channel
//--------------------------------------------------------------------------
//
ExecuteWatchers();
//
// Turn the volume down while setting up the channels
//
//
// Set the channels to the bank and program
//
PatchResource *patch_resource;
patch_resource = Cast_Object(PatchResource*, GetAudioResource());
Check(patch_resource);
patch_resource->SetDistance(GetDistanceToSource());
patch_resource->SetupPatch(channelSet);
/*patch_resource->SetDistance(GetDistanceToSource());
for (i = 0; i < AudioChannelSetSize; i++)
{
channel = channelSet.GetNth(i);
patch_resource->SetupPatch(channel);
}*/
//
// Set the channels to default control values
//
//MIDIValue midi_reverb_level =
// audio_head->GetGlobalReverbScale() *
// (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f;
/* for (i = 0; i < AudioChannelSetSize; i++)
{
channel = channelSet.GetNth(i);
Check(channel);
channel->SendController(MIDI_REVERB_CONTROL, midi_reverb_level);
channel->SendController(MIDI_CHORUS_CONTROL, MIDI_MIN_CONTROL_VALUE);
}*/
//
// Set the channels to correct pan
//
/* channel = channelSet.GetFrontLeft();
Check(channel);
channel->SendController(MIDI_PAN_CONTROL, MIDI_LEFT_PAN_VALUE);
channel = channelSet.GetFrontRight();
Check(channel);
channel->SendController(MIDI_PAN_CONTROL, MIDI_RIGHT_PAN_VALUE);
channel = channelSet.GetRearLeft();
Check(channel);
channel->SendController(MIDI_PAN_CONTROL, MIDI_LEFT_PAN_VALUE);
channel = channelSet.GetRearRight();
Check(channel);
channel->SendController(MIDI_PAN_CONTROL, MIDI_RIGHT_PAN_VALUE);*/
//
// Set midi history to default control values
//
/*lastFrontLeftMIDIVolume = MIDI_MIN_CONTROL_VALUE;
lastFrontRightMIDIVolume = MIDI_MIN_CONTROL_VALUE;
lastRearLeftMIDIVolume = MIDI_MIN_CONTROL_VALUE;
lastRearRightMIDIVolume = MIDI_MIN_CONTROL_VALUE;
lastFrontLeftMIDIPitchBend = 0; // Set by force update
lastFrontRightMIDIPitchBend = 0; // Set by force update
lastRearLeftMIDIPitchBend = 0; // Set by force update
lastRearRightMIDIPitchBend = 0; // Set by force update
lastMIDIFilterCutoff = MIDI_MAX_CONTROL_VALUE; // Set by patch
//
//--------------------------------------------------------------------------
// Calculate attack time, velocity, and execute model
//--------------------------------------------------------------------------
//
MIDIValue midi_velocity =
CalculateSourceAttackVolumeScale() *
(Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f;
if (UseSourceAttackTime())
{
MIDINRPNValue midi_attack_time =
CalculateSourceAttackTime() *
(Scalar)AWE_VOL_ATTACK_TIME_RANGE + 0.5f;
for (i = 0; i < AudioChannelSetSize; i++)
{
channel = channelSet.GetNth(i);
Check(channel);
channel->SendNRPN(AWE_VOL_ATTACK_TIME_NRPN, midi_attack_time);
}
}*/
ExecuteModel(True);
//
//--------------------------------------------------------------------------
// Start note
//--------------------------------------------------------------------------
//
//TODO: Start OpenAL source
/* for (i = 0; i < AudioChannelSetSize; i++)
{
channel = channelSet.GetNth(i);
Check(channel);
channel->SendNoteOn(GetCurrentNoteValue(), midi_velocity);
}*/
patch_resource->PlayNote(channelSet);
}
//
//#############################################################################
//#############################################################################
//
void
Dynamic3DPatchSource::StopImplementation()
{
Check(this);
//
// Stop note
//
PatchResource *patch_resource;
patch_resource = Cast_Object(PatchResource*, GetAudioResource());
Check(patch_resource);
patch_resource->StopNote(channelSet);
/* AudioChannel *channel;
for (int i = 0; i < AudioChannelSetSize; i++)
{
channel = channelSet.GetNth(i);
Check(channel);
channel->SendNoteOff(GetCurrentNoteValue(), MIDI_MIN_CONTROL_VALUE);
}*/
}
//
//#############################################################################
//#############################################################################
//
void
Dynamic3DPatchSource::ExecuteModel(Logical force_update)
{
Check(this);
//
//--------------------------------------------------------------------------
// Call inherited method
//--------------------------------------------------------------------------
//
L4AudioSource::Execute();
//
//--------------------------------------------------------------------------
// Get audio resource
//--------------------------------------------------------------------------
//
PatchResource *patch_resource;
patch_resource = Cast_Object(PatchResource*, GetAudioResource());
Check(patch_resource);
//
//--------------------------------------------------------------------------
// Get audio location
//--------------------------------------------------------------------------
//
L4AudioLocation *audio_location;
L4AudioRenderer *audio_renderer;
AudioHead *audio_head;
audio_location = Cast_Object(L4AudioLocation*, GetAudioLocation());
Check(audio_location);
Check(application);
audio_renderer =
Cast_Object(L4AudioRenderer*, application->GetAudioRenderer());
Check(audio_renderer);
audio_head = audio_renderer->GetAudioHead();
Check(audio_head);
//
//--------------------------------------------------------------------------
// Render spatial model
//--------------------------------------------------------------------------
//
//TODO: Sync location info to OpenAL sources
Vector3D pos;
Vector3D locationPosition = audio_location->GetLinkedEntity()->localOrigin.linearPosition;
Vector3D headPosition = audio_head->GetHeadEntity()->localOrigin.linearPosition;
pos.Subtract(locationPosition, headPosition);
float posMag = pos.Length();
pos.MultiplyByInverse(pos, audio_head->GetHeadEntity()->localToWorld);
Vector3D relative_velocity;
relative_velocity.MultiplyByInverse(
audio_location->GetLinkedEntity()->GetWorldLinearVelocity(),
audio_head->GetHeadEntity()->localToWorld
);
Check(&relative_velocity);
Scalar volume_scale = CalculateSourceVolumeScale();
Scalar pitch_offset;
pitch_offset = CalculateSourcePitchOffset();
double relativePitch = pow(2.0,pitch_offset/1200.0);
Clamp(relativePitch,0.5,2.0);
for (int i=0; i < channelSet.count; i++)
{
alSource3f(channelSet.sources[i],AL_POSITION,pos.x,pos.y,pos.z);
alSourcef(channelSet.sources[i], AL_GAIN, volume_scale);
alSource3f(channelSet.sources[i],AL_VELOCITY,-relative_velocity.x,-relative_velocity.y,-relative_velocity.z);
alSourcef(channelSet.sources[i],AL_MAX_DISTANCE,audio_location->getMaxDistance(audio_head));
}
}
//
//#############################################################################
//#############################################################################
//
AudioControlValue
Dynamic3DPatchSource::CalculateSourceVolumeScale()
{
Check(this);
//
// Call inherited method to calculate volume scale
//
Scalar
volume_scale = L4AudioSource::CalculateSourceVolumeScale();
return volume_scale;
//
// Update the spatial model that will result in the value
// for distance related volume attenuation
//
/*Check(application);
Check(application->GetAudioRenderer());
UpdateSpatialModel(application->GetAudioRenderer()->GetAudioHead());
//
// Apply distance attenuation to the volume scale
//
Check(GetAudioLocation());
volume_scale *= GetAudioLocation()->GetDistanceVolumeScale();
return volume_scale;*/
}
//#############################################################################
//####################### Static3DPatchSource ###########################
//#############################################################################
//
//#############################################################################
//#############################################################################
//
Static3DPatchSource::Static3DPatchSource(
PlugStream *stream,
Entity *entity
):
L4AudioSource(stream, entity),
position(0.0f, 0.0f, 0.0f)
{
MemoryStream_Read(stream, &useInternalSpatialization);
}
Logical Static3DPatchSource::IsAudioSourceClipped(AudioHead *audio_head)
{
if (AudioSource::IsAudioSourceClipped(audio_head) || l4_application->GetMissionPlayer()->GetPlayerVehicle()->GetSimulationState() == VTV::BurningState)
{
return true;
} else
{
return false;
}
}
//
//#############################################################################
//#############################################################################
//
Static3DPatchSource::~Static3DPatchSource()
{
}
//
//#############################################################################
//#############################################################################
//
void
Static3DPatchSource::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
L4AudioSource::BuildFromPage(stream, name_list, class_ID, object_ID);
if (name_list->FindData("use_internal") != NULL)
{
MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, use_internal);
}
else
{
Logical use_internal = True;
MemoryStream_Write(stream, &use_internal);
}
}
//
//#############################################################################
//#############################################################################
//
Logical
Static3DPatchSource::TestInstance() const
{
L4AudioSource::TestInstance();
if (useInternalSpatialization)
{
Check(&internalSpatialization);
}
return True;
}
//
//#############################################################################
//#############################################################################
//
void
Static3DPatchSource::SetPosition(const Vector3D &vector3D)
{
position = vector3D;
}
//
//#############################################################################
//#############################################################################
//
void
Static3DPatchSource::StartMessageImplementation()
{
Check(this);
L4AudioSource::StartMessageImplementation();
//
//--------------------------------------------------------------------------
// Get audio renderer
//--------------------------------------------------------------------------
//
L4AudioRenderer *audio_renderer;
Check(application);
audio_renderer =
Cast_Object(L4AudioRenderer*, application->GetAudioRenderer());
Check(audio_renderer);
//
//--------------------------------------------------------------------------
// Update spatial parameters
//--------------------------------------------------------------------------
//
if (useInternalSpatialization)
{
//
//-----------------------------------------------------------------------
// Calculate azimuth of position
//-----------------------------------------------------------------------
//
Radian azimuth_of_source;
if (Small_Enough(position.x) && Small_Enough(position.z))
{
azimuth_of_source = 0.0f;
}
else
{
Verify(!(Small_Enough(position.x) && Small_Enough(position.z)));
azimuth_of_source = Arctan(position.x, position.z);
}
Verify(azimuth_of_source <= PI && azimuth_of_source >= -PI);
internalSpatialization.CalculateSpatialization(azimuth_of_source);
}
else
{
UpdateSpatialModel(audio_renderer->GetAudioHead());
Cast_Object(L4AudioLocation*, GetAudioLocation())->GetSpatialization(
&internalSpatialization
);
}
//
//--------------------------------------------------------------------------
// Init channel set to required channels
//--------------------------------------------------------------------------
//
/* channelSet.EnableFrontLeft(False);
channelSet.EnableFrontRight(False);
channelSet.EnableRearLeft(False);
channelSet.EnableRearRight(False);
switch (GetQuadrant())
{
case L4AudioSpatialization::Quadrant1:
channelSet.EnableFrontLeft(True);
break;
case L4AudioSpatialization::Quadrant2:
channelSet.EnableFrontLeft(True);
channelSet.EnableRearLeft(True);
break;
case L4AudioSpatialization::Quadrant3:
channelSet.EnableRearLeft(True);
break;
case L4AudioSpatialization::Quadrant4:
channelSet.EnableFrontRight(True);
channelSet.EnableRearRight(True);
break;
}*/
//
//--------------------------------------------------------------------------
// Request start from renderer
//--------------------------------------------------------------------------
//
//audio_renderer->StartRequest(this);
(static_cast<L4AudioRenderer*>(application->GetAudioRenderer()))->StartRequest(this);
// Cast_Object(L4AudioRenderer*, application->GetAudioRenderer())->
// StartRequest(this);
}
//
//#############################################################################
//#############################################################################
//
void
Static3DPatchSource::StartImplementation()
{
Check(this);
L4AudioSource::StartImplementation();
//
//--------------------------------------------------------------------------
// Get audio head constants
//--------------------------------------------------------------------------
//
L4AudioRenderer *audio_renderer;
AudioHead *audio_head;
Check(application);
audio_renderer =
Cast_Object(L4AudioRenderer*, application->GetAudioRenderer());
Check(audio_renderer);
audio_head = audio_renderer->GetAudioHead();
Check(audio_head);
//
//--------------------------------------------------------------------------
// Setup the channel
//--------------------------------------------------------------------------
//
ExecuteWatchers();
//
// Turn the volume down while setting up the channels
//
int i;
/* AudioChannel *channel;
for (i = 0; i < AudioChannelSetSize; i++)
{
if ((channel = channelSet.GetNth(i)) != NULL)
{
Check(channel);
channel->SendController(MIDI_VOLUME_CONTROL, MIDI_MIN_CONTROL_VALUE);
}
}*/
//
// Set the channels to the bank and program
//
PatchResource *patch_resource;
patch_resource = Cast_Object(PatchResource*, GetAudioResource());
Check(patch_resource);
patch_resource->SetDistance(GetDistanceToSource());
patch_resource->SetupPatch(channelSet);
/*for (i = 0; i < AudioChannelSetSize; i++)
{
if ((channel = channelSet.GetNth(i)) != NULL)
{
patch_resource->SetupPatch(channel);
}
}*/
//
// Set the channels to default control values
//
/*MIDIValue midi_reverb_level =
audio_head->GetGlobalReverbScale() *
(Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f;*/
/*for (i = 0; i < AudioChannelSetSize; i++)
{
if ((channel = channelSet.GetNth(i)) != NULL)
{
Check(channel);
channel->SendController(MIDI_REVERB_CONTROL, midi_reverb_level);
channel->SendController(MIDI_CHORUS_CONTROL, MIDI_MIN_CONTROL_VALUE);
}
}*/
//
// Set the channels to correct pan
//
/*
switch (GetQuadrant())
{
case L4AudioSpatialization::Quadrant1:
{
const Radian azimuth_max =
45.0*RAD_PER_DEG; // HACK - should come from head
const Scalar slope =
-(Scalar)MIDI_MAX_CONTROL_VALUE / (2.0f * azimuth_max);
const Scalar intercept =
(MIDI_MAX_CONTROL_VALUE * 0.5f);
MIDIValue
midi_pan;
midi_pan = slope * GetAzimuthOfSource() + intercept;
Check(channelSet.GetFrontLeft());
channelSet.GetFrontLeft()->SendController(
MIDI_PAN_CONTROL,
midi_pan
);
}
break;
case L4AudioSpatialization::Quadrant2:
{
Check(channelSet.GetFrontLeft());
Check(channelSet.GetRearLeft());
channelSet.GetFrontLeft()->SendController(
MIDI_PAN_CONTROL,
MIDI_MIN_CONTROL_VALUE
);
channelSet.GetRearLeft()->SendController(
MIDI_PAN_CONTROL,
MIDI_MIN_CONTROL_VALUE
);
}
break;
case L4AudioSpatialization::Quadrant3:
{
const Radian azimuth_max =
45.0*RAD_PER_DEG; // HACK - should come from head
const Scalar slope =
(Scalar)MIDI_MAX_CONTROL_VALUE / (2.0f * azimuth_max);
const Scalar intercept =
(MIDI_MAX_CONTROL_VALUE * 0.5f);
MIDIValue
midi_pan;
midi_pan = slope * GetAzimuthOfSource() + intercept;
Check(channelSet.GetRearLeft());
channelSet.GetRearLeft()->SendController(
MIDI_PAN_CONTROL,
midi_pan
);
}
break;
case L4AudioSpatialization::Quadrant4:
{
Check(channelSet.GetFrontRight());
Check(channelSet.GetRearRight());
channelSet.GetFrontRight()->SendController(
MIDI_PAN_CONTROL,
MIDI_MAX_CONTROL_VALUE
);
channelSet.GetRearRight()->SendController(
MIDI_PAN_CONTROL,
MIDI_MAX_CONTROL_VALUE
);
}
break;
}*/
//
// Set midi history to default control values
//
/*lastFrontLeftMIDIVolume = MIDI_MIN_CONTROL_VALUE;
lastFrontRightMIDIVolume = MIDI_MIN_CONTROL_VALUE;
lastRearLeftMIDIVolume = MIDI_MIN_CONTROL_VALUE;
lastRearRightMIDIVolume = MIDI_MIN_CONTROL_VALUE;
lastMIDIPitchBend = 0; // Set by force update
lastMIDIFilterCutoff = MIDI_MAX_CONTROL_VALUE; // Set by patch
//
//--------------------------------------------------------------------------
// Calculate attack time, velocity, and execute model
//--------------------------------------------------------------------------
//
MIDIValue midi_velocity =
CalculateSourceAttackVolumeScale() *
(Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f;
if (UseSourceAttackTime())
{
MIDINRPNValue midi_attack_time =
CalculateSourceAttackTime() *
(Scalar)AWE_VOL_ATTACK_TIME_RANGE + 0.5f;
for (i = 0; i < AudioChannelSetSize; i++)
{
if ((channel = channelSet.GetNth(i)) != NULL)
{
Check(channel);
channel->SendNRPN(AWE_VOL_ATTACK_TIME_NRPN, midi_attack_time);
}
}
}*/
ExecuteModel(True);
//
//--------------------------------------------------------------------------
// Start note
//--------------------------------------------------------------------------
//
//TODO: Start OpenAL source playing
/*for (i = 0; i < AudioChannelSetSize; i++)
{
if ((channel = channelSet.GetNth(i)) != NULL)
{
Check(channel);
channel->SendNoteOn(GetCurrentNoteValue(), midi_velocity);
}
}*/
patch_resource->PlayNote(channelSet);
}
//
//#############################################################################
//#############################################################################
//
void
Static3DPatchSource::StopImplementation()
{
Check(this);
//
//------------------------------------------------------------
// Stop note
//------------------------------------------------------------
//
//TODO: Stop OpenAL source playing
PatchResource *patch_resource;
patch_resource = Cast_Object(PatchResource*, GetAudioResource());
Check(patch_resource);
patch_resource->StopNote(channelSet);
/*AudioChannel *channel;
for (int i = 0; i < AudioChannelSetSize; i++)
{
if ((channel = channelSet.GetNth(i)) != NULL)
{
Check(channel);
channel->SendNoteOff(GetCurrentNoteValue(), MIDI_MIN_CONTROL_VALUE);
}
}*/
}
//
//#############################################################################
//#############################################################################
//
void
Static3DPatchSource::ExecuteModel(Logical force_update)
{
Check(this);
//
//--------------------------------------------------------------------------
// Get audio resource
//--------------------------------------------------------------------------
//
PatchResource *patch_resource;
patch_resource = Cast_Object(PatchResource*, GetAudioResource());
Check(patch_resource);
Scalar volume_scale = CalculateSourceVolumeScale();
L4AudioLocation *audio_location = Cast_Object(L4AudioLocation*, GetAudioLocation());
Check(application);
L4AudioRenderer *audio_renderer =
Cast_Object(L4AudioRenderer*, application->GetAudioRenderer());
Check(audio_renderer);
AudioHead *audio_head = audio_renderer->GetAudioHead();
Check(audio_head);
Scalar pitch_offset;
pitch_offset = CalculateSourcePitchOffset();
double relativePitch = pow(2.0,pitch_offset/1200.0);
Clamp(relativePitch,0.5,2.0);
Vector3D relative_position;
Vector3D relative_velocity;
if (useInternalSpatialization)
{
relative_position = position;
} else
{
relative_position = audio_location->GetVectorToSource();
}
//Static models have their position freely available as relative positions and stand still
for (int i=0; i < channelSet.count; i++)
{
alSourcef(channelSet.sources[i], AL_GAIN, volume_scale);
alSource3f(channelSet.sources[i],AL_POSITION,relative_position.x,relative_position.y,relative_position.z);
alSourcef(channelSet.sources[i],AL_MAX_DISTANCE,audio_location->getMaxDistance(audio_head));
}
//
//--------------------------------------------------------------------------
// Render spatial model
//--------------------------------------------------------------------------
//
/*AudioChannel *front_left_channel = channelSet.GetFrontLeft();
AudioChannel *front_right_channel = channelSet.GetFrontRight();
AudioChannel *rear_left_channel = channelSet.GetRearLeft();
AudioChannel *rear_right_channel = channelSet.GetRearRight();*/
//TODO: Update spatial stuff?
//
// Apply volume scale offset
//
//Scalar volume_scale = CalculateSourceVolumeScale();
//
// Apply pitch offset and calculate MIDI pitch bend
//
/*Scalar pitch_offset;
MIDIPitchBend midi_pitch_bend;
pitch_offset = CalculateSourcePitchOffset();
midi_pitch_bend = pitch_offset * MIDI_PITCH_PER_CENTS + 0.5f;
Clamp(midi_pitch_bend, -MIDI_PITCH_BEND_MAX, MIDI_PITCH_BEND_MAX);
//
// Apply high frequency scale and calculate NRPN filter cutoff
//
Scalar filter_scale;
MIDINRPNValue max_midi_filter_cutoff;
MIDINRPNValue midi_filter_cutoff;
filter_scale = CalculateSourceBrightnessScale();
max_midi_filter_cutoff = patch_resource->GetMaxMIDIFilterCutoff();
midi_filter_cutoff = filter_scale * (Scalar)max_midi_filter_cutoff + 0.5f;
//
//--------------------------------------------------------------------------
// Send pitch bend
//--------------------------------------------------------------------------
//
const MIDIPitchBend pitch_resolution = 2;
MIDIPitchBend pitch_difference = midi_pitch_bend - lastMIDIPitchBend;
if (Abs(pitch_difference) >= pitch_resolution || force_update)
{
lastMIDIPitchBend = midi_pitch_bend;
switch (GetQuadrant())
{
case L4AudioSpatialization::Quadrant1:
Check(front_left_channel);
front_left_channel->SendPitchBend(midi_pitch_bend);
break;
case L4AudioSpatialization::Quadrant2:
Check(front_left_channel);
front_left_channel->SendPitchBend(midi_pitch_bend);
Check(rear_left_channel);
rear_left_channel->SendPitchBend(midi_pitch_bend);
break;
case L4AudioSpatialization::Quadrant3:
Check(rear_left_channel);
rear_left_channel->SendPitchBend(midi_pitch_bend);
break;
case L4AudioSpatialization::Quadrant4:
Check(front_right_channel);
front_right_channel->SendPitchBend(midi_pitch_bend);
Check(rear_right_channel);
rear_right_channel->SendPitchBend(midi_pitch_bend);
break;
}
}
//
//--------------------------------------------------------------------------
// Send NRPN filter cutoff
//--------------------------------------------------------------------------
//
if (UseSourceBrightnessScale())
{
const MIDIValue filter_resolution = 2;
MIDINRPNValue filter_difference;
filter_difference = midi_filter_cutoff - lastMIDIFilterCutoff;
if (Abs(filter_difference) >= filter_resolution)
{
lastMIDIFilterCutoff = midi_filter_cutoff;
switch (GetQuadrant())
{
case L4AudioSpatialization::Quadrant1:
Check(front_left_channel);
front_left_channel->SendNRPN(
AWE_FILTER_CUTOFF_NRPN,
midi_filter_cutoff
);
break;
case L4AudioSpatialization::Quadrant2:
Check(front_left_channel);
front_left_channel->SendNRPN(
AWE_FILTER_CUTOFF_NRPN,
midi_filter_cutoff
);
Check(rear_left_channel);
rear_left_channel->SendNRPN(
AWE_FILTER_CUTOFF_NRPN,
midi_filter_cutoff
);
break;
case L4AudioSpatialization::Quadrant3:
Check(rear_left_channel);
rear_left_channel->SendNRPN(
AWE_FILTER_CUTOFF_NRPN,
midi_filter_cutoff
);
break;
case L4AudioSpatialization::Quadrant4:
Check(front_right_channel);
front_right_channel->SendNRPN(
AWE_FILTER_CUTOFF_NRPN,
midi_filter_cutoff
);
Check(rear_right_channel);
rear_right_channel->SendNRPN(
AWE_FILTER_CUTOFF_NRPN,
midi_filter_cutoff
);
break;
}
}
}
//
//--------------------------------------------------------------------------
// Send MIDI volume
//--------------------------------------------------------------------------
//
switch (GetQuadrant())
{
case L4AudioSpatialization::Quadrant1:
{
MIDIValue front_left_midi_volume =
volume_scale *
(Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f;
if (front_left_midi_volume != lastFrontLeftMIDIVolume)
{
lastFrontLeftMIDIVolume = front_left_midi_volume;
Check(front_left_channel);
front_left_channel->SendController(
MIDI_VOLUME_CONTROL,
front_left_midi_volume
);
}
}
break;
case L4AudioSpatialization::Quadrant2:
{
MIDIValue front_left_midi_volume =
volume_scale * GetFrontLeftScale() *
(Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f;
MIDIValue rear_left_midi_volume =
volume_scale * GetRearLeftScale() *
(Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f;
if (front_left_midi_volume != lastFrontLeftMIDIVolume)
{
lastFrontLeftMIDIVolume = front_left_midi_volume;
Check(front_left_channel);
front_left_channel->SendController(
MIDI_VOLUME_CONTROL,
front_left_midi_volume
);
}
if (rear_left_midi_volume != lastRearLeftMIDIVolume)
{
lastRearLeftMIDIVolume = rear_left_midi_volume;
Check(rear_left_channel);
rear_left_channel->SendController(
MIDI_VOLUME_CONTROL,
rear_left_midi_volume
);
}
}
break;
case L4AudioSpatialization::Quadrant3:
{
MIDIValue rear_left_midi_volume =
volume_scale *
(Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f;
if (rear_left_midi_volume != lastRearLeftMIDIVolume)
{
lastRearLeftMIDIVolume = rear_left_midi_volume;
Check(rear_left_channel);
rear_left_channel->SendController(
MIDI_VOLUME_CONTROL,
rear_left_midi_volume
);
}
}
break;
case L4AudioSpatialization::Quadrant4:
{
MIDIValue front_right_midi_volume =
volume_scale * GetFrontRightScale() *
(Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f;
MIDIValue rear_right_midi_volume =
volume_scale * GetRearRightScale() *
(Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f;
if (front_right_midi_volume != lastFrontRightMIDIVolume)
{
lastFrontRightMIDIVolume = front_right_midi_volume;
Check(front_right_channel);
front_right_channel->SendController(
MIDI_VOLUME_CONTROL,
front_right_midi_volume
);
}
if (rear_right_midi_volume != lastRearRightMIDIVolume)
{
lastRearRightMIDIVolume = rear_right_midi_volume;
Check(rear_right_channel);
rear_right_channel->SendController(
MIDI_VOLUME_CONTROL,
rear_right_midi_volume
);
}
}
break;
}*/
}