首页 > 解决方案 > Unity 将麦克风输入转换为赫兹

问题描述

我正在开发一个具有一些麦克风控件的 Unity 应用程序。在某一时刻,我必须将麦克风输入转换为赫兹 (Hz) 值并将它们显示给用户。现在,我做了一些研究,并为此目的制作了以下脚本:

int amountSamples = 1024;

 void Start ()
        {
            _fSample = AudioSettings.outputSampleRate;
        }

 void Update() {
            
            if (focused && Initialized) {
                if (Microphone.IsRecording(selectedDevice) && recording) {
                    
                        spectrumData = GetSpectrumAnalysis();
                        
                        if (spectrumCurve.keys.Length <= spectrumData.Length) {
                           
                            float keyTimeValue = 0;
                            float currentHighestKeyTime = 0;

                            //create a curvefield if none exists
                            spectrumCurve = new AnimationCurve();

                            for (int t = 0; t < spectrumData.Length; t++) {
                                spectrumCurve.AddKey(1 / spectrumData.Length + t, spectrumData[t]);
                                spectrumCurve.MoveKey(1 / spectrumData.Length + t, new Keyframe(1 / spectrumData.Length + t, keyTimeValue = spectrumData[t])); //update keyframe value
                                if (keyTimeValue > currentHighestKeyTime) {
                                    currentHighestKeyTime = keyTimeValue;
                                }
                            }

                            HighestKeyTimeValue = currentHighestKeyTime;
                            float freqN = HighestKeyTimeValue;
                            float f = freqN * (_fSample / 2) / amountSamples;
                            Debug.Log(f); //hz

                        }
                    }
                }
                audioSource.volume = 1;
            }

和 GetSpectrumAnalysis()

 public float[] GetSpectrumAnalysis ()
        {
            float[] dataSpectrum = new float[amountSamples];
            audioSource.GetSpectrumData (dataSpectrum, 0, FFTWindow.BlackmanHarris); 
            for (int i = 0; i <= dataSpectrum.Length - 1; i++)
            {

                dataSpectrum[i] = Mathf.Abs (dataSpectrum[i] * sensitivity);

            }
            return dataSpectrum;

        }

现在,使用此代码,Hz 值应该在float f中计算,它确实有效,但 Hz 值不太准确,例如,我得到 400-500 Hz,而我应该得到大约 880 Hz。同样,我得到的是 130 Hz 而不是 220 Hz,等等。所以,我有两个问题:我得到的 Hz 比我应该得到的要少,而且 Hz 值跳得太多太快,所以即使声音也不一致玩是恒定的。知道如何改进此代码吗?我在哪里做错了?

编辑 检查我的答案以获得解决方案。

标签: c#unity3d

解决方案


好的,没关系,我找到了解决方案,也许这会帮助遇到这个线程的人,将GetSpectrumAnalysis方法更改为:

public float test() {
            float Threshold = 0.02f;
            float[] dataSpectrum = new float[amountSamples];
            audioSource.GetSpectrumData(dataSpectrum, 0, FFTWindow.BlackmanHarris); //Rectangular
            float maxV = 0;
            var maxN = 0;
            for (int i = 0; i < amountSamples; i++) {
                if (!(dataSpectrum[i] > maxV) || !(dataSpectrum[i] > Threshold)) {
                    continue;
                }

                maxV = dataSpectrum[i];
                maxN = i; // maxN is the index of max
            }

            float freqN = maxN; // pass the index to a float variable
            if (maxN > 0 && maxN < amountSamples - 1) { // interpolate index using neighbours
                var dL = dataSpectrum[maxN - 1] / dataSpectrum[maxN];
                var dR = dataSpectrum[maxN + 1] / dataSpectrum[maxN];
                freqN += 0.5f * (dR * dR - dL * dL);
            }

            return freqN * (_fSample / 2) / amountSamples; // convert index to frequency
        }

然后只需在更新方法中调用它,如下所示:

Text.text = test().ToString("00");

有关更多信息,请查看此线程:Unity 答案


推荐阅读