Я пытаюсь смоделировать эффект Доплера в игре (игра в автомобильные гонки). Я не использую определенную звуковую библиотеку, которая имитирует эффект, у меня есть только функция обратного вызова, где я смешиваю данные.
Я уже разобрался, как изменить частоту сэмпла в функции микшера.
То, что я не знаю, это то, насколько частота должна меняться в зависимости от положения игрока и эмиттера и его скорости.
Вот что у меня есть в игре:
//player
vec3 p.pos;
vec3 p.vel;
//emitter
vec3 e.pos;
vec3 e.vel;
1) Согласно википедии , соотношение между излучаемой частотой и наблюдаемой частотой определяется как:
float f = (c + vr) / (c + vs) * fo
где c - постоянная, скорость в среде (обычно большое число) vs и 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); ?
однако эта формула предполагает, что приемник не двигается, что здесь не так. если игрок и эмиттер движутся с одинаковой скоростью (или небольшой разницей), эффект допплера не должен быть. эта функция также характерна для одного случая, я полагаю, что окончательная формула должна быть такой же, независимо от ситуации.
РЕДАКТИРОВАТЬ: я пытаюсь найти правильную формулу, используя сообщение 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
нужно вводить в первую формулу википедии:
Я протестировал его, и он успешно работает, обеспечивая отличные результаты.
Ответы:
1) Предполагается, что оба объекта движутся по одной и той же линии - (это объясняется на странице википедии, на которую вы ссылались). Ваш вывод верен, в этой ситуации с постоянными скоростями сдвиг частоты является постоянным. Для изменения сдвига частоты необходимо изменить относительные скорости, следовательно, формулу 2), для ситуации, когда
Vs
она постоянна, но не является коллинеарной с осью SR.Однако формула 2) вводит в заблуждение: ее
Vr
следует понимать какVs,r
радиальную / относительную составляющую скорости источника.Обратите внимание, что эффект Доплера зависит только от скоростей, вам нужны только позиции, чтобы найти ось SR.
Изменить : это должно помочь вам выяснить скорости, вам нужно использовать
Vs,r
иVr,r
величины с формулой 1:источник
Для XACT существует скалярная переменная доплеровского шага, то есть относительная скорость, где 1,0 - это та же скорость, но <1,0 медленнее, а> 1,0 быстрее.
Спасибо вам, ребята, за код, который я перенес на этот кусок C #, где звук рассчитывается между положением экрана и сигналом. Работает точно
Btw.
источник