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); } } }
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; } }
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; } }
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); } } }
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); } }
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); }
public void SetEndMeshMirror(MirrorMethod mirror) { if (extrudableMeshes.Count >= 2 && extrudableMeshes[1] != null) { extrudableMeshes[1].mirror = mirror; CheckMeshes(); Rebuild(sampleComputer: false); } }
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); } }
public void SetStartMeshMirror(MirrorMethod mirror) { if (extrudableMeshes.Count != 0 && extrudableMeshes[0] != null) { extrudableMeshes[0].mirror = mirror; CheckMeshes(); Rebuild(sampleComputer: false); } }
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); }
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); }
public void SetEndMeshMirror(MirrorMethod mirror) { if (extrudableMeshes.Count < 2) { return; } if (extrudableMeshes[1] == null) { return; } extrudableMeshes[1].mirror = mirror; CheckMeshes(); Rebuild(false); }
public void SetStartMeshMirror(MirrorMethod mirror) { if (extrudableMeshes.Count == 0) { return; } if (extrudableMeshes[0] == null) { return; } extrudableMeshes[0].mirror = mirror; CheckMeshes(); Rebuild(false); }
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); }
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); } } }
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); }
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); }
/// <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(); }
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); }
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(); }
public void GenerateMirroredRoomIndices_CheckIndexCount(int maxReflectionCount, int expectedIndexCount) { var actualIndexCount = MirrorMethod.GenerateMirroredRoomIndices(maxReflectionCount).Count(); Assert.AreEqual(expectedIndexCount, actualIndexCount); }
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(); }
/// <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(); }