#include #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); if (getenv("BT_AUDIO_SPATIAL")) { static int s_dp=0; if ((s_dp++ % 120)==0) DEBUG_STREAM << "[spatial] direct src=" << (channelSet.count>0?channelSet.sources[0]:0) << " vol=" << volume_scale << "\n" << std::flush; } 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); if (getenv("BT_AUDIO_SPATIAL")) { static int s_sp=0; if ((s_sp++ % 120) == 0) DEBUG_STREAM << "[spatial] dyn src=" << (channelSet.count>0?channelSet.sources[0]:0) << " head=(" << headPosition.x << "," << headPosition.z << ")" << " loc=(" << locationPosition.x << "," << locationPosition.z << ")" << " dist=" << posMag << " vol=" << volume_scale << "\n" << std::flush; } 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(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; }*/ }