Saya mencoba untuk mensimulasikan efek doppler dalam permainan (permainan balap mobil). Saya tidak menggunakan pustaka suara tertentu yang mensimulasikan efek, saya hanya memiliki fungsi panggilan balik di mana saya mencampur data.
Saya sudah menemukan cara mengubah frekuensi sampel dalam fungsi mixer.
Apa yang saya tidak tahu adalah berapa frekuensi harus berubah tergantung posisi pemain dan emitor dan kecepatan.
Inilah yang saya miliki dalam permainan:
//player
vec3 p.pos;
vec3 p.vel;
//emitter
vec3 e.pos;
vec3 e.vel;
1) Menurut wikipedia , hubungan antara frekuensi yang dipancarkan dan frekuensi yang diamati diberikan oleh:
float f = (c + vr) / (c + vs) * fo
di mana c adalah konstanta, kecepatan dalam medium (biasanya dalam jumlah besar) vs dan vr adalah kecepatan sumber dan penerima relatif terhadap medium.
jadi saya kira:
float vr = p.vel.length; //player speed
float vs = e.vel.length; //emitter speed
tetapi saya pikir itu salah, itu tidak akan menghasilkan perubahan dalam frekuensi, misalnya: jika vr = 0
(pemain tidak bergerak) dan emitor memiliki kecepatan konstan, maka vr
dan vs
tidak akan berubah (sementara mereka harus).
mungkin saya harus menghitung kecepatan pemain relatif terhadap kecepatan emitor?
seperti ini :
relative_speed = distance(p.pos + p.vel, e.pos + e.vel) -
distance(p.pos, e.pos);
lalu bagaimana vr
dan vs
harus diberi makan?
2) wikipedia juga memberikan formula lain untuk mensimulasikan efek kendaraan yang dilewati oleh pengamat:
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); ?
Namun, rumus ini menganggap penerima tidak bergerak, yang tidak terjadi di sini. jika pemain dan emitor bergerak dengan kecepatan yang sama (atau perbedaan kecil), seharusnya tidak ada efek doppler. fungsi ini juga spesifik untuk satu kasus, saya kira rumus terakhir harus sama tanpa situasi.
EDIT: Saya mencoba mencari formula yang benar, menggunakan pos 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:
Bagi yang berminat, berikut adalah rumus terakhir:
vec2 dist = vs.pos - vr.pos;
vr,r = dotproduct(vr.vel, dist) / length(dist)
vs,r = dotproduct(vs.vel, dist) / length(dist)
CATATAN: ini menggunakan proyeksi vektor, dijelaskan di sini :
lalu vr,s
dan vs,r
harus disuntikkan dalam rumus wikipedia pertama:
Saya mengujinya dan berhasil, memberikan hasil yang bagus.