Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
0
        private void DrawRoute(WWRoute route)
        {
            Brush[] brushes = new Brush[] {
                new SolidColorBrush(Colors.Cyan),
                new SolidColorBrush(Colors.Magenta)
            };

            for (int i = 0; i < route.Count(); ++i)
            {
                var     lineSegment = route.GetNth(i);
                Point3D p0          = Point3D.Multiply(lineSegment.StartPos, mWorldProjectionMatrix);
                Point3D p1          = Point3D.Multiply(lineSegment.StartPos + lineSegment.Length * lineSegment.Direction, mWorldProjectionMatrix);

                Brush b = brushes[route.EarCh].Clone();
                b.Opacity = IntensityToOpacity(lineSegment.Intensity);
                AddNewLine(p0, p1, b);

                Point3D pSL = Point3D.Multiply(mRoom.SpeakerPos(0), mWorldProjectionMatrix);
                Point3D pSR = Point3D.Multiply(mRoom.SpeakerPos(1), mWorldProjectionMatrix);
                AddNewLine(pSL, p1, b);
                AddNewLine(pSR, p1, b);
            }
        }
Ejemplo n.º 3
0
        private void DrawRoute(WWRoute route)
        {
            Brush[] brushes = new Brush[] {
                new SolidColorBrush(Colors.Cyan),
                new SolidColorBrush(Colors.Magenta)
            };

            for (int i = 0; i < route.Count(); ++i) {
                var lineSegment = route.GetNth(i);
                Point3D p0 = Point3D.Multiply(lineSegment.StartPos, mWorldProjectionMatrix);
                Point3D p1 = Point3D.Multiply(lineSegment.StartPos + lineSegment.Length * lineSegment.Direction, mWorldProjectionMatrix);

                Brush b = brushes[route.EarCh].Clone();
                b.Opacity = IntensityToOpacity(lineSegment.Intensity);
                AddNewLine(p0, p1, b);

                Point3D pSL = Point3D.Multiply(mRoom.SpeakerPos(0), mWorldProjectionMatrix);
                Point3D pSR = Point3D.Multiply(mRoom.SpeakerPos(1), mWorldProjectionMatrix);
                AddNewLine(pSL, p1, b);
                AddNewLine(pSR, p1, b);
            }
        }
Ejemplo n.º 4
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;
 }
Ejemplo n.º 5
0
        /// <summary>
        ///  スピーカーから耳に届く音がたどる経路を調べる。
        /// </summary>
        /// <param name="room"></param>
        /// <param name="earCh">耳 0:左耳, 1:右耳</param>
        public void Trace(WWRoom room, ReflectionType reflectionType, int earCh)
        {
            var route = new WWRoute(earCh);

            // 耳の位置
            var rayPos = room.ListenerEarPos(earCh);
            var earDir = room.ListenerEarDir(earCh);

            Vector3D rayDir = RayGen(earDir);
            //耳からrayが発射して、部屋の壁に当たる

            // 音が耳に向かう方向。
            Vector3D soundDir = -rayDir;
            var accumReflectionGain = new double[] {1.0, 1.0};

            for (int i = 0; i < MaxReflectionCount; ++i) {
                Point3D hitPos;
                Vector3D hitSurfaceNormal;
                double rayLength;
                if (!room.RayIntersection(rayPos, rayDir, out hitPos, out hitSurfaceNormal, out rayLength)) {
                    // 終わり。
                    break;
                }

                // 1.0 - 反射率の確率で、計算を打ち切る。
                // たとえば反射率0.8の壁にRayが10本入射すると、8本のRayが強度を100%保ったまま反射する。
                if (WallReflectionRatio < NextDouble()) {
                    break;
                }

                // スピーカーから耳への道のりを計算する。
                var lineSegment = new WWLineSegment(rayPos, rayDir, rayLength, 1.0f /* 仮 Intensity */ );

                {
                    int speakerCh = earCh;
                    var distance = CalcRouteDistance(room, speakerCh, route, lineSegment, hitPos);
                    double gain = CalcReflectionGain(reflectionType, room, speakerCh, hitPos, rayDir, hitSurfaceNormal);
                    accumReflectionGain[0] *= gain;
                    var coeffS = new WWFirCoefficient(distance / SoundSpeed, soundDir, accumReflectionGain[0] / distance, false);
                    lineSegment.Intensity = coeffS.Gain;

                    if (1.0 / distance < SMALL_GAIN_THRESHOLD) {
                        break;
                    }

                    if (SMALL_GAIN_THRESHOLD <= coeffS.Gain) {
                        StoreCoeff(earCh, earCh, coeffS);
                    }
                }

                {
                    int speakerCh = (earCh == 0) ? 1 : 0;
                    var distance = CalcRouteDistance(room, speakerCh, route, lineSegment, hitPos);
                    double gain = CalcReflectionGain(reflectionType, room, speakerCh, hitPos, rayDir, hitSurfaceNormal);
                    accumReflectionGain[1] *= gain;
                    var coeffD = new WWFirCoefficient(distance / SoundSpeed, soundDir, accumReflectionGain[1] / distance, false);

                    if (SMALL_GAIN_THRESHOLD <= coeffD.Gain) {
                        StoreCoeff(earCh, speakerCh, coeffD);
                    }
                }

                route.Add(lineSegment);
                rayPos = hitPos;

                // 反射後の出射方向rayDir
                switch (reflectionType) {
                case ReflectionType.Diffuse:
                    rayDir = RayGen(hitSurfaceNormal);
                    break;
                case ReflectionType.Specular:
                    rayDir = SpecularReflection(rayDir, hitSurfaceNormal);
                    break;
                default:
                    System.Diagnostics.Debug.Assert(false);
                    break;
                }
            }

            // routeの中に、1つもlineSegmentが入っていないことがある。
            mRouteList.Add(route);
            Interlocked.Increment(ref mRouteCount[earCh]);
        }
Ejemplo n.º 6
0
        /// <summary>
        ///  スピーカーから耳に届く音がたどる経路を調べる。
        /// </summary>
        /// <param name="room"></param>
        /// <param name="earCh">耳 0:左耳, 1:右耳</param>
        public void Trace(WWRoom room, ReflectionType reflectionType, int earCh)
        {
            var route = new WWRoute(earCh);

            // 耳の位置
            var rayPos = room.ListenerEarPos(earCh);
            var earDir = room.ListenerEarDir(earCh);

            Vector3D rayDir = RayGen(earDir);
            //耳からrayが発射して、部屋の壁に当たる

            // 音が耳に向かう方向。
            Vector3D soundDir            = -rayDir;
            var      accumReflectionGain = new double[] { 1.0, 1.0 };

            for (int i = 0; i < MaxReflectionCount; ++i)
            {
                Point3D  hitPos;
                Vector3D hitSurfaceNormal;
                double   rayLength;
                if (!room.RayIntersection(rayPos, rayDir, out hitPos, out hitSurfaceNormal, out rayLength))
                {
                    // 終わり。
                    break;
                }

                // 1.0 - 反射率の確率で、計算を打ち切る。
                // たとえば反射率0.8の壁にRayが10本入射すると、8本のRayが強度を100%保ったまま反射する。
                if (WallReflectionRatio < NextDouble())
                {
                    break;
                }

                // スピーカーから耳への道のりを計算する。
                var lineSegment = new WWLineSegment(rayPos, rayDir, rayLength, 1.0f /* 仮 Intensity */);

                {
                    int    speakerCh = earCh;
                    var    distance  = CalcRouteDistance(room, speakerCh, route, lineSegment, hitPos);
                    double gain      = CalcReflectionGain(reflectionType, room, speakerCh, hitPos, rayDir, hitSurfaceNormal);
                    accumReflectionGain[0] *= gain;
                    var coeffS = new WWFirCoefficient(distance / SoundSpeed, soundDir, accumReflectionGain[0] / distance, false);
                    lineSegment.Intensity = coeffS.Gain;

                    if (1.0 / distance < SMALL_GAIN_THRESHOLD)
                    {
                        break;
                    }

                    if (SMALL_GAIN_THRESHOLD <= coeffS.Gain)
                    {
                        StoreCoeff(earCh, earCh, coeffS);
                    }
                }

                {
                    int    speakerCh = (earCh == 0) ? 1 : 0;
                    var    distance  = CalcRouteDistance(room, speakerCh, route, lineSegment, hitPos);
                    double gain      = CalcReflectionGain(reflectionType, room, speakerCh, hitPos, rayDir, hitSurfaceNormal);
                    accumReflectionGain[1] *= gain;
                    var coeffD = new WWFirCoefficient(distance / SoundSpeed, soundDir, accumReflectionGain[1] / distance, false);

                    if (SMALL_GAIN_THRESHOLD <= coeffD.Gain)
                    {
                        StoreCoeff(earCh, speakerCh, coeffD);
                    }
                }

                route.Add(lineSegment);
                rayPos = hitPos;

                // 反射後の出射方向rayDir
                switch (reflectionType)
                {
                case ReflectionType.Diffuse:
                    rayDir = RayGen(hitSurfaceNormal);
                    break;

                case ReflectionType.Specular:
                    rayDir = SpecularReflection(rayDir, hitSurfaceNormal);
                    break;

                default:
                    System.Diagnostics.Debug.Assert(false);
                    break;
                }
            }

            // routeの中に、1つもlineSegmentが入っていないことがある。
            mRouteList.Add(route);
            Interlocked.Increment(ref mRouteCount[earCh]);
        }