/// <summary> /// Direct sound constructor. This prepares the simulation to run. /// </summary> /// <param name="Src_in">The sound source</param> /// <param name="Rec_in">The collection of receivers</param> /// <param name="Room_in">The acoustical scene to render</param> /// <param name="RayCount">The number of rays which will be used </param> public Direct_Sound(Source Src_in, Receiver_Bank Rec_in, Scene Room_in, int[] Octaves) { type = Src_in.Type(); Validity = new bool[Rec_in.Count];//[Rec_in.Count]; Io = new double[Rec_in.Count][][];//[Rec_in.Count][t,8]; Time_Pt = new double[Rec_in.Count];//[Rec_in.Count]; Dir_Rec_Pos = new float[Rec_in.Count][][][]; Dir_Rec_Neg = new float[Rec_in.Count][][][]; Room = Room_in; C_Sound = Room_in.Sound_speed(0); SampleFreq = Rec_in.SampleRate; Src = Src_in; this.CO_Time = Rec_in.CO_Time; Receiver = new List<Point>(); Rho_C = new double[Rec_in.Count]; for(int i = 0; i < Rec_in.Count; i++) { Rho_C[i] = Room.Rho_C(Rec_in.H_Origin(i)); Receiver.Add(Rec_in.H_Origin(i)); } SWL = new double[8] { Src_in.SWL(0), Src_in.SWL(1), Src_in.SWL(2), Src_in.SWL(3), Src_in.SWL(4), Src_in.SWL(5), Src_in.SWL(6), Src_in.SWL(7) }; Delay_ms = Src.Delay; Oct_choice = Octaves; }
public Specular_Path(Hare.Geometry.Point[] Path, int[] Seq_planes, int[] Seq_Polys, Scene Room, Source Src, double C_Sound, double[] Trans_Mod, ref double Direct_Time, int thread, int Rnd) { PathEnergy = new double[8]; ValidPath = Path; //Build an Identifier Sequence = Seq_planes; Hare.Geometry.Point Pt; for (int q = 1; q < ValidPath.Length; q++) { Pt = ValidPath[q] - ValidPath[q - 1]; Length += Math.Sqrt(Pt.x * Pt.x + Pt.y * Pt.y + Pt.z * Pt.z); } Time = Length / C_Sound + Src.Delay; Vector DIR = ValidPath[1] - ValidPath[0]; DIR.Normalize(); Random rnd = new Random(Rnd); float time = (float)(Length / C_Sound); double[] phase = Src.Phase(DIR, ref rnd); ///Energy based formulation double[] Power = Src.DirPower(thread, Rnd, DIR); Identify(Src.Source_ID(), Direct_Time); for (int oct = 0; oct < 8; oct++) { PathEnergy[oct] = (Power[oct] * Math.Pow(10,-.1 * Room.Attenuation(0)[oct] * Length) / (4 * Math.PI * Length * Length)); PathEnergy[oct] *= Trans_Mod[oct]; } foreach (int q in Seq_Polys) { if (!(Room.AbsorptionValue[q] is Basic_Material)) continue; double[] AbsorptionData = Room.AbsorptionValue[q].Coefficient_A_Broad(); double[] ScatteringData = Room.ScatteringValue[q].Coefficient(); for (int t = 0; t <= 7; t++) { PathEnergy[t] *= (1 - AbsorptionData[t]) * (1 - ScatteringData[t]); } } prms = new double[8]; for (int i = 0; i < 8; i++) prms[i] = Math.Sqrt(PathEnergy[i] * Room.Rho_C(Path[0])); //System.Numerics.Complex[] Pspec = Audio.Pach_SP.Mirror_Spectrum(Audio.Pach_SP.Magnitude_Spectrum(prms, 44100, 4096, thread)); //System.Numerics.Complex[] Pspec = Audio.Pach_SP.Mirror_Spectrum(Audio.Pach_SP.Magnitude_Spectrum(prms, 88200, 4096, thread)); Special_Filter = new System.Numerics.Complex[4096]; for (int i = 0; i < Special_Filter.Length; i++) Special_Filter[i] = 1; foreach (int q in Seq_Polys) { if (Room.AbsorptionValue[q] is Basic_Material) continue; //Pressure based formulation of materials for (int i = 0; i < Seq_Polys.Length; i++) { Hare.Geometry.Vector d = Path[i + 1] - Path[i + 2]; d.Normalize(); if (!(Room.AbsorptionValue[Seq_Polys[i]] is Basic_Material)) { System.Numerics.Complex[] Ref = Room.AbsorptionValue[Seq_Polys[i]].Reflection_Spectrum(44100, 4096, Room.Normal(Seq_Polys[i]), d, thread); //System.Numerics.Complex[] Ref = Room.AbsorptionValue[Seq_Polys[i]].Reflection_Spectrum(88200, 4096, Room.Normal(Seq_Polys[i]), d, thread); //for (int j = 0; j < Pspec.Length; j++) Pspec[j] *= Ref[j]; for (int j = 0; j < Special_Filter.Length; j++) Special_Filter[j] *= Ref[j]; } } } Create_pressure(44100, 4096, thread); //double[] tank = new double[Pspec.Length]; //for (int i = 0; i < tank.Length; i++) tank[i] = Pspec[i].Real; //P = Audio.Pach_SP.Minimum_Phase_Response(tank, 44100, thread); //TODO: Investigate phase propoerties of this for special materials filters... //double[] pre = Audio.Pach_SP.IFFT_Real4096(Pspec, thread); //P = new double[pre.Length]; //double scale = Math.Sqrt(P.Length); //int hw = P.Length / 2; //for (int i = 0; i < pre.Length; i++) P[i] = pre[(i + hw) % pre.Length] / scale; ///////////////////////////////// //Audio.Pach_SP.resample(ref P); /////////////////////////////// //Audio.Pach_SP.Raised_Cosine_Window(ref P); }