c# - 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 值跳得太多太快,所以即使声音也不一致玩是恒定的。知道如何改进此代码吗?我在哪里做错了?
编辑 检查我的答案以获得解决方案。
解决方案
好的,没关系,我找到了解决方案,也许这会帮助遇到这个线程的人,将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 答案
推荐阅读
- javascript - 如何从 forEach 减少数组
- javascript - Font Awesome 5 (SVG):jQuery toggleClass 不起作用
- linked-list - 链接列表 - 对象引用未设置为对象实例
- kubernetes - 检测何时在 openfaas 中创建了函数
- python - 如何按列删除熊猫中的重复行;但不将 None 与 None 值进行比较
- c# - 无法更新 Access 数据库 DataGridView
- python - pip 和 AWS CLI 的 SSL 自签名证书错误
- nginx - Nginx 从环境变量中设置 SSL 证书值
- amazon-web-services - 在本地调用“aws ecr-public get-login-password”时出错
- javascript - 不确定在 R3F 中使用 Cannon.js 和导入模型的最佳方式