Search Unity

What I've learned about how Unity handles audio sample rates

Discussion in 'General Discussion' started by casimps1, Apr 3, 2014.

  1. casimps1

    casimps1

    Joined:
    Jul 28, 2012
    Posts:
    254
    I've been working on a mobile app that involves recording audio via microphone input and then playing back that audio. As part of that I've been experimenting with how Unity handles sample rates. I wanted to investigate optimizing the audio filesize and also make sure there were no conflicts between mic sample rate, audio file sample rate, and speaker (output) sample rate. There didn't seem to be a lot of info on this topic, so I thought I'd share what I've found. Some of it was expected. Some not so much.

    1) Unity can play inputs of any sample rate - It doesn't matter what the sample rate of an audio file is, Unity can play it and will seamlessly resample the audio to Unity's selected output sample rate (which can be found in AudioSettings.outputSampleRate). This is true on PC and mobile.

    2) Microphone.GetDeviceCaps lies - According to the docs, GetDeviceCaps is what you use to determine what sample rates are supported by the attached microphone. On both of my Android devices, Unity shows a minimum sample rate of 44100 and a maximum sample rate of 44100 for the built-in mic. However, I've found that I can actually record at many other sample rates. I was able to successfully record audio at 12k, 24k, and 48k sample rates by simply specifying those values in Microphone.Start(). I double checked the resulting samples and found that it does seem to truly record at those other rates. I also played back the various sample rates as a triple check and could hear the distortion/noise in the audio recorded at 12k. The reported min and max are a lie.

    3) Setting AudioSettings.outputSampleRate won't necessarily do what you think - The docs note that you can set outputSampleRate to change the output sample rate of Unity's internal audio mixer. I thought maybe that was there as an optimization feature - allowing you to set a lower sample rate if you wanted performance over quality or if you wanted to minimize any up/downsampling. My Android devices default to an output rate of 24k and everything works fine if you leave that alone. But once I changed that to 12k, all audio plays twice as fast. This was regardless of the input sample rate of the audio file. Setting output rate to 48k made all audio play at half-speed. If I had to guess, I'd assume there's maybe some kind of hardware limitation that restricts my device to only output at a 24k sample rate? Maybe Unity's mixer actually downsamples the output to 12k and then something else down the chain says "Nope! I've gotta output this at 24k" so it plays it twice as fast. Regardless, it makes the outputSampleRate setting useless to me.

    Anyway, I learned a lot playing with Unity's audio system. Hope this helps someone! If anyone has any insights into the odd things I saw above or any other relevant info to add, feel free!
     
  2. MrMetwurst2

    MrMetwurst2

    Joined:
    Jul 16, 2009
    Posts:
    253
    Yeah, the audio system is a bit deceptive.
    I'm streaming 48,000Hz audio samples to the DSP filter and notice they played at 44,100 Hz (about 2 semitones lower) even though AudioSettings.outputSampleRate says 48,000 Hz.
    I tested this by setting up a counter in OnAudioFilterRead and sure as eggs it returned 44,100 Hz.

    To me this is a bug. There should be a way to read the DSP frequency correctly.
     
  3. Andy-Korth

    Andy-Korth

    Joined:
    Jun 7, 2013
    Posts:
    144
    It sounds like you've found the same thing I've found, casimps1. A few additional notes:

    AudioSettings.outputSampleRate affects how audioSource.GetSpectrumData (the FFT method) calculates the spectrum.

    Some android devices (at least the ASUS MeMO Pad FHD 10, an x86 android tablet (admittedly very odd hardware ) doesn't seem to respect changes to AudioSettings.outputSampleRate. Sometimes I've had changes to the sample rate cause slower playback (as you mentioned), but sometimes not. This device reports a default sample rate of 24000. (not 22050).

    Microphone.Start also takes a sample rate. But if I set AudioSettings.outputSampleRate(24000) and Microphone.Start(..., 24000), the FFT is no longer correct. I'm not sure if Microphone.Start is lying about using that sample rate, or the FFT is not behaving properly.

    On desktop I get different behavior (that is very easy to replicate)
    http://kortham.net/temp/upshot_wb0RJtD5.png

    Whereas in Android, the rate defaults to 24000 and can be set to 41000. After setting it, the rate reports 41000.

    Sorry if this raises more questions than answers, but I suspect it will save someone a lot of time.

    The docs at:
    https://docs.unity3d.com/Documentation/ScriptReference/AudioSettings-outputSampleRate.html
    Don't mention what happens if you set an invalid rate. I have some open documentation requests for GetSpectrumData. Perhaps outputSampleRate needs some too.
     
  4. Shulin_S

    Shulin_S

    Joined:
    Sep 30, 2016
    Posts:
    2
    Thank you! I am just facing this problem now. Have you found any method to let Unity correctly read sample rates on mobile devices?
     
    Last edited: Feb 15, 2018
    Carrotpie likes this.
  5. jhughes2112

    jhughes2112

    Joined:
    Nov 20, 2014
    Posts:
    178
    Sorry for the necropost, but this might save someone time. Be aware that Microphone.GetDeviceCaps may return 16000 as min and max sampling rate on some PC microphones, while it actually delivers 48000hz data to you from the very same microphone. As far as I can tell, there's no way to know what frequency data is arriving at. If you tell Microphone.Start to use 16000 and the data is 48000... It doesn't fail to start, it just works incorrectly. You're just... screwed.
     
    CloudyVR likes this.