ฉันจะจำลองเอฟเฟกต์ doppler ในเกมได้อย่างไร


14

ฉันพยายามจำลองลักษณะของดอปเลอร์ในเกม (เกมแข่งรถ) ฉันไม่ได้ใช้ไลบรารี่เสียงเฉพาะที่จำลองเอฟเฟกต์ฉันมีฟังก์ชั่นโทรกลับเฉพาะที่ฉันผสมข้อมูล

ฉันหาวิธีเปลี่ยนความถี่ของตัวอย่างในฟังก์ชั่นมิกเซอร์แล้ว

สิ่งที่ฉันไม่รู้ก็คือความถี่ควรเปลี่ยนไปตามตำแหน่งของผู้เล่นและตัวส่งและความเร็ว

นี่คือสิ่งที่ฉันมีในเกม:

//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. 

แก้ไข 2:

สำหรับผู้ที่สนใจนี่คือสูตรสุดท้าย:

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ควรถูกฉีดในสูตรแรกของวิกิพีเดีย:

ป้อนคำอธิบายรูปภาพที่นี่

ฉันทดสอบแล้วใช้งานได้สำเร็จให้ผลลัพธ์ที่ยอดเยี่ยม


3
คุณสามารถปรับสูตรที่สมมติว่าผู้รับไม่ได้เคลื่อนที่โดยแทนที่การเคลื่อนไหวจริงของแหล่งที่มาด้วยการเคลื่อนไหวที่สัมพันธ์กับผู้รับ
yoozer8

คำตอบ:


9

1) สมมติว่าวัตถุทั้งสองเคลื่อนที่ในบรรทัดเดียวกัน - (อธิบายไว้ในหน้าวิกิพีเดียที่คุณเชื่อมโยง) ข้อสรุปของคุณถูกต้องในสถานการณ์นี้ด้วยความเร็วคงที่การเปลี่ยนความถี่คงที่ สำหรับการเปลี่ยนความถี่เพื่อเปลี่ยนความเร็วเชิงสัมพัทธ์จะต้องเปลี่ยนดังนั้นสูตร 2) สำหรับสถานการณ์ที่Vsมีค่าคงที่ แต่ไม่ใช่ colinear กับแกน SR

อย่างไรก็ตามสูตร 2) ทำให้เข้าใจผิด: Vrควรอ่านVs,rว่านั่นคือส่วนประกอบรัศมี / สัมพัทธ์ของความเร็วต้นฉบับ

โปรดทราบว่าเอฟเฟกต์ Doppler นั้นขึ้นอยู่กับความเร็วเท่านั้นคุณต้องการตำแหน่งเพื่อค้นหาแกน SR

แก้ไข : สิ่งนี้จะช่วยให้คุณทราบความเร็วคุณต้องใช้Vs,rและVr,rปริมาณกับสูตร 1:

ความเร็วสัมพัทธ์สำหรับ Doppler shift


ตกลงขอบคุณสำหรับคำตอบของคุณ (และรูปภาพ) มันช่วยได้มาก ตอนนี้ทุกอย่างชัดเจนฉันควรรวมสูตร 1 และ 2 เข้าด้วยกัน ดังที่คุณอธิบายไว้ formula2 จะเป็นประโยชน์เมื่อวัตถุไม่อยู่ในบรรทัดเดียวกัน ส่วนสุดท้ายคือการหา vr, r และ vs, r vr, r = vr.vel * cos (shortest_angle_between (vr.vel, vs.pos - vr.pos)); vs, r = vs.vel * cos (shortest_angle_b ระหว่าง (vs.vel, vr.pos - vs.pos)); // มีวิธีที่ง่ายกว่า / เร็วกว่าในการค้นหาพวกเขาหรือไม่? // note vr.vel และ vs.vel เป็นเวกเตอร์, ลูกศรสีเขียวและสีแดงบนรูปภาพ SkimFlux
tigrou

ฉันแก้ไขโพสต์แรกและเพิ่มสูตรด้วยการจัดรูปแบบที่ถูกต้อง คุณตรวจสอบได้ไหม (ครั้งแรกที่ฉันใช้ stackexchange gamedev ฉันไม่เคยรู้ว่ามันให้ผลตอบแทนบรรทัดในการตอบกลับและที่แสดงความคิดเห็นถูกล็อคหลังจากนั้น 5 นาที ... .)
tigrou

@ user1083855 ใช่พวกมันถูกต้อง วิธีหนึ่งที่จะทำให้ง่ายขึ้น / เร็วขึ้นก็คือการทำตามคำแนะนำของจิมและใช้สูตร 2) โดยมีการเคลื่อนที่สัมพัทธ์ระหว่างทั้งสอง ฉันไม่คิดว่ามันจะเหมือนกันเพราะเอฟเฟกต์ Doppler ที่แท้จริงขึ้นอยู่กับความเร็วของเอนทิตีทั้งสองที่สัมพันธ์กับเสียงกลาง (อากาศ) แต่ในสถานการณ์เกมมันอาจจะอยู่ใกล้พอและช่วยให้คุณประหยัดค่าใช้จ่ายได้
SkimFlux

ดีจริงฉันพบวิธีที่ง่ายกว่ามากในการค้นหา vr, r vs, r: en.wikipedia.org/wiki/Vector_project
tigrou

0

สำหรับ XACT ควรมีการระบุตัวแปรสเกลาร์ doppler pitch scalar เช่นความเร็วสัมพัทธ์โดยที่ 1.0 คือความเร็วเดียวกัน แต่ <1.0 ช้าลงและ> 1.0 เร็วขึ้น

ขอบคุณพวกคุณสำหรับรหัสที่ฉันถ่ายโอนไปยังชิ้นส่วนของ C # นี้ที่มีการคำนวณเสียงระหว่างตำแหน่งหน้าจอและคิว ทำงานได้อย่างแม่นยำ

soundElements.ForEach(e =>
            {
                var cuePosition = new Vector3(e.PhysicPosition, 0);
                var distance = cuePosition - ScreenCenter;
                var distanceLength = distance.Length();
                e.Cue.SetVariable("Distance", distanceLength);
                var dopplerPitchScalar = 1.0f;
                if (e.AssociatedBody != null)
                {
                    ///gamedev/23583/how-do-i-simulate-a-doppler-effect-in-a-game
                    var screenVelocity = Vector3.Dot(ScreenVelocity, distance) / distanceLength;
                    var cueVelocity = Vector3.Dot(new Vector3(e.AssociatedBody.LinearVelocity, 0), distance) / distanceLength;
                    var relativeVelocity = screenVelocity - cueVelocity;
                    dopplerPitchScalar = (1f + relativeVelocity / SoundEffect.SpeedOfSound) / (1f - relativeVelocity / SoundEffect.SpeedOfSound);
                    //Console.WriteLine($"C: {ScreenCenter}, V: {ScreenVelocity}, D: {dopplerPitchScalar}");
                }
                e.Cue.SetVariable("DopplerPitchScalar", dopplerPitchScalar);
            });

Btw

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.