ゲーム(カーレースゲーム)でドップラー効果をシミュレートしようとしています。エフェクトをシミュレートする特定のサウンドライブラリを使用していません。データをミックスするコールバック関数しかありません。
ミキサー機能でサンプルの周波数を変更する方法はすでにわかっています。
私が知らないのは、プレイヤーとエミッターの位置と速度に応じて周波数がどれだけ変化するかです。
ここに私がゲームに持っているものがあります:
//player
vec3 p.pos;
vec3 p.vel;
//emitter
vec3 e.pos;
vec3 e.vel;
1)ウィキペディアによると、放射周波数と観測周波数の関係は次のように与えられます。
float f = (c + vr) / (c + vs) * fo
ここで、Cは定数、媒体の速度(典型的には大きい数)であり、 対と 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)ウィキペディアは、車両がオブザーバーを通過する車両の効果をシミュレートする別の式も提供します。
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); ?
ただし、この式は、レシーバーが動かないことを想定していますが、ここではそうではありません。プレーヤーとエミッターが同じ速度(またはわずかな差)で移動する場合、ドップラー効果はありません。また、この関数は1つのケースに固有です。最終的な式は状況に関係なく同じであると仮定します。
編集:私は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
第Wikipediaの式に注入されるべきです。
私はそれをテストし、うまく機能し、素晴らしい結果を提供しました。