J'essaie de simuler l'effet doppler dans un jeu (un jeu de course automobile). Je n'utilise pas de bibliothèque de sons spécifique qui simule l'effet, je n'ai qu'une fonction de rappel où je mixe les données.
J'ai déjà compris comment changer la fréquence d'un échantillon dans la fonction de mixage.
Ce que je ne sais pas, c'est à quel point la fréquence doit changer en fonction de la position et de la vitesse du joueur et de l'émetteur.
Voici ce que j'ai dans le jeu:
//player
vec3 p.pos;
vec3 p.vel;
//emitter
vec3 e.pos;
vec3 e.vel;
1) Selon wikipedia , la relation entre la fréquence émise et la fréquence observée est donnée par:
float f = (c + vr) / (c + vs) * fo
où c est une constante, la vitesse dans le milieu (généralement un grand nombre) vs et vr sont les vitesses source et réceptrice par rapport au milieu.
donc je suppose :
float vr = p.vel.length; //player speed
float vs = e.vel.length; //emitter speed
mais je pense que c'est faux, cela ne produira aucun changement de fréquence, par exemple: si vr = 0
(le joueur ne bouge pas) et l'émetteur ont une vitesse constante, alors vr
et vs
ne changera pas (alors qu'ils le devraient).
peut-être devrais-je calculer la vitesse du joueur par rapport à la vitesse de l'émetteur?
comme ça :
relative_speed = distance(p.pos + p.vel, e.pos + e.vel) -
distance(p.pos, e.pos);
alors comment vr
et vs
devrait être nourrir?
2) wikipedia donne également une autre formule pour simuler l'effet d'un véhicule que ce véhicule passe par l'observateur:
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); ?
cependant, cette formule suppose que le récepteur ne bouge pas, ce qui n'est pas le cas ici. si le joueur et l'émetteur se déplacent à la même vitesse (ou à une petite différence), il ne devrait pas y avoir d'effet doppler. cette fonction est également spécifique à un cas, je suppose que la formule finale devrait être la même quelle que soit la situation.
EDIT: j'essaie de trouver la bonne formule, en utilisant le post 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:
Pour les intéressés, voici la formule finale:
vec2 dist = vs.pos - vr.pos;
vr,r = dotproduct(vr.vel, dist) / length(dist)
vs,r = dotproduct(vs.vel, dist) / length(dist)
REMARQUE: il utilise une projection vectorielle, décrite ici :
puis vr,s
et vs,r
devrait être injecté dans la première formule wikipedia:
Je l'ai testé et cela fonctionne avec succès, fournissant de grands résultats.