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;
}

和getspectrananalysis ()

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赫兹而不是220赫兹,等等。所以,我有两个问题:我得到的Hz比我应该得到的少,Hz值跳得太多太快,所以即使声音播放是恒定的,它也不一致。知道如何改进这段代码吗?我哪里出错了?编辑看看我的答案。

Ok,没关系,我找到了解决方案,也许这将有助于有人在这个线程中绊倒,更改getspectrananalysis方法为:

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
}

然后在update方法中像这样调用它:

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

更多信息查看这个线程:Unity答案

最新更新