Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
7
Question by unityplease · Apr 07, 2016 at 06:17 PM · audiosourcevolumespeech

How do I get the current volume level (amplitude) of playing audio (not the set volume but how loud it is)

How do I get the current volume level (amplitude) of playing audio (not the set volume but how loud it is)?

There doesn't seem to be an obvious function to get this value. I really just want a simple float value that I can set a mouth blend shape value to - so I can approximate talking, while a character speaks.

I know it might not look perfect but at least the loader the speech the more the mouth will open, and with most speech patterns the volume goes up and down and so will approximate the mouth opening and closing.

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Chris_Entropy · Apr 29, 2016 at 06:07 PM 1
Share

I second this question. There has to be a way, but the only things I found is the function AudioSource.GetOutputData, which no longer exists, and the function AudioClip.GetData, which delivers what I seek, but is too costly on the CPU to be called at regular intervals. Seriously, only one call brings the frame rate down seriously, and I would need it for a bunch of objects, which update at the same time.

/Edit: Ok, scratch that, I had another issue. $$anonymous$$y code works now, and I will write an according answer.

3 Replies

· Add your reply
  • Sort: 
avatar image
15
Best Answer

Answer by Chris_Entropy · Apr 29, 2016 at 06:30 PM

You can use AudioClip.GetData to get what you need. Just write a script like this:

 using UnityEngine;
 
 public class AudioSourceLoudnessTester : MonoBehaviour {
 
     public AudioSource audioSource;
     public float updateStep = 0.1f;
     public int sampleDataLength = 1024;
 
     private float currentUpdateTime = 0f;
 
     private float clipLoudness;
     private float[] clipSampleData;
 
     // Use this for initialization
     void Awake () {
     
         if (!audioSource) {
             Debug.LogError(GetType() + ".Awake: there was no audioSource set.");
         }
         clipSampleData = new float[sampleDataLength];
 
     }
     
     // Update is called once per frame
     void Update () {
     
         currentUpdateTime += Time.deltaTime;
         if (currentUpdateTime >= updateStep) {
             currentUpdateTime = 0f;
             audioSource.clip.GetData(clipSampleData, audioSource.timeSamples); //I read 1024 samples, which is about 80 ms on a 44khz stereo clip, beginning at the current sample position of the clip.
             clipLoudness = 0f;
             foreach (var sample in clipSampleData) {
                 clipLoudness += Mathf.Abs(sample);
             }
             clipLoudness /= sampleDataLength; //clipLoudness is what you are looking for
         }
 
     }
 
 }
 

I update the loudness value only once every 100ms to keep its CPU usage down, and make sure to declare the float[] for the sample data globally, since it could annoy the garbage collector, if you declare a huge array and destroy it again every update step.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image zakirshikhli · Aug 23, 2016 at 09:58 AM 0
Share

Thank You very much !

avatar image wbknox · Jan 10, 2018 at 04:55 PM 1
Share

Thanks so much for this answer, Chris_Entropy. I'll add a couple of notes:

  • If you don't have a specific AudioClip associated with the AudioSource, you can get audio data for whatever combination of clips are playing from AudioSource.GetOutputData(). (https://docs.unity3d.com/ScriptReference/AudioSource.GetOutputData.html)

  • For AudioSource.GetOutputData(), the returned array appears to be the most recently played audio data, not the upco$$anonymous$$g audio data or a mix of the two. So you'll be using slightly stale information.

  • If you want audio data that's centered on now, you might be able to get it by keeping track of what clips were triggered and when, and then looking at the content of those clips (ignoring the AudioSource object).

avatar image
0

Answer by gegagome · Mar 02, 2018 at 05:57 PM

Thanks

Do you know what happens if you have a sample size of 4 or 8 rather than 1024? Do the values match on average?

Comment
Add comment · Show 8 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Chris_Entropy · Mar 02, 2018 at 06:43 PM 0
Share

As you can see in the foreach-loop of my code, I average all my samples. A larger sample size means of course that I get a more average value. With a sample size of 4 or 8, the averages might fluctuate too much to be of actual use. As I said above, a sample size of 1024 equals about 80ms on a 44kHtz clip. A sample size of 8 would hardly be one millisecond.

avatar image gegagome Chris_Entropy · Mar 02, 2018 at 07:04 PM 0
Share

I am trying to detect silence one second ahead and my implementation is now (changed to 1024 from 8) like this: float[] aryOfSamples = new float[1024]; _currentSR = _stems[0].clip.frequency; as.clip.GetData(aryOfSamples, as.timeSamples + (_currentSR * 2))

I am already averaging the values, but my question is: - why would there be negative values in the array? - why are you doing $$anonymous$$athf.Abs? Won't that affect the accuracy of the average value?

Any ideas?

Thanks for your super quick response.

avatar image Chris_Entropy gegagome · Mar 02, 2018 at 07:13 PM 0
Share

It's an audio oscillation amplitude, so naturally there will be negative values as well. The amount of the amplitude is important, be it negative or positive. If I would take the average over the whole sample data, I would in most cases get a value near 0. Therefore the Abs. Only sample values with or near 0 are actually silent. So if you are checking for silence, the $$anonymous$$ath.Abs of each value must be under a certain amount near 0. If you want to peak a full second ahead, you would need a sample size of about over 10 000 (depending on the frequency of your clip). The clip frequency is actually the amount of samples that you need for a full second, since it gives the maximum amount of data points per seconds, i.e. samples.

avatar image gegagome Chris_Entropy · Mar 02, 2018 at 07:48 PM 0
Share
 float[] aryOfSamples = new float[1024];
 _currentSR = _stems[0].clip.frequency;
 as.clip.GetData(aryOfSamples, as.timeSamples + (_currentSR * 1));

I am already checking ahead the full second worth of samples (_currentSR) and it works, but the problem I have is that in audacity I see a flat line all the way until the 17 second marker, but when after averaging I get values of:

 0.04 on second 13
 0.09 on second 14
 0.0000222 on second 15
 0.11 on second 16

I get 90% accurate silence using GetData, except for some points like these.

Not sure why this would happen as I said Audacity shows a flat line, even when I zoom in.

Thanks for your help

avatar image gegagome gegagome · Mar 03, 2018 at 06:34 PM 0
Share

The above problem was due to a problem with my array implementation. After solving the problem I can detect future silences.

avatar image gegagome Chris_Entropy · Mar 03, 2018 at 12:45 AM 0
Share

Think I got it now. if aryOfSamples was of size 44100 like this: float[] aryOfSamples = new float[44100]; It would effectively store every sample in a one-second section of the song, considering the song's frequency is 44100.

So when you use an array of 1024, you are storing 23ms worth of samples, am I correct? I know you said 80ms, but using Audacity I actually selected 1024 samples on a 44.1khz file and ended up selecting 0.023 seconds.

Thanks

avatar image Chris_Entropy gegagome · Mar 03, 2018 at 10:47 AM 0
Share

Yes, you are correct. I don't know why I calculated 80ms the first time.

Show more comments
avatar image
0

Answer by dlstilts · May 15, 2018 at 02:31 PM

Hi I am having trouble trying to implement your code with an audio source with no clip attached with the AudioSource.GetOutputData(). but I keep getting errors? I have the audio coming from a live source and need to monitor the volume. @Chris_Entropy Thanks!

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image krougeau · May 16, 2018 at 05:59 AM 0
Share

You haven't specified what errors you're getting, but if you're trying to use an audio source with no clip, you might try adding the following to the top of your Update function:

         if (audioSource.clip == null)
         {
             return;
         }

which should keep anything from happening until you've actually loaded a clip at runtime. I had the same issue using a file browser to select music, not any particular clip. Hope it helps!

avatar image dlstilts krougeau · May 16, 2018 at 03:18 PM 0
Share

Thank you! That was exactly it. Cheers!

avatar image krougeau dlstilts · May 16, 2018 at 05:56 PM 0
Share

Terrific! Have fun! :D

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

63 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Change audio volume of song depending on scene. 0 Answers

AudioSource not responding to volume change 0 Answers

AudioListener changes only volume and not pitch 1 Answer

Volume Slider not saving when changing scene 1 Answer

Master Audio source volume control with slider 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges