예제 #1
0
        public void GenerateImpulseResponse_CheckSignal()
        {
            var sampleRate       = 16000;
            var dftLength        = 1024;
            var delaySampleCount = 30;

            var time     = (double)delaySampleCount / sampleRate;
            var distance = AcousticConstants.SoundSpeed * time;

            var roomSize              = DenseVector.OfArray(new double[] { distance, distance, distance });
            var distanceAttenuation   = new DistanceAttenuation(distance => 0.9);
            var reflectionAttenuation = new ReflectionAttenuation(frequency => 0.7);
            var room        = new Room(roomSize, distanceAttenuation, reflectionAttenuation, 1);
            var soundSource = new SoundSource(distance / 2, distance / 2, distance / 2);
            var microphone  = new Microphone(distance / 2, distance / 2, distance / 2);

            var response = MirrorMethod.GenerateImpulseResponse(room, soundSource, microphone, sampleRate, dftLength);

            Assert.AreEqual(dftLength / 2, response.Length);

            for (var t = 0; t < response.Length; t++)
            {
                if (t == 0)
                {
                    Assert.AreEqual(0.9, response[t], 1.0E-6);
                }
                else if (t == delaySampleCount)
                {
                    Assert.AreEqual(6 * 0.9 * 0.7, response[t], 1.0E-6);
                }
            }
        }
예제 #2
0
        void UpdateStartExtrudeMesh()
        {
            MirrorMethod lastMirror = MirrorMethod.None;

            if (extrudableMeshes[0] != null)
            {
                lastMirror = extrudableMeshes[0].mirror;
            }
            if (_startMesh != null)
            {
                extrudableMeshes[0] = new ExtrudableMesh(_startMesh, _axis);
            }
            else if (_middleMeshes.Length > 0)
            {
                if (_iteration == Iteration.Ordered)
                {
                    extrudableMeshes[0] = new ExtrudableMesh(_middleMeshes[0], _axis);
                }
                else
                {
                    random = new System.Random(_randomSeed);
                    extrudableMeshes[0] = new ExtrudableMesh(_middleMeshes[random.Next(_middleMeshes.Length - 1)], _axis);
                }
            }
            if (extrudableMeshes[0] != null)
            {
                extrudableMeshes[0].mirror = lastMirror;
            }
        }
예제 #3
0
        void UpdateEndExtrudeMesh()
        {
            MirrorMethod lastMirror = MirrorMethod.None;

            lastMirror = MirrorMethod.None;
            if (extrudableMeshes[1] != null)
            {
                lastMirror = extrudableMeshes[1].mirror;
            }
            if (_endMesh != null)
            {
                extrudableMeshes[1] = new ExtrudableMesh(_endMesh, _axis);
            }
            else if (_middleMeshes.Length > 0)
            {
                if (_iteration == Iteration.Ordered)
                {
                    extrudableMeshes[1] = new ExtrudableMesh(_middleMeshes[_startMesh != null ? (iterations - 2) % _middleMeshes.Length : (iterations - 1) % _middleMeshes.Length], _axis);
                }
                else
                {
                    random = new System.Random(_randomSeed);
                    for (int i = 0; i < iterations - 1; i++)
                    {
                        random.Next(_middleMeshes.Length - 1);
                    }
                    extrudableMeshes[1] = new ExtrudableMesh(_middleMeshes[random.Next(_middleMeshes.Length - 1)], _axis);
                }
            }
            if (extrudableMeshes[1] != null)
            {
                extrudableMeshes[1].mirror = lastMirror;
            }
        }
예제 #4
0
        public void GenerateSoundRays_CheckRayProperties()
        {
            var roomSize              = DenseVector.OfArray(new double[] { 2.0, 2.0, 2.0 });
            var distanceAttenuation   = new DistanceAttenuation(distance => 0.9);
            var reflectionAttenuation = new ReflectionAttenuation(frequency => 0.7);
            var room        = new Room(roomSize, distanceAttenuation, reflectionAttenuation, 1);
            var soundSource = new SoundSource(1.0, 1.0, 1.0);
            var microphone  = new Microphone(1.0, 1.0, 1.0);
            var rays        = MirrorMethod.GenerateSoundRays(room, soundSource, microphone).ToArray();

            Assert.AreEqual(7, rays.Length);

            foreach (var ray in rays)
            {
                if (ray.Distance < 1.0E-6)
                {
                    Assert.AreEqual(0, ray.ReflectionCount);
                }
                else
                {
                    Assert.AreEqual(2.0, ray.Distance, 1.0E-6);
                    Assert.AreEqual(1, ray.ReflectionCount);
                }
            }
        }
예제 #5
0
 public void GenerateMirroredRoomIndices_CheckIndexSum(int maxReflectionCount)
 {
     foreach (var index in MirrorMethod.GenerateMirroredRoomIndices(maxReflectionCount))
     {
         var sum = Math.Abs(index.X) + Math.Abs(index.Y) + Math.Abs(index.Z);
         Assert.IsTrue(sum <= maxReflectionCount);
     }
 }
예제 #6
0
        public void GenerateMirroredRoomIndices_CheckIndexUniqueness(int maxReflectionCount)
        {
            var indices    = MirrorMethod.GenerateMirroredRoomIndices(maxReflectionCount);
            var ids        = indices.Select(index => index.ToString()).ToArray();
            var distincted = ids.Distinct().ToArray();

            Assert.AreEqual(ids.Length, distincted.Length);
        }
예제 #7
0
 public void SetEndMeshMirror(MirrorMethod mirror)
 {
     if (extrudableMeshes.Count >= 2 && extrudableMeshes[1] != null)
     {
         extrudableMeshes[1].mirror = mirror;
         CheckMeshes();
         Rebuild(sampleComputer: false);
     }
 }
예제 #8
0
 public void SetMeshMirror(int index, MirrorMethod mirror)
 {
     if (extrudableMeshes.Count >= 2 + index && extrudableMeshes[2 + index] != null)
     {
         extrudableMeshes[2 + index].mirror = mirror;
         CheckMeshes();
         Rebuild(sampleComputer: false);
     }
 }
예제 #9
0
 public void SetStartMeshMirror(MirrorMethod mirror)
 {
     if (extrudableMeshes.Count != 0 && extrudableMeshes[0] != null)
     {
         extrudableMeshes[0].mirror = mirror;
         CheckMeshes();
         Rebuild(sampleComputer: false);
     }
 }
예제 #10
0
 public void SetMesh(int index, Mesh inputMesh, MirrorMethod mirror = MirrorMethod.None)
 {
     if (inputMesh == null)
     {
         RemoveMesh(index);
         return;
     }
     _middleMeshes[index] = inputMesh;
     UpdateExtrudableMeshes();
     extrudableMeshes[2 + index].mirror = mirror;
     CheckMeshes();
     Rebuild(false);
 }
예제 #11
0
 public void SetMeshMirror(int index, MirrorMethod mirror)
 {
     if (extrudableMeshes.Count < 2 + index)
     {
         return;
     }
     if (extrudableMeshes[2 + index] == null)
     {
         return;
     }
     extrudableMeshes[2 + index].mirror = mirror;
     CheckMeshes();
     Rebuild(false);
 }
예제 #12
0
 public void SetEndMeshMirror(MirrorMethod mirror)
 {
     if (extrudableMeshes.Count < 2)
     {
         return;
     }
     if (extrudableMeshes[1] == null)
     {
         return;
     }
     extrudableMeshes[1].mirror = mirror;
     CheckMeshes();
     Rebuild(false);
 }
예제 #13
0
 public void SetStartMeshMirror(MirrorMethod mirror)
 {
     if (extrudableMeshes.Count == 0)
     {
         return;
     }
     if (extrudableMeshes[0] == null)
     {
         return;
     }
     extrudableMeshes[0].mirror = mirror;
     CheckMeshes();
     Rebuild(false);
 }
예제 #14
0
        public void GetMirroredPosition_Case3()
        {
            var roomSize              = DenseVector.OfArray(new double[] { 3.0, 4.0, 2.0 });
            var distanceAttenuation   = new DistanceAttenuation(distance => 0.9);
            var reflectionAttenuation = new ReflectionAttenuation(frequency => 0.7);
            var room       = new Room(roomSize, distanceAttenuation, reflectionAttenuation, 1);
            var microphone = new Microphone(0.5, 1.0, 1.5);
            var index      = new MirroredRoomIndex(5, -2, -3);
            var mirrored   = MirrorMethod.GetMirroredPosition(room, microphone, index);

            Assert.AreEqual(15.0 + 2.5, mirrored[0], 1.0E-9);
            Assert.AreEqual(-8.0 + 1.0, mirrored[1], 1.0E-9);
            Assert.AreEqual(-6.0 + 0.5, mirrored[2], 1.0E-9);
        }
예제 #15
0
        public void GenerateFrequencyDomainImpulseResponse_CheckDistanceAttenuation()
        {
            var sampleRate       = 16000;
            var dftLength        = 1024;
            var delaySampleCount = 30;

            var time     = (double)delaySampleCount / sampleRate;
            var distance = AcousticConstants.SoundSpeed * time;

            var roomSize              = DenseVector.OfArray(new double[] { distance, distance, distance });
            var distanceAttenuation   = new DistanceAttenuation(distance => distance < 0.1 ? 3.1 : 2.3);
            var reflectionAttenuation = new ReflectionAttenuation(frequency => 0.7);
            var room        = new Room(roomSize, distanceAttenuation, reflectionAttenuation, 1);
            var soundSource = new SoundSource(distance / 2, distance / 2, distance / 2);
            var microphone  = new Microphone(distance / 2, distance / 2, distance / 2);

            var response = MirrorMethod.GenerateFrequencyDomainImpulseResponse(room, soundSource, microphone, sampleRate, dftLength);

            var timeDomainSignal = new Complex[dftLength];

            timeDomainSignal[0] = response[0];
            for (var w = 1; w < dftLength / 2; w++)
            {
                timeDomainSignal[w]             = response[w];
                timeDomainSignal[dftLength - w] = response[w].Conjugate();
            }
            timeDomainSignal[dftLength / 2] = response[dftLength / 2];
            Fourier.Inverse(timeDomainSignal, FourierOptions.AsymmetricScaling);

            for (var t = 0; t < dftLength; t++)
            {
                if (t == 0)
                {
                    Assert.AreEqual(3.1, timeDomainSignal[t].Real, 1.0E-6);
                    Assert.AreEqual(0.0, timeDomainSignal[t].Imaginary, 1.0E-6);
                }
                else if (t == delaySampleCount)
                {
                    Assert.AreEqual(6 * 2.3 * 0.7, timeDomainSignal[t].Real, 1.0E-6);
                    Assert.AreEqual(0.0, timeDomainSignal[t].Imaginary, 1.0E-6);
                }
                else
                {
                    Assert.AreEqual(0.0, timeDomainSignal[t].Real, 1.0E-6);
                    Assert.AreEqual(0.0, timeDomainSignal[t].Imaginary, 1.0E-6);
                }
            }
        }
예제 #16
0
 public void SetEndMesh(Mesh inputMesh, MirrorMethod mirror = MirrorMethod.None)
 {
     _endMesh = inputMesh;
     if (extrudableMeshes.Count < 2)
     {
         extrudableMeshes.AddRange(new ExtrudableMesh[2 - extrudableMeshes.Count]);
     }
     if (_endMesh == null)
     {
         extrudableMeshes[1] = null;
         _hasEndMesh         = false;
         Rebuild(false);
         return;
     }
     extrudableMeshes[1]        = new ExtrudableMesh(_endMesh, _axis);
     extrudableMeshes[1].mirror = mirror;
     CheckMeshes();
     Rebuild(false);
 }
예제 #17
0
 public void SetStartMesh(Mesh inputMesh, MirrorMethod mirror = MirrorMethod.None)
 {
     _startMesh = inputMesh;
     if (extrudableMeshes.Count == 0)
     {
         extrudableMeshes.Add(null);
     }
     if (_startMesh == null)
     {
         extrudableMeshes[0] = null;
         _hasStartMesh       = false;
         Rebuild(false);
         return;
     }
     extrudableMeshes[0]        = new ExtrudableMesh(_startMesh, _axis);
     extrudableMeshes[0].mirror = mirror;
     CheckMeshes();
     Rebuild(false);
 }
예제 #18
0
        /// <summary>
        /// Creates the mesh array that will be referenced when extruding the meshes. Elements 0 and 1 are the start and end cap meshes
        /// </summary>
        void UpdateExtrudableMeshes()
        {
            iterations = 0;
            if (_startMesh != null)
            {
                iterations++;
            }
            if (_endMesh != null)
            {
                iterations++;
            }
            iterations += (extrudableMeshes.Count - 2) * _repeat;
            int targetCount = 2 + _middleMeshes.Length;

            if (extrudableMeshes.Count < targetCount)
            {
                extrudableMeshes.AddRange(new ExtrudableMesh[targetCount - extrudableMeshes.Count]);
            }

            for (int i = 0; i < _middleMeshes.Length; i++)
            {
                if (_middleMeshes[i] == null)
                {
                    RemoveMesh(i);
                    i--;
                    continue;
                }
                MirrorMethod lastMirror = MirrorMethod.None;
                if (extrudableMeshes[i + 2] != null)
                {
                    lastMirror = extrudableMeshes[i + 2].mirror;
                    extrudableMeshes[i + 2].Update(_middleMeshes[i], _axis);
                }
                else
                {
                    extrudableMeshes[i + 2] = new ExtrudableMesh(_middleMeshes[i], _axis);
                }
                extrudableMeshes[i + 2].mirror = lastMirror;
            }
            UpdateStartExtrudeMesh();
            UpdateEndExtrudeMesh();
        }
예제 #19
0
        public void GenerateFrequencyDomainImpulseResponse_CheckReflectionAttenuation()
        {
            var sampleRate       = 16000;
            var dftLength        = 1024;
            var delaySampleCount = 30;

            var time     = (double)delaySampleCount / sampleRate;
            var distance = AcousticConstants.SoundSpeed * time;

            var cutOff = 4000;

            var roomSize              = DenseVector.OfArray(new double[] { distance, distance, distance });
            var distanceAttenuation   = new DistanceAttenuation(distance => distance < 1.0E-3 ? 0.0 : 0.9);
            var reflectionAttenuation = new ReflectionAttenuation(frequency => frequency < cutOff ? 0.7 : 0.0);
            var room        = new Room(roomSize, distanceAttenuation, reflectionAttenuation, 1);
            var soundSource = new SoundSource(distance / 2, distance / 2, distance / 2);
            var microphone  = new Microphone(distance / 2, distance / 2, distance / 2);

            var response = MirrorMethod.GenerateFrequencyDomainImpulseResponse(room, soundSource, microphone, sampleRate, dftLength);

            var validCount = 0;

            for (var w = 0; w < response.Length; w++)
            {
                var frequency = (double)w / dftLength * sampleRate;
                if (Math.Abs(frequency - cutOff) > 1)
                {
                    if (frequency < cutOff)
                    {
                        Assert.IsTrue(response[w].Magnitude > 1.0E-3);
                    }
                    else
                    {
                        Assert.IsTrue(response[w].Magnitude < 1.0E-3);
                    }
                    validCount++;
                }
            }
            Assert.IsTrue(validCount >= response.Length - 3);
        }
예제 #20
0
            private void Mirror(MirrorMethod method)
            {
                if (method == MirrorMethod.None)
                {
                    return;
                }
                switch (method)
                {
                case MirrorMethod.X:
                    for (int i = 0; i < vertices.Length; i++)
                    {
                        float percent = Mathf.InverseLerp(bounds.min.x, bounds.max.x, vertices[i].x);
                        vertices[i].x = Mathf.Lerp(bounds.min.x, bounds.max.x, 1f - percent);
                        normals[i].x  = -normals[i].x;
                    }
                    if (_axis == Axis.X)
                    {
                        for (int i = 0; i < vertexGroups.Count; i++)
                        {
                            float percent = Mathf.InverseLerp(bounds.min.x, bounds.max.x, vertexGroups[i].value);
                            vertexGroups[i].value = Mathf.Lerp(bounds.min.x, bounds.max.x, 1f - percent);
                        }
                    }
                    break;

                case MirrorMethod.Y:
                    for (int i = 0; i < vertices.Length; i++)
                    {
                        float percent = Mathf.InverseLerp(bounds.min.y, bounds.max.y, vertices[i].y);
                        vertices[i].y = Mathf.Lerp(bounds.min.y, bounds.max.y, 1f - percent);
                        normals[i].y  = -normals[i].y;
                    }
                    if (_axis == Axis.Y)
                    {
                        for (int i = 0; i < vertexGroups.Count; i++)
                        {
                            float percent = Mathf.InverseLerp(bounds.min.y, bounds.max.y, vertexGroups[i].value);
                            vertexGroups[i].value = Mathf.Lerp(bounds.min.y, bounds.max.y, 1f - percent);
                        }
                    }
                    break;

                case MirrorMethod.Z:
                    for (int i = 0; i < vertices.Length; i++)
                    {
                        float percent = Mathf.InverseLerp(bounds.min.z, bounds.max.z, vertices[i].z);
                        vertices[i].z = Mathf.Lerp(bounds.min.z, bounds.max.z, 1f - percent);
                        normals[i].z  = -normals[i].z;
                    }
                    if (_axis == Axis.Z)
                    {
                        for (int i = 0; i < vertexGroups.Count; i++)
                        {
                            float percent = Mathf.InverseLerp(bounds.min.z, bounds.max.z, vertexGroups[i].value);
                            vertexGroups[i].value = Mathf.Lerp(bounds.min.z, bounds.max.z, 1f - percent);
                        }
                    }
                    break;
                }
                for (int i = 0; i < subMeshes.Count; i++)
                {
                    for (int n = 0; n < subMeshes[i].triangles.Length; n += 3)
                    {
                        int temp = subMeshes[i].triangles[n];
                        subMeshes[i].triangles[n]     = subMeshes[i].triangles[n + 2];
                        subMeshes[i].triangles[n + 2] = temp;
                    }
                }
                CalculateTangents();
            }
예제 #21
0
        public void GenerateMirroredRoomIndices_CheckIndexCount(int maxReflectionCount, int expectedIndexCount)
        {
            var actualIndexCount = MirrorMethod.GenerateMirroredRoomIndices(maxReflectionCount).Count();

            Assert.AreEqual(expectedIndexCount, actualIndexCount);
        }
예제 #22
0
            private void Mirror(MirrorMethod method)
            {
                switch (method)
                {
                case MirrorMethod.None:
                    return;

                case MirrorMethod.X:
                    for (int m = 0; m < vertices.Length; m++)
                    {
                        float num5 = Mathf.InverseLerp(bounds.min.x, bounds.max.x, vertices[m].x);
                        vertices[m].x = Mathf.Lerp(bounds.min.x, bounds.max.x, 1f - num5);
                        normals[m].x  = 0f - normals[m].x;
                    }
                    if (_axis == Axis.X)
                    {
                        for (int n = 0; n < vertexGroups.Count; n++)
                        {
                            float num6 = Mathf.InverseLerp(bounds.min.x, bounds.max.x, vertexGroups[n].value);
                            vertexGroups[n].value = Mathf.Lerp(bounds.min.x, bounds.max.x, 1f - num6);
                        }
                    }
                    break;

                case MirrorMethod.Y:
                    for (int k = 0; k < vertices.Length; k++)
                    {
                        float num3 = Mathf.InverseLerp(bounds.min.y, bounds.max.y, vertices[k].y);
                        vertices[k].y = Mathf.Lerp(bounds.min.y, bounds.max.y, 1f - num3);
                        normals[k].y  = 0f - normals[k].y;
                    }
                    if (_axis == Axis.Y)
                    {
                        for (int l = 0; l < vertexGroups.Count; l++)
                        {
                            float num4 = Mathf.InverseLerp(bounds.min.y, bounds.max.y, vertexGroups[l].value);
                            vertexGroups[l].value = Mathf.Lerp(bounds.min.y, bounds.max.y, 1f - num4);
                        }
                    }
                    break;

                case MirrorMethod.Z:
                    for (int i = 0; i < vertices.Length; i++)
                    {
                        float num = Mathf.InverseLerp(bounds.min.z, bounds.max.z, vertices[i].z);
                        vertices[i].z = Mathf.Lerp(bounds.min.z, bounds.max.z, 1f - num);
                        normals[i].z  = 0f - normals[i].z;
                    }
                    if (_axis == Axis.Z)
                    {
                        for (int j = 0; j < vertexGroups.Count; j++)
                        {
                            float num2 = Mathf.InverseLerp(bounds.min.z, bounds.max.z, vertexGroups[j].value);
                            vertexGroups[j].value = Mathf.Lerp(bounds.min.z, bounds.max.z, 1f - num2);
                        }
                    }
                    break;
                }
                for (int num7 = 0; num7 < subMeshes.Count; num7++)
                {
                    for (int num8 = 0; num8 < subMeshes[num7].triangles.Length; num8 += 3)
                    {
                        int num9 = subMeshes[num7].triangles[num8];
                        subMeshes[num7].triangles[num8]     = subMeshes[num7].triangles[num8 + 2];
                        subMeshes[num7].triangles[num8 + 2] = num9;
                    }
                }
                CalculateTangents();
            }
예제 #23
0
        /// <summary>
        /// Creates the mesh array that will be referenced when extruding the meshes. Elements 0 and 1 are the start and end cap meshes
        /// </summary>
        void UpdateExtrudableMeshes()
        {
            iterations = 0;
            if (_startMesh != null)
            {
                iterations++;
            }
            if (_endMesh != null)
            {
                iterations++;
            }
            iterations += (extrudableMeshes.Count - 2) * _repeat;
            int targetCount = 2 + _middleMeshes.Length;

            if (extrudableMeshes.Count < targetCount)
            {
                extrudableMeshes.AddRange(new ExtrudableMesh[targetCount - extrudableMeshes.Count]);
            }
            //If the deprecated sourceMesh is set, then migrate it to the new mesh array
            if (_sourceMesh != null)
            {
                Mesh[] newMeshes = new Mesh[_middleMeshes.Length + 1];
                _middleMeshes.CopyTo(newMeshes, 0);
                newMeshes[newMeshes.Length - 1] = _sourceMesh;
                _middleMeshes = newMeshes;
                extrudableMeshes.Add(new ExtrudableMesh(_sourceMesh, _axis));
                _sourceMesh = null;
#if UNITY_EDITOR
                if (!Application.isPlaying)
                {
#if UNITY_5_4_OR_NEWER
                    UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEngine.SceneManagement.SceneManager.GetActiveScene());
#else
                    UnityEditor.EditorUtility.SetDirty(gameObject);
#endif
                }
#endif
            }

            for (int i = 0; i < _middleMeshes.Length; i++)
            {
                if (_middleMeshes[i] == null)
                {
                    RemoveMesh(i);
                    i--;
                    continue;
                }
                MirrorMethod lastMirror = MirrorMethod.None;
                if (extrudableMeshes[i + 2] != null)
                {
                    lastMirror = extrudableMeshes[i + 2].mirror;
                    extrudableMeshes[i + 2].Update(_middleMeshes[i], _axis);
                }
                else
                {
                    extrudableMeshes[i + 2] = new ExtrudableMesh(_middleMeshes[i], _axis);
                }
                extrudableMeshes[i + 2].mirror = lastMirror;
            }
            UpdateStartExtrudeMesh();
            UpdateEndExtrudeMesh();
        }