/// <summary> /// 初期設定する /// </summary> /// <param name="room"></param> public void Start(WWRoom room) { var leftEarPos = room.ListenerEarPos(0); var rightEarPos = room.ListenerEarPos(1); var leftSpeakerPos = room.SpeakerPos(0); var rightSpeakerPos = room.SpeakerPos(1); // 左スピーカーから左の耳に音が届く var ll = leftEarPos - leftSpeakerPos; var llN = ll; llN.Normalize(); // エネルギーは、距離の2乗に反比例する // 振幅は、距離の1乗に反比例 // ということにする。 mLeftSpeakerToLeftEar.Add(new WWFirCoefficient(ll.Length / SoundSpeed, llN, 1.0 / ll.Length, true)); // 右スピーカーから右の耳に音が届く var rr = rightEarPos - rightSpeakerPos; var rrN = rr; rrN.Normalize(); mRightSpeakerToRightEar.Add(new WWFirCoefficient(rr.Length / SoundSpeed, rrN, 1.0 / rr.Length, true)); double gain = 1.0; if (WallReflectionType == ReflectionType.Specular) { // なんとなく、高音は逆の耳に届きにくい感じ。 gain = 1.0 / 1.414; } // 左スピーカーから右の耳に音が届く。 // 振幅が-3dBくらいになる。 double attenuationDecibel = -3.0; double attenuationMagnitude = Math.Pow(10.0, attenuationDecibel / 20.0); var lr = rightEarPos - leftSpeakerPos; var lrN = lr; lrN.Normalize(); mLeftSpeakerToRightEar.Add(new WWFirCoefficient(lr.Length / SoundSpeed, lrN, gain * attenuationMagnitude / lr.Length, true)); var rl = leftEarPos - rightSpeakerPos; var rlN = rl; rlN.Normalize(); mRightSpeakerToLeftEar.Add(new WWFirCoefficient(rl.Length / SoundSpeed, rlN, gain * attenuationMagnitude / rl.Length, true)); // 1本のレイがそれぞれのスピーカーリスナー組に入る。 mRouteCount[0] = 1; mRouteCount[1] = 1; }
private double CalcRouteDistance(WWRoom room, int speakerCh, WWRoute route, WWLineSegment lastSegment, Point3D hitPos) { var speakerToHitPos = hitPos - room.SpeakerPos(speakerCh); double distance = speakerToHitPos.Length; for (int i = 0; i < route.Count(); ++i) { var lineSegment = route.GetNth(i); distance += lineSegment.Length; } distance += lastSegment.Length; return(distance); }
private void RedrawRoom() { DrawModel(mRoom.RoomModel, Matrix3D.Identity, new SolidColorBrush(Colors.White)); Matrix3D listenerMatrix = new Matrix3D(); listenerMatrix.Translate((Vector3D)mRoom.ListenerPos); DrawModel(mRoom.ListenerModel, listenerMatrix, new SolidColorBrush(Colors.Gray)); for (int i = 0; i < WWRoom.NUM_OF_SPEAKERS; ++i) { var pos = mRoom.SpeakerPos(i); var dir = mRoom.SpeakerDir(i); Vector3D posV = new Vector3D(pos.X, pos.Y, pos.Z); Vector3D at = new Vector3D(pos.X + dir.X, pos.Y + dir.Y, pos.Z + dir.Z); Vector3D up = new Vector3D(0.0, 1.0, 0.0); Matrix3D speakerMatrixInv = WWMatrixUtil.CalculateLookAt(posV, at, up); var speakerMatrix = speakerMatrixInv; speakerMatrix.Invert(); DrawModel(mRoom.SpeakerModel, speakerMatrix, new SolidColorBrush(Colors.Gray)); } }
private double CalcReflectionGain(ReflectionType type, WWRoom room, int speakerCh, Point3D hitPos, Vector3D rayDir, Vector3D hitSurfaceNormal) { if (type == ReflectionType.Diffuse) { // Lambert's cosine law return(Vector3D.DotProduct(-rayDir, hitSurfaceNormal)); } // specular var reflectionDir = SpecularReflection(rayDir, hitSurfaceNormal); var speakerDir = room.SpeakerPos(speakerCh) - hitPos; speakerDir.Normalize(); var dot = Vector3D.DotProduct(reflectionDir, speakerDir); return(Math.Pow(Saturate0to1(dot), SPECULAR_HARDNESS)); }
private double CalcRouteDistance(WWRoom room, int speakerCh, WWRoute route, WWLineSegment lastSegment, Point3D hitPos) { var speakerToHitPos = hitPos - room.SpeakerPos(speakerCh); double distance = speakerToHitPos.Length; for (int i = 0; i < route.Count(); ++i) { var lineSegment = route.GetNth(i); distance += lineSegment.Length; } distance += lastSegment.Length; return distance; }
private double CalcReflectionGain(ReflectionType type, WWRoom room, int speakerCh, Point3D hitPos, Vector3D rayDir, Vector3D hitSurfaceNormal) { if (type == ReflectionType.Diffuse) { // Lambert's cosine law return Vector3D.DotProduct(-rayDir, hitSurfaceNormal); } // specular var reflectionDir = SpecularReflection(rayDir, hitSurfaceNormal); var speakerDir = room.SpeakerPos(speakerCh) - hitPos; speakerDir.Normalize(); var dot = Vector3D.DotProduct(reflectionDir, speakerDir); return Math.Pow(Saturate0to1(dot), SPECULAR_HARDNESS); }
/// <summary> /// 初期設定する /// </summary> /// <param name="room"></param> public void Start(WWRoom room) { var leftEarPos = room.ListenerEarPos(0); var rightEarPos = room.ListenerEarPos(1); var leftSpeakerPos = room.SpeakerPos(0); var rightSpeakerPos = room.SpeakerPos(1); // 左スピーカーから左の耳に音が届く var ll = leftEarPos - leftSpeakerPos; var llN = ll; llN.Normalize(); // エネルギーは、距離の2乗に反比例する // 振幅は、距離の1乗に反比例 // ということにする。 mLeftSpeakerToLeftEar.Add(new WWFirCoefficient(ll.Length / SoundSpeed, llN, 1.0 / ll.Length, true)); // 右スピーカーから右の耳に音が届く var rr = rightEarPos - rightSpeakerPos; var rrN = rr; rrN.Normalize(); mRightSpeakerToRightEar.Add(new WWFirCoefficient(rr.Length / SoundSpeed, rrN, 1.0 / rr.Length, true)); double gain = 1.0; if (WallReflectionType == ReflectionType.Specular) { // なんとなく、高音は逆の耳に届きにくい感じ。 gain = 1.0/1.414; } // 左スピーカーから右の耳に音が届く。 // 振幅が-3dBくらいになる。 double attenuationDecibel = -3.0; double attenuationMagnitude = Math.Pow(10.0, attenuationDecibel / 20.0); var lr = rightEarPos - leftSpeakerPos; var lrN = lr; lrN.Normalize(); mLeftSpeakerToRightEar.Add(new WWFirCoefficient(lr.Length / SoundSpeed, lrN, gain * attenuationMagnitude / lr.Length, true)); var rl = leftEarPos - rightSpeakerPos; var rlN = rl; rlN.Normalize(); mRightSpeakerToLeftEar.Add(new WWFirCoefficient(rl.Length / SoundSpeed, rlN, gain * attenuationMagnitude / rl.Length, true)); // 1本のレイがそれぞれのスピーカーリスナー組に入る。 mRouteCount[0] = 1; mRouteCount[1] = 1; }