Моя проблема довольно проста, но я все еще пытаюсь найти ответ.Краткий контекст, у меня есть спрайт, который перемещается по оси Y в соответствии с входом микрофона.Заранее я попросил пользователя записать их самую низкую и самую высокую ноты, рассчитал частоту этих двух нот и использую ее в качестве эталона для позиционирования спрайта на оси Y.
Скажем, самая низкая нота - 100 Гц, а самая высокая - 400 Гц.Таким образом, если игрок издает звук с частотой 100 Гц, спрайт должен сместиться вниз до оси Y.Чтобы вернуться к центру (позиция Y по оси Y), игрок должен будет сделать тон 250 Гц (средняя точка между 100 и 400).
Итак, мы знаем, что для этого игрока 250 Гц соответствует Y-позиции 0. Но мне нужно знать эквиваленты Y-позиции нижней ноты (нижний край) и самой высокой ноты (верхний край).Когда я перемещаю спрайт вручную к верхнему краю и смотрю значение Y в инспекторе, оно, по-видимому, равно 4,58.Но я не уверен, что жесткое кодирование 4.58 хорошо масштабируется на устройствах с разными размерами экрана.
Снимок экрана здесь: https://i.ibb.co/pjrkSNV/Capture.png
В идеале я хочу иметь метод FrequencyToY (частота с плавающей запятой), которыйпреобразует значение частоты в соответствующее значение Y на оси.Я сохранил самые низкие и самые высокие значения частоты в PlayerPrefs.Важное замечание о движении спрайтов, я не хочу гравитации.Птица должна просто плавно перемещаться в соответствующую позицию Y каждый раз, когда игрок издает тон, и оставаться на месте в противном случае.
Это мой текущий скрипт, прикрепленный к моему спрайту:
public class Player : MonoBehaviour
{
public AudioSource audioPlayer;
public AudioMixer masterMixer;
private float[] _spectrum;
private float _fSample;
private Transform playerTransform;
void Start()
{
playerTransform = transform;
//Code for microphone loop
masterMixer.SetFloat("masterVolume", -80f);
_spectrum = new float[AudioAnalyzer.QSamples];
_fSample = AudioSettings.outputSampleRate;
audioPlayer.clip = Microphone.Start("", true, 10, 44100);
audioPlayer.loop = true;
while(!(Microphone.GetPosition("") > 0)) { }
audioPlayer.Play();
}
void Update()
{
//Calculate frequency of currently detected tones
audioPlayer.GetSpectrumData(_spectrum, 0, FFTWindow.BlackmanHarris);
float pitchVal = AudioAnalyzer.calculateFrequency(ref _spectrum, _fSample);
if(pitchVal != 0)
{
if (pitchVal < PlayerPrefs.GetFloat("lowestFrequency"))
pitchVal = PlayerPrefs.GetFloat("lowestFrequency");
else if (pitchVal < PlayerPrefs.GetFloat("highestFrequency"))
pitchVal = PlayerPrefs.GetFloat("highestFrequency");
//This is how I'd like to call the function
//But if someone could change this and make the sprite actually
//"move" to that point instead of just popping there it would be awesome!
transform.position = new Vector2(0, FrequencyToY(pitchVal));
}
}
//Converts frequency to position on Y-axis
public float FrequencyToY(float frequency)
{
float x = 0;
return x;
}
}