private void StoreCoeff(int earCh, int speakerCh, WWFirCoefficient coeff)
        {
            int n = earCh + speakerCh * 2;

            switch (n)
            {
            case 0:
                mLeftSpeakerToLeftEar.Add(coeff);
                break;

            case 1:
                mLeftSpeakerToRightEar.Add(coeff);
                break;

            case 2:
                mRightSpeakerToLeftEar.Add(coeff);
                break;

            case 3:
                mRightSpeakerToRightEar.Add(coeff);
                break;

            default:
                System.Diagnostics.Debug.Assert(false);
                break;
            }
        }
Beispiel #2
0
        private void StoreCoeff(int earCh, int speakerCh, WWFirCoefficient coeff)
        {
            int n = earCh + speakerCh * 2;

            switch (n) {
            case 0:
                mLeftSpeakerToLeftEar.Add(coeff);
                break;
            case 1:
                mLeftSpeakerToRightEar.Add(coeff);
                break;
            case 2:
                mRightSpeakerToLeftEar.Add(coeff);
                break;
            case 3:
                mRightSpeakerToRightEar.Add(coeff);
                break;
            default:
                System.Diagnostics.Debug.Assert(false);
                break;
            }
        }
Beispiel #3
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]);
        }
        /// <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]);
        }