Sto cercando di simulare l'effetto doppler in un gioco (un gioco di corse automobilistiche). Non sto usando una libreria di suoni specifica che simuli l'effetto, ho solo una funzione di callback in cui mescolo i dati.
Ho già capito come cambiare la frequenza di un campione nella funzione mixer.
Quello che non so è quanto la frequenza dovrebbe cambiare a seconda della posizione e della velocità del lettore e dell'emettitore.
Ecco cosa ho nel gioco:
//player
vec3 p.pos;
vec3 p.vel;
//emitter
vec3 e.pos;
vec3 e.vel;
1) Secondo Wikipedia , la relazione tra frequenza emessa e frequenza osservata è data da:
float f = (c + vr) / (c + vs) * fo
dove c è una costante, la velocità nel mezzo (in genere un numero elevato) vs e vr sono velocità di sorgente e di ricezione relative al mezzo.
immagino :
float vr = p.vel.length; //player speed
float vs = e.vel.length; //emitter speed
ma penso che sia sbagliato, non produrrà alcun cambiamento di frequenza, ad esempio: se vr = 0
(il giocatore non si muove) e l'emettitore hanno una velocità costante, allora vr
e vs
non cambieranno (mentre dovrebbero).
forse dovrei calcolare la velocità del lettore relativamente alla velocità dell'emettitore?
come questo :
relative_speed = distance(p.pos + p.vel, e.pos + e.vel) -
distance(p.pos, e.pos);
allora come vr
e vs
dovrebbe essere nutrito?
2) Wikipedia fornisce anche un'altra formula per simulare l'effetto di un veicolo che il veicolo passa dall'osservatore:
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); ?
tuttavia, questa formula suppone che il ricevitore non si sposti, il che non è il caso qui. se il giocatore e l'emettitore si muovono alla stessa velocità (o piccola differenza), non dovrebbe esserci alcun effetto doppler. questa funzione è specifica anche per un caso, suppongo che la formula finale dovrebbe essere la stessa, non importa la situazione.
EDIT: sto cercando di trovare la formula corretta, usando SkimFlux post:
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:
Per chi fosse interessato, ecco la formula finale:
vec2 dist = vs.pos - vr.pos;
vr,r = dotproduct(vr.vel, dist) / length(dist)
vs,r = dotproduct(vs.vel, dist) / length(dist)
NOTA: utilizza la proiezione vettoriale, descritta qui :
quindi vr,s
e vs,r
dovrebbe essere iniettato nella prima formula di Wikipedia:
L'ho provato e funziona con successo, fornendo grandi risultati.