Я намагаюся імітувати ефект допплера в грі (гра в гоночний автомобіль). Я не використовую певну звукову бібліотеку, яка імітує ефект, у мене є лише функція зворотного дзвінка, де я змішую дані.
Я вже зрозумів, як змінити частоту зразка у функції змішувача.
Я не знаю, наскільки частота повинна змінюватися залежно від позиції гравця та випромінювача.
Ось що у мене в грі:
//player
vec3 p.pos;
vec3 p.vel;
//emitter
vec3 e.pos;
vec3 e.vel;
1) Згідно з Вікіпедією , співвідношення між випромінюваною частотою та спостережуваною частотою задається:
float f = (c + vr) / (c + vs) * fo
де c - константа, швидкість у середовищі (зазвичай велика кількість) vs і vr є швидкістю джерела та приймача відносно середовища.
тож я здогадуюсь:
float vr = p.vel.length; //player speed
float vs = e.vel.length; //emitter speed
але я думаю, що це неправильно, він не буде виробляти будь-яких змін частоти, наприклад: якщо vr = 0
(гравець не рухається) і випромінювач мають постійну швидкість, то vr
і vs
звичаї змінюються (поки вони повинні).
може я повинен обчислити швидкість гравця відносно швидкості випромінювача?
подобається це :
relative_speed = distance(p.pos + p.vel, e.pos + e.vel) -
distance(p.pos, e.pos);
то як vr
і vs
слід годувати?
2) wikipedia також дає іншу формулу для імітації ефекту транспортного засобу, який транспортний засіб проходить повз спостерігача:
vr = vs * cos(theta);
//theta is angle between observer and emitter
//theta = atan2(e.pos.y-p.pos.y, e.pos.x-p.pos.x); ?
однак ця формула припускає, що приймач не рухається, що тут не так. якщо гравець і емітер рухаються з однаковою швидкістю (або невеликою різницею), ефекту допплера не повинно бути. ця функція специфічна і для одного випадку, я вважаю, що остаточна формула повинна бути однаковою, не залежно від ситуації.
EDIT: Я намагаюся знайти правильну формулу, використовуючи допис SkimFlux:
vr,r = vr.vel * cos(shortest_angle_between ( vr.vel , vs.pos - vr.pos));
vs,r = vs.vel * cos(shortest_angle_between ( vs.vel , vr.pos - vs.pos));
//is there a easier/faster way to find them out ?
//note: vr.vel and vs.vel are vectors, the green and red arrows on SkimFlux picture.
EDIT2:
Для тих, хто цікавиться, ось остаточна формула:
vec2 dist = vs.pos - vr.pos;
vr,r = dotproduct(vr.vel, dist) / length(dist)
vs,r = dotproduct(vs.vel, dist) / length(dist)
ПРИМІТКА: тут використовується векторна проекція, описана тут :
тоді vr,s
і vs,r
слід вводити у формулу першої вікіпедії:
Я перевірив це, і він працює успішно, даючи чудові результати.