예제 #1
0
        /// <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;
        }
예제 #2
0
        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);
        }
예제 #3
0
        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));
            }
        }
예제 #4
0
        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));
        }
예제 #5
0
 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;
 }
예제 #6
0
        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);
        }
예제 #7
0
        /// <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;
        }