Ich versuche, den Doppler-Effekt in einem Spiel (einem Autorennspiel) zu simulieren. Ich verwende keine bestimmte Soundbibliothek, die den Effekt simuliert. Ich habe nur eine Rückruffunktion, mit der ich die Daten mische.
Ich habe bereits herausgefunden, wie man die Frequenz eines Samples in der Mixer-Funktion ändert.
Was ich nicht weiß, ist, wie sehr sich die Frequenz in Abhängigkeit von der Position und der Geschwindigkeit des Players und des Senders ändern sollte.
Folgendes habe ich im Spiel:
//player
vec3 p.pos;
vec3 p.vel;
//emitter
vec3 e.pos;
vec3 e.vel;
1) Laut Wikipedia ist die Beziehung zwischen der emittierten Frequenz und der beobachteten Frequenz gegeben durch:
float f = (c + vr) / (c + vs) * fo
wobei c eine Konstante ist, ist die Geschwindigkeit in Medium (typischerweise eine große Zahl) vs und vr die Quell- und Empfängergeschwindigkeit relativ zu Medium.
also denke ich:
float vr = p.vel.length; //player speed
float vs = e.vel.length; //emitter speed
aber ich denke, es ist falsch, es wird keine Frequenzänderung hervorrufen, zum Beispiel: wenn vr = 0
(Spieler bewegt sich nicht) und Emitter eine konstante Geschwindigkeit haben, dann vr
und wird sich vs
nicht ändern (solange sie sollten).
Vielleicht sollte ich die Geschwindigkeit des Spielers relativ zur Geschwindigkeit des Emitters berechnen?
so was :
relative_speed = distance(p.pos + p.vel, e.pos + e.vel) -
distance(p.pos, e.pos);
wie vr
und vs
sollte dann gefüttert werden?
2) wikipedia gibt auch eine andere Formel an, um die Wirkung eines Fahrzeugs zu simulieren, das der Beobachter passiert:
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); ?
Diese Formel setzt jedoch voraus, dass sich der Empfänger nicht bewegt, was hier nicht der Fall ist. Wenn sich Player und Emitter mit der gleichen Geschwindigkeit (oder einem geringen Unterschied) bewegen, sollte kein Doppler-Effekt auftreten. Diese Funktion ist auch spezifisch für einen Fall, ich nehme an, die endgültige Formel sollte in jeder Situation gleich sein.
BEARBEITEN: Ich versuche die richtige Formel zu finden, indem ich SkimFlux poste:
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:
Für Interessierte ist hier die endgültige Formel:
vec2 dist = vs.pos - vr.pos;
vr,r = dotproduct(vr.vel, dist) / length(dist)
vs,r = dotproduct(vs.vel, dist) / length(dist)
HINWEIS: Es wird die hier beschriebene Vektorprojektion verwendet :
dann vr,s
und vs,r
sollte in der ersten Wikipedia-Formel injiziert werden:
Ich habe es getestet und es funktioniert erfolgreich und liefert großartige Ergebnisse.