/** * Updates the source specific parameter like e.g. volume and pitch based on the associated * wave instance. */ void FSLESSoundSource::Update( void ) { SCOPE_CYCLE_COUNTER( STAT_AudioUpdateSources ); if( !WaveInstance || Paused ) { return; } float Volume = WaveInstance->Volume * WaveInstance->VolumeMultiplier; if( SetStereoBleed() ) { // Emulate the bleed to rear speakers followed by stereo fold down Volume *= 1.25f; } Volume *= GVolumeMultiplier; Volume = FMath::Clamp(Volume, 0.0f, MAX_VOLUME); const float Pitch = FMath::Clamp<float>(WaveInstance->Pitch, MIN_PITCH, MAX_PITCH); // Set whether to apply reverb SetReverbApplied(true); // Set the HighFrequencyGain value SetHighFrequencyGain(); FVector Location; FVector Velocity; // See file header for coordinate system explanation. Location.X = WaveInstance->Location.X; Location.Y = WaveInstance->Location.Z; // Z/Y swapped to match UE coordinate system Location.Z = WaveInstance->Location.Y; // Z/Y swapped to match UE coordinate system Velocity.X = WaveInstance->Velocity.X; Velocity.Y = WaveInstance->Velocity.Z; // Z/Y swapped to match UE coordinate system Velocity.Z = WaveInstance->Velocity.Y; // Z/Y swapped to match UE coordinate system // We're using a relative coordinate system for un- spatialized sounds. if( !WaveInstance->bUseSpatialization ) { Location = FVector( 0.f, 0.f, 0.f ); } // Set volume & Pitch // also Location & Velocity // Convert volume to millibels. SLmillibel MaxMillibel = 0; SLmillibel MinMillibel = -3000; (*SL_VolumeInterface)->GetMaxVolumeLevel( SL_VolumeInterface, &MaxMillibel ); SLmillibel VolumeMillibel = (Volume * (MaxMillibel - MinMillibel)) + MinMillibel; VolumeMillibel = FMath::Clamp(VolumeMillibel, MinMillibel, MaxMillibel); SLresult result = (*SL_VolumeInterface)->SetVolumeLevel(SL_VolumeInterface, VolumeMillibel); check(SL_RESULT_SUCCESS == result); }
void FMixerSource::UpdateChannelMaps() { SetStereoBleed(); SetLFEBleed(); bool bChanged = false; check(Buffer); if (Buffer->NumChannels == 1) { bChanged = ComputeMonoChannelMap(); } else if (Buffer->NumChannels == 2) { bChanged = ComputeStereoChannelMap(); } else if (Buffer->NumChannels == 4) { bChanged = ComputeQuadChannelMap(); } else if (Buffer->NumChannels == 6) { bChanged = ComputeHexChannelMap(); } else { UE_LOG(LogAudioMixer, Warning, TEXT("Unsupported input audio channels '%d'"), Buffer->NumChannels); return; } if (bChanged) { MixerSourceVoice->SetChannelMap(ChannelMap); } }
/** * Updates the source specific parameter like e.g. volume and pitch based on the associated * wave instance. */ void FCoreAudioSoundSource::Update( void ) { SCOPE_CYCLE_COUNTER( STAT_AudioUpdateSources ); if( !WaveInstance || Paused || !AudioChannel ) { return; } float Volume = WaveInstance->GetActualVolume(); if( Buffer->NumChannels < 3 ) { float Azimuth = 0.0f; float Elevation = 0.0f; if( SetStereoBleed() ) { // Emulate the bleed to rear speakers followed by stereo fold down Volume *= 1.25f; } // apply global multiplier (ie to disable sound when not the foreground app) Volume *= GVolumeMultiplier; Volume = FMath::Clamp<float>( Volume, 0.0f, MAX_VOLUME ); // Convert to dB Volume = 20.0 * log10(Volume); Volume = FMath::Clamp<float>( Volume, -120.0f, 20.0f ); const float Pitch = FMath::Clamp<float>( WaveInstance->Pitch, MIN_PITCH, MAX_PITCH ); // Set the HighFrequencyGain value SetHighFrequencyGain(); if( WaveInstance->bApplyRadioFilter ) { Volume = WaveInstance->RadioFilterVolume; } else if( WaveInstance->bUseSpatialization ) { FRotator Rotation = AudioDevice->InverseTransform.TransformPosition( WaveInstance->Location ).SafeNormal().Rotation(); Azimuth = Rotation.Yaw; Elevation = Rotation.Pitch; } // Apply any debug settings { bool bMuteDry, bMuteReverb, bMuteRadio; switch( AudioDevice->GetMixDebugState() ) { case DEBUGSTATE_IsolateReverb: bMuteDry = true; bMuteReverb = false; bMuteRadio = false; break; case DEBUGSTATE_IsolateDryAudio: bMuteDry = false; bMuteReverb = true; bMuteRadio = true; break; default: bMuteDry = false; bMuteReverb = false; bMuteRadio = false; break; }; // Dry audio or EQ node if( bMuteDry != bDryMuted ) { if( bMuteDry ) { if( StreamSplitterUnit ) { for( int32 OutputChannelIndex = 0; OutputChannelIndex < AudioDevice->Mixer3DFormat.mChannelsPerFrame; ++OutputChannelIndex ) { SAFE_CA_CALL( AudioUnitSetParameter( StreamSplitterUnit, kMatrixMixerParam_Volume, kAudioUnitScope_Output, OutputChannelIndex, 0.0, 0 ) ); } } else { SAFE_CA_CALL( AudioUnitSetParameter( AudioDevice->GetMixer3DUnit(), k3DMixerParam_Gain, kAudioUnitScope_Input, MixerInputNumber, 0.0, 0 ) ); } bDryMuted = true; } else { if( StreamSplitterUnit ) { for( int32 OutputChannelIndex = 0; OutputChannelIndex < AudioDevice->Mixer3DFormat.mChannelsPerFrame; ++OutputChannelIndex ) { SAFE_CA_CALL( AudioUnitSetParameter( StreamSplitterUnit, kMatrixMixerParam_Volume, kAudioUnitScope_Output, OutputChannelIndex, 1.0, 0 ) ); } } bDryMuted = false; } } if( ReverbNode && bMuteReverb != bReverbMuted ) { int ReverbNodeBaseIndex = AudioDevice->Mixer3DFormat.mChannelsPerFrame; if( bMuteReverb ) { for( int32 OutputChannelIndex = 0; OutputChannelIndex < AudioDevice->Mixer3DFormat.mChannelsPerFrame; ++OutputChannelIndex ) { SAFE_CA_CALL( AudioUnitSetParameter( StreamSplitterUnit, kMatrixMixerParam_Volume, kAudioUnitScope_Output, ReverbNodeBaseIndex + OutputChannelIndex, 0.0, 0 ) ); } bReverbMuted = true; } else { for( int32 OutputChannelIndex = 0; OutputChannelIndex < AudioDevice->Mixer3DFormat.mChannelsPerFrame; ++OutputChannelIndex ) { SAFE_CA_CALL( AudioUnitSetParameter( StreamSplitterUnit, kMatrixMixerParam_Volume, kAudioUnitScope_Output, ReverbNodeBaseIndex + OutputChannelIndex, 1.0, 0 ) ); } bReverbMuted = false; } } if( RadioNode && bMuteRadio != bRadioMuted ) { int RadioNodeBaseIndex = ( 1 + ( ReverbNode ? 1 : 0 ) ) * AudioDevice->Mixer3DFormat.mChannelsPerFrame; if( bMuteRadio ) { for( int32 OutputChannelIndex = 0; OutputChannelIndex < AudioDevice->Mixer3DFormat.mChannelsPerFrame; ++OutputChannelIndex ) { SAFE_CA_CALL( AudioUnitSetParameter( StreamSplitterUnit, kMatrixMixerParam_Volume, kAudioUnitScope_Output, RadioNodeBaseIndex + OutputChannelIndex, 0.0, 0 ) ); } bRadioMuted = true; } else { for( int32 OutputChannelIndex = 0; OutputChannelIndex < AudioDevice->Mixer3DFormat.mChannelsPerFrame; ++OutputChannelIndex ) { SAFE_CA_CALL( AudioUnitSetParameter( StreamSplitterUnit, kMatrixMixerParam_Volume, kAudioUnitScope_Output, RadioNodeBaseIndex + OutputChannelIndex, 1.0, 0 ) ); } bRadioMuted = false; } } } if( !bDryMuted || StreamSplitterUnit ) { SAFE_CA_CALL( AudioUnitSetParameter( AudioDevice->GetMixer3DUnit(), k3DMixerParam_Gain, kAudioUnitScope_Input, MixerInputNumber, Volume, 0 ) ); } SAFE_CA_CALL( AudioUnitSetParameter( AudioDevice->GetMixer3DUnit(), k3DMixerParam_PlaybackRate, kAudioUnitScope_Input, MixerInputNumber, Pitch, 0 ) ); SAFE_CA_CALL( AudioUnitSetParameter( AudioDevice->GetMixer3DUnit(), k3DMixerParam_Azimuth, kAudioUnitScope_Input, MixerInputNumber, Azimuth, 0 ) ); SAFE_CA_CALL( AudioUnitSetParameter( AudioDevice->GetMixer3DUnit(), k3DMixerParam_Elevation, kAudioUnitScope_Input, MixerInputNumber, Elevation, 0 ) ); } else { // apply global multiplier (ie to disable sound when not the foreground app) Volume *= GVolumeMultiplier; Volume = FMath::Clamp<float>( Volume, 0.0f, MAX_VOLUME ); if( AudioDevice->GetMixDebugState() == DEBUGSTATE_IsolateReverb ) { Volume = 0.0f; } AudioDevice->SetMatrixMixerInputVolume( MixerInputNumber, Volume ); } }