Estoy tratando de simular el efecto Doppler en un juego (un juego de carreras de autos). No estoy usando una biblioteca de sonido específica que simule el efecto, solo tengo una función de devolución de llamada donde mezclo los datos.
Ya descubrí cómo cambiar la frecuencia de una muestra en la función del mezclador.
Lo que no sé es cuánto debería cambiar la frecuencia dependiendo de la posición y velocidad del jugador y del emisor.
Esto es lo que tengo en el juego:
//player
vec3 p.pos;
vec3 p.vel;
//emitter
vec3 e.pos;
vec3 e.vel;
1) Según Wikipedia , la relación entre la frecuencia emitida y la frecuencia observada viene dada por:
float f = (c + vr) / (c + vs) * fo
donde c es una constante, la velocidad en el medio (generalmente un gran número) vs y vr son las velocidades de origen y receptor en relación con el medio.
así que supongo:
float vr = p.vel.length; //player speed
float vs = e.vel.length; //emitter speed
pero creo que está mal, no producirá ningún cambio en la frecuencia, por ejemplo: si vr = 0
(el jugador no se mueve) y el emisor tienen una velocidad constante, entonces vr
y vs
no cambiarán (mientras deberían).
¿Tal vez debería calcular la velocidad del jugador en relación con la velocidad del emisor?
Me gusta esto :
relative_speed = distance(p.pos + p.vel, e.pos + e.vel) -
distance(p.pos, e.pos);
entonces, ¿cómo vr
y vs
debe ser alimentado?
2) Wikipedia también da otra fórmula para simular el efecto de un vehículo que el vehículo pasa por el observador:
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); ?
sin embargo, esta fórmula supone que el receptor no se mueve, lo cual no es el caso aquí. Si el jugador y el emisor se mueven a la misma velocidad (o una pequeña diferencia), no debería haber efecto Doppler. Esta función también es específica para un caso, supongo que la fórmula final debería ser la misma sin importar la situación.
EDITAR: estoy tratando de encontrar la fórmula correcta, usando la publicación de 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:
Para aquellos interesados, aquí está la fórmula final:
vec2 dist = vs.pos - vr.pos;
vr,r = dotproduct(vr.vel, dist) / length(dist)
vs,r = dotproduct(vs.vel, dist) / length(dist)
NOTA: utiliza proyección vectorial, descrita aquí :
entonces vr,s
y vs,r
debería inyectarse en la primera fórmula de Wikipedia:
Lo probé y funciona con éxito, proporcionando excelentes resultados.
Respuestas:
1) Asume que ambos objetos se mueven en la misma línea - (esto se explica en la página de wikipedia que ha vinculado) su conclusión es correcta, en esta situación, con velocidades constantes, el cambio de frecuencia es constante. Para que el cambio de frecuencia cambie, las velocidades relativas deben cambiar, de ahí la fórmula 2), para la situación donde
Vs
es constante pero no colineal con el eje SR.Sin embargo, la fórmula 2) es engañosa:
Vr
debe leerse comoVs,r
, es decir, el componente radial / relativo de la velocidad de la fuente.Tenga en cuenta que el efecto Doppler depende solo de las velocidades, solo necesita las posiciones para encontrar el eje SR.
Editar : esto debería ayudarlo a calcular las velocidades, debe usar las cantidades
Vs,r
yVr,r
con la fórmula 1:fuente
Para XACT, existe la variable escalar de tono doppler, es decir, velocidad relativa, donde 1.0 es la misma velocidad, pero <1.0 es más lento y> 1.0 es más rápido
Gracias a todos por el código, que he transferido a esta pieza de C #, donde se calcula un sonido entre la posición de la pantalla y una señal. Trabaja con precisión
Por cierto.
fuente