x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

How to change sound volume in C++?

How to change a sound class's volume in C++? I'm trying to build an audio options menu, where you can configure the Master (overall) volume, Effects volume, Music volume, Voice volume, etc.

I tried changing it via GEngine->GetAudioDevice()->SetClassVolume(SoundClass, Volume);, but nothing happens. Below is the full code.

 void FShooterOptions::ChangeVolume(FString ClassName, float Volume)
 {
     FAudioDevice* Device = GEngine->GetAudioDevice();
     if (!Device)
     {
         return;
     }
     
     USoundClass* SoundClass = NULL;
     for (TMap<USoundClass*, FSoundClassProperties>::TIterator It(Device->SoundClasses); It; ++It)
     {
         USoundClass* ThisSoundClass = It.Key();
         if (ThisSoundClass && ThisSoundClass->GetFullName().Find(ClassName) != INDEX_NONE)
         {
             SoundClass = ThisSoundClass;
             break;
         }
     }
 
     if (SoundClass)
     {
         Device->SetClassVolume(SoundClass, Volume);
     }
 }

I debugged the code and it was finding the sound classes (Master, SFX, etc.), and it was assigning the new values, but the volume didn't actually change.

Product Version: Not Selected
Tags:
more ▼

asked Jul 12 '14 at 03:54 AM in C++ Programming

avatar image

Ixiguis
1.1k 57 59 252

(comments are locked)
10|2000 characters needed characters left

3 answers: sort voted first

Small improvement

I'd like to suggest a small improvement I did on the function. As the finding class by name part uses FString::Find it could get the wrong class searching for a name that's part of another class. For example, it could give you SFX_Weapons while searching for SFX, as SFX_Weapons also contains SFX. So, instead, I look for the part after the . in the full name. The names are like Engine/Something/Sound.Master , so the class name we look for is right after the only . in the name. Splitting the name by the . and getting the right part, we have the class name only.

Code (tested on 4.10.4)

 #include "AudioDevice.h"
 
 void SetSoundClassVolume(FString ClassName, float Volume, bool &Success)
 {
     FAudioDevice* AudioDevice = GEngine->GetMainAudioDevice();
 
     Success = false;
     if (!AudioDevice) return;
 
     for (auto i = AudioDevice->SoundClasses.CreateIterator(); i; ++i)
     {
         USoundClass* SoundClass = i.Key();
         FString SoundClassName;
 
         // Test if the Split function works then, if the name was the right one
         if (SoundClass->GetFullName().Split(L".", nullptr, &SoundClassName, ESearchCase::CaseSensitive)
             && SoundClassName.Equals(ClassName))
         {
             SoundClass->Properties.Volume = Volume;
             Success = true;
             return;
         }
     }
 }
more ▼

answered Mar 10 '16 at 10:17 PM

avatar image

RVillani
1.1k 28 38 90

(comments are locked)
10|2000 characters needed characters left

I've managed to achieve that by changing sound class volume property. Instead of

 Device->SetClassVolume(SoundClass, Volume);

try

 SoundClass->Properties.Volume = NewMasterSoundVolume;

Also make sure there is only one "Master" sound class.

more ▼

answered Jul 13 '14 at 10:31 PM

avatar image

sailentz
26 1 4 5

avatar image Ixiguis Jul 13 '14 at 11:47 PM

Also make sure there is only one "Master" sound class.

That was the problem! There were 3 'Master' sound classes registered on the device, for some reason. Hmm ahh: one from the Engine, one from Game/Sounds (maybe from ShooterGame), and one from Game/ExampleContent (from the examples project).

So the solution is:

 void FShooterOptions::ChangeVolume(FString ClassName, float Volume)
 {
     FAudioDevice* Device = GEngine->GetAudioDevice();
     if (!Device)
     {
         return;
     }
     
     for (TMap<USoundClass*, FSoundClassProperties>::TIterator It(Device->SoundClasses); It; ++It)
     {
         USoundClass* SoundClass = It.Key();
         if (SoundClass && SoundClass->GetFullName().Find(ClassName) != INDEX_NONE)
         {
             Device->SetClassVolume(SoundClass, Volume);
         }
     }
 }

Thanks!

avatar image sds-michael Oct 03 '14 at 07:47 AM

Thanks for posting this code - was a great time saver!

avatar image MisterMonday May 21 '15 at 09:44 PM

Since 4.7 it's

 SoundClass->Properties.Volume = Volume;

instead of

 Device->SetClassVolume(SoundClass, Volume);




(comments are locked)
10|2000 characters needed characters left

In the newer version of Unreal Engine FAudioDevice::SoundClasses has been made private. Instead the default USoundClass can be easily accessed from UAudioSettings or if the access of a custom USoundClass is desired it can be accessed by calling LoadObject<>().

 // Change volume of SoundClass by specifying asset path to SoundClass
 ChangeVolume(float volume, FSoftObjectPath soundClassPath) {

     // Guard statement against invalid FSoftObjectPath
     if (!soundClassPath.IsValid())
     {
         return;
     }

     // Load object if not already loaded
     USoundClass* soundClass = LoadObject<USoundClass>(nullptr, *soundClassPath.ToString());

     // Guard against unsuccessful object instantiation
     if (soundClass == nullptr) {
         return;
     }

     // 
     soundClass->Properties.Volume = volume;
 }

 // Change the volume of the default SoundClass
 ChangeDefaultVolume(float volume) {
      const FSoftObjectPath DefaultSoundClassName = GetDefault<UAudioSettings>()->DefaultSoundClassName;
     
     if (!DefaultSoundClassName.IsValid())
     {
         return;
     }
 
     USoundClass* masterSoundClass = LoadObject<USoundClass>(nullptr, *DefaultSoundClassName.ToString());
 
     if (masterSoundClass == nullptr) {
         return;
     }
 
     masterSoundClass->Properties.Volume = volume;
 }
more ▼

answered Jan 13 '18 at 09:36 PM

avatar image

Dantali0n
31 3 3

(comments are locked)
10|2000 characters needed characters left
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question