public Basic_Material(double[] ABS, double[] Phase_Delay)
            {
                Abs = ABS;
                PD  = Phase_Delay;
                for (int i = 0; i < ABS.Length; i++)
                {
                    Ref[i] = 1 - ABS[i];
                }

                //Interpolate a transfer function... this will probably be clumsy at first...
                double rt2 = Math.Sqrt(2);

                List <double> f = new List <double>();

                f.Add(0);
                f.Add(31.25 * rt2);
                for (int oct = 0; oct < 9; oct++)
                {
                    f.Add(62.5 * Math.Pow(2, oct));
                    f.Add(rt2 * 62.5 * Math.Pow(2, oct));
                }
                f.Add(24000);

                List <double> pr = new List <double>();

                pr.Add(0);
                pr.Add(Math.Sqrt(1 - Abs[0]));

                for (int oct = 0; oct < 7; oct++)
                {
                    pr.Add(Math.Sqrt(1 - Abs[oct]));
                    pr.Add(Math.Sqrt((2 - Abs[oct] - Abs[oct + 1]) / 2));
                }
                if (pr.Count < f.Count)
                {
                    pr.Add(Math.Sqrt(1 - Abs[7]));                    //8k
                }
                if (pr.Count < f.Count)
                {
                    pr.Add(Math.Sqrt((1 - Abs[7] + (1 - Abs[7])) / 2));                    //10k
                }
                if (pr.Count < f.Count)
                {
                    pr.Add(Math.Sqrt(1 - Abs[7]));                    //12k
                }
                if (pr.Count < f.Count)
                {
                    pr.Add(Math.Sqrt(1 - Abs[7]));                    //16k
                }
                while (pr.Count < f.Count)
                {
                    pr.Add(1 - Abs[7]);
                }

                Transfer_Function = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkimaSorted(f.ToArray(), pr.ToArray());
            }
예제 #2
0
            public void ISO9613_1_Spline(double Tk, double Pa, double Hr)
            {
                double[] freq = new double[1024];
                double   df   = 22050 / 1024;

                for (int i = 1; i < 1025; i++)
                {
                    freq[i - 1] = df * i;
                }

                Spectrum = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(freq, ISO9613_1_attencoef(freq, Tk, Pa, Hr));
            }
            public void Populate_EigenFrequencies(double[] mag, double[] freq, string functiontype)
            {
                MathNet.Numerics.Interpolation.CubicSpline CS = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(freq, mag);

                for (double f = freq[0]; f < freq[freq.Length / 10]; f += 10)
                {
                    double f_ = f + 10;
                    double v  = CS.Differentiate(f);
                    double vf = CS.Differentiate(f_);

                    if (v > 0 && vf < 0)
                    {
                        //Look closer - find the exact frequency.
                        for (double f1 = f; f1 < f_; f1 += 1)
                        {
                            double v1  = CS.Differentiate(f1);
                            double v1f = CS.Differentiate(f1 + 1);
                            if (v1 > 0 && v1f < 0)
                            {
                                double eigen = v1 < -v1f?Math.Ceiling(f1) : Math.Floor(f1 + 1);

                                string s = "";
                                if (eigen < 100)
                                {
                                    s = "00";
                                }
                                else if (eigen < 1000)
                                {
                                    s = "0";
                                }
                                s = s + string.Format("{0} hz. {1}", eigen, functiontype);
                                EigenFrequencies.Items.Add(s);
                            }
                        }
                    }
                }
            }
            public static void Initialize_filter_functions()
            {
                int n = 100;
                double[] A = new double[n];
                double[] ph = new double[n];

                for (int i = 0; i < 100; i++)
                {
                    ph[i] = Math.PI / 2 * i;
                    A[i] = 0.25 * (ph[i] - Math.Cos(ph[i])) / (Math.PI * 2);
                }

                RCos_Integral = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(A, ph);
            }
            public Basic_Material(double[] ABS, double[] Phase_Delay)
            {
                Abs = ABS;
                PD = Phase_Delay;
                for (int i = 0; i < ABS.Length; i++) Ref[i] = 1 - ABS[i];

                //Interpolate a transfer function... this will probably be clumsy at first...
                double rt2 = Math.Sqrt(2);

                List<double> f = new List<double>();
                f.Add(0);
                f.Add(31.25 * rt2);
                for (int oct = 0; oct < 9; oct++)
                {
                    f.Add(62.5 * Math.Pow(2, oct));
                    f.Add(rt2 * 62.5 * Math.Pow(2, oct));
                }
                f.Add(24000);

                List<double> pr = new List<double>();
                pr.Add(0);
                pr.Add(Math.Sqrt(1 - Abs[0]));

                for (int oct = 0; oct < 7; oct++)
                {
                    pr.Add(Math.Sqrt(1 - Abs[oct]));
                    pr.Add(Math.Sqrt((2 - Abs[oct] - Abs[oct + 1]) / 2));
                }
                if (pr.Count < f.Count) pr.Add(Math.Sqrt(1 - Abs[7]));//8k
                if (pr.Count < f.Count) pr.Add(Math.Sqrt((1 - Abs[7] + (1 - Abs[7])) / 2));//10k
                if (pr.Count < f.Count) pr.Add(Math.Sqrt(1 - Abs[7]));//12k
                if (pr.Count < f.Count) pr.Add(Math.Sqrt(1 - Abs[7]));//16k
                while (pr.Count < f.Count) pr.Add(1 - Abs[7]);

                Transfer_Function = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkimaSorted(f.ToArray(), pr.ToArray());
            }
            public Finite_Material(Smart_Material Mat, Rhino.Geometry.Brep Br, Rhino.Geometry.Mesh M, int face_id, Medium_Properties med)
            {
                //Strictly for the flat X,Y case - oversimplified for now.
                Inf_Mat = Mat;
                Azimuth = new double[36];
                Altitude = new double[Mat.Angles.Length/2];
                alpha = new double[Altitude.Length][][];
                for(int i = 0; i < Altitude.Length; i++) Altitude[i] = Mat.Angles[i].Magnitude;
                for(int i = 0; i < Azimuth.Length; i++) Azimuth[i] = i * 360f / Azimuth.Length;

                    //Set up a frequency interpolated Zr for each direction individually.
                    Rhino.Geometry.Point3d pt = M.Faces.GetFaceCenter(face_id);

                    double[][][] ZrR = new double[Altitude.Length][][], ZrI = new double[Altitude.Length][][];
                    double[] fr = new double[9];
                    for (int k = 0; k < Altitude.Length; k++)
                    {
                        ZrR[k] = new double[Azimuth.Length][];
                        ZrI[k] = new double[Azimuth.Length][];
                        alpha[k] = new double[Azimuth.Length][];
                        for (int j = 0; j < Azimuth.Length; j++)
                        {
                            ZrR[k][j] = new double[9];
                            ZrI[k][j] = new double[9];
                            alpha[k][j] = new double[8];
                        }
                    }

                    for (int oct = 0; oct < 9; oct++)
                    {
                        fr[oct] = 62.5 * Math.Pow(2, oct) / Utilities.Numerics.rt2;
                        System.Numerics.Complex[][] Zr = AbsorptionModels.Operations.Finite_Radiation_Impedance_Rect_Longhand(pt.X, pt.Y, Br, fr[oct], Altitude, Azimuth, med.Sound_Speed(pt));

                        for (int k = 0; k < Zr.Length; k++)
                        {
                            for (int j = 0; j < Zr[k].Length; j++)
                            {
                                ZrR[k][j][oct] = Zr[k][j].Real;
                                ZrI[k][j][oct] = Zr[k][j].Imaginary;
                            }
                        }
                    }

                    MathNet.Numerics.Interpolation.CubicSpline[][] Zr_r = new MathNet.Numerics.Interpolation.CubicSpline[Altitude.Length][];
                    MathNet.Numerics.Interpolation.CubicSpline[][] Zr_i = new MathNet.Numerics.Interpolation.CubicSpline[Altitude.Length][];

                    for (int k = 0; k < Zr_r.Length; k++)
                    {
                        Zr_r[k] = new MathNet.Numerics.Interpolation.CubicSpline[Azimuth.Length];
                        Zr_i[k] = new MathNet.Numerics.Interpolation.CubicSpline[Azimuth.Length];
                        for (int j = 0; j < Zr_r[k].Length; j++)
                        {
                            //Interpolate over curve real and imaginary Zr here...
                            Zr_r[k][j] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(fr, ZrR[k][j]);
                            Zr_i[k][j] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(fr, ZrI[k][j]);
                        }
                    }

                    for (int k = 0; k < Zr_r.Length; k++)
                    {
                        for (int j = 0; j < Zr_r[k].Length; j++)
                        {
                            List<double> freq = new List<double>();
                            List<double> alpha_interp = new List<double>();
                            for (int l = 0; l < Mat.frequency.Length; l++)
                            {
                                if (Mat.frequency[l] > 10000) break;
                                freq.Add(Mat.frequency[l]);
                                alpha_interp.Add(AbsorptionModels.Operations.Finite_Unit_Absorption_Coefficient(Mat.Z[k][j], new System.Numerics.Complex(Zr_r[k][j].Interpolate(Mat.frequency[l]), Zr_i[k][j].Interpolate(Mat.frequency[l])), med.Rho(Utilities.PachTools.RPttoHPt(pt)), med.Sound_Speed(pt)));
                            }
                            MathNet.Numerics.Interpolation.CubicSpline a = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(freq, alpha_interp);
                            for (int oct = 0; oct < 8; oct++)
                            {
                                alpha[k][j][oct] = 1 - a.Integrate(fr[oct], fr[oct + 1]) / (fr[oct + 1] - fr[oct]);
                            }
                        }
                    }
            }
예제 #7
0
        private void Record_Line_Segment(ref List<double> t, ref List<double[]> I, ref List<Vector> d, int rec_id)
        {
            if (t.Count > 4)
            {
                double[] t_dump = new double[t.Count];
                double[][] I_dump = new double[8][];
                double[][] xp_dump = new double[8][];
                double[][] xn_dump = new double[8][];
                double[][] yp_dump = new double[8][];
                double[][] yn_dump = new double[8][];
                double[][] zp_dump = new double[8][];
                double[][] zn_dump = new double[8][];

                double dt = 1d / (double)SampleFreq;

                double tmin = double.PositiveInfinity;
                double tmax = double.NegativeInfinity;
                for (int oct = 0; oct < 8; oct++)
                {
                    I_dump[oct] = new double[t.Count];
                    xp_dump[oct] = new double[t.Count];
                    xn_dump[oct] = new double[t.Count];
                    yp_dump[oct] = new double[t.Count];
                    yn_dump[oct] = new double[t.Count];
                    zp_dump[oct] = new double[t.Count];
                    zn_dump[oct] = new double[t.Count];
                }

                for (int i = 0; i < t.Count; i++)
                {
                    Vector v = d[i];
                    t_dump[i] = t[i];
                    tmin = Math.Min(t[i], tmin);
                    tmax = Math.Max(t[i], tmax);
                    double log10Eps = Math.Log10(1E-12);

                    for (int oct = 0; oct < 8; oct++)
                    {
                        I_dump[oct][i] = Math.Log10(I[i][oct]);
                        if (v.x > 0)
                        {
                            xp_dump[oct][i] = Math.Log10(Math.Abs(I[i][oct] * v.x));
                            xn_dump[oct][i] = log10Eps;
                        }
                        else
                        {
                            xn_dump[oct][i] = Math.Log10(Math.Abs(I[i][oct] * v.x));
                            xp_dump[oct][i] = log10Eps;
                        }
                        if (v.y > 0)
                        {
                            yp_dump[oct][i] = Math.Log10(Math.Abs(I[i][oct] * v.y));
                            yn_dump[oct][i] = log10Eps;
                        }
                        else
                        {
                            yn_dump[oct][i] = Math.Log10(Math.Abs(I[i][oct] * v.y));
                            yp_dump[oct][i] = log10Eps;
                        }
                        if (v.z > 0)
                        {
                            zp_dump[oct][i] = Math.Log10(Math.Abs(I[i][oct] * v.z));
                            zn_dump[oct][i] = log10Eps;
                        }
                        else
                        {
                            zn_dump[oct][i] = Math.Log10(Math.Abs(I[i][oct] * v.z));
                            zp_dump[oct][i] = log10Eps;
                        }
                    }
                }

                MathNet.Numerics.Interpolation.CubicSpline[] I_Spline = new MathNet.Numerics.Interpolation.CubicSpline[8];
                MathNet.Numerics.Interpolation.CubicSpline[] xp_Spline = new MathNet.Numerics.Interpolation.CubicSpline[8];
                MathNet.Numerics.Interpolation.CubicSpline[] xn_Spline = new MathNet.Numerics.Interpolation.CubicSpline[8];
                MathNet.Numerics.Interpolation.CubicSpline[] yp_Spline = new MathNet.Numerics.Interpolation.CubicSpline[8];
                MathNet.Numerics.Interpolation.CubicSpline[] yn_Spline = new MathNet.Numerics.Interpolation.CubicSpline[8];
                MathNet.Numerics.Interpolation.CubicSpline[] zp_Spline = new MathNet.Numerics.Interpolation.CubicSpline[8];
                MathNet.Numerics.Interpolation.CubicSpline[] zn_Spline = new MathNet.Numerics.Interpolation.CubicSpline[8];

                for (int oct = 0; oct < 8; oct++)
                {
                    I_Spline[oct] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(t_dump, I_dump[oct]);
                    xp_Spline[oct] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(t_dump, xp_dump[oct]);
                    xn_Spline[oct] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(t_dump, xn_dump[oct]);
                    yp_Spline[oct] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(t_dump, yp_dump[oct]);
                    yn_Spline[oct] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(t_dump, yn_dump[oct]);
                    zp_Spline[oct] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(t_dump, zp_dump[oct]);
                    zn_Spline[oct] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkimaSorted(t_dump, zn_dump[oct]);
                }
                int taumin = (int)Math.Ceiling(tmin / dt);
                int taumax = (int)Math.Floor(tmax / dt);

                if (Io[rec_id][0].Length < taumax)
                {
                    int tau_present = Io[rec_id][0].Length;
                    //resize the intensity histograms...
                    for (int oct = 0; oct < 8; oct++)
                    {
                        Array.Resize(ref Io[rec_id][oct], taumax);
                        for (int j = tau_present; j < Io[rec_id][oct].Length; j++)
                        {
                            Dir_Rec_Pos[rec_id][oct][j] = new float[3];
                            Dir_Rec_Neg[rec_id][oct][j] = new float[3];
                        }
                    }
                    Array.Resize(ref Io[rec_id][8], taumax);
                }

                //Adjust for energy differential between what might be two different sample rates...
                double mod = (double)(taumax - taumin) / t.Count;

                for (int tau = taumin; tau < taumax; tau++)
                {
                    for (int oct = 0; oct < 8; oct++)
                    {
                        double tdbl = (double)tau * dt;
                        double spl = I_Spline[oct].Interpolate(tdbl);
                        Io[rec_id][oct][tau] += Math.Pow(10, spl);// * mod;

                        if (Io[rec_id][oct][tau] < 0 || double.IsInfinity(Io[rec_id][oct][tau]) || double.IsNaN(Io[rec_id][oct][tau]))
                        {
                            Rhino.RhinoApp.Write("MEEP");
                        }

                        this.Dir_Rec_Pos[rec_id][oct][tau][0] += (float)(Math.Pow(10, xp_Spline[oct].Interpolate(tdbl)) * mod);
                        this.Dir_Rec_Neg[rec_id][oct][tau][0] += (float)(Math.Pow(10, xn_Spline[oct].Interpolate(tdbl)) * mod);
                        this.Dir_Rec_Pos[rec_id][oct][tau][1] += (float)(Math.Pow(10, yp_Spline[oct].Interpolate(tdbl)) * mod);
                        this.Dir_Rec_Neg[rec_id][oct][tau][1] += (float)(Math.Pow(10, yn_Spline[oct].Interpolate(tdbl)) * mod);
                        this.Dir_Rec_Pos[rec_id][oct][tau][2] += (float)(Math.Pow(10, zp_Spline[oct].Interpolate(tdbl)) * mod);
                        this.Dir_Rec_Neg[rec_id][oct][tau][2] += (float)(Math.Pow(10, zn_Spline[oct].Interpolate(tdbl)) * mod);
                    }
                }
            }
            else
            {
                Rhino.RhinoApp.Write("MEEP");
            }

            t = new List<double>();
            I = new List<double[]>();
            d = new List<Vector>();
        }
            public Finite_Material(Smart_Material Mat, Rhino.Geometry.Brep Br, Rhino.Geometry.Mesh M, int face_id, Medium_Properties med)
            {
                //Strictly for the flat X,Y case - oversimplified for now.
                Inf_Mat  = Mat;
                Azimuth  = new double[36];
                Altitude = new double[Mat.Angles.Length / 2];
                alpha    = new double[Altitude.Length][][];
                for (int i = 0; i < Altitude.Length; i++)
                {
                    Altitude[i] = Mat.Angles[i].Magnitude;
                }
                for (int i = 0; i < Azimuth.Length; i++)
                {
                    Azimuth[i] = i * 360f / Azimuth.Length;
                }

                //Set up a frequency interpolated Zr for each direction individually.
                Rhino.Geometry.Point3d pt = M.Faces.GetFaceCenter(face_id);

                double[][][] ZrR = new double[Altitude.Length][][], ZrI = new double[Altitude.Length][][];
                double[]     fr  = new double[9];
                for (int k = 0; k < Altitude.Length; k++)
                {
                    ZrR[k]   = new double[Azimuth.Length][];
                    ZrI[k]   = new double[Azimuth.Length][];
                    alpha[k] = new double[Azimuth.Length][];
                    for (int j = 0; j < Azimuth.Length; j++)
                    {
                        ZrR[k][j]   = new double[9];
                        ZrI[k][j]   = new double[9];
                        alpha[k][j] = new double[8];
                    }
                }

                for (int oct = 0; oct < 9; oct++)
                {
                    fr[oct] = 62.5 * Math.Pow(2, oct) / Utilities.Numerics.rt2;
                    System.Numerics.Complex[][] Zr = AbsorptionModels.Operations.Finite_Radiation_Impedance_Rect_Longhand(pt.X, pt.Y, Br, fr[oct], Altitude, Azimuth, med.Sound_Speed(pt));

                    for (int k = 0; k < Zr.Length; k++)
                    {
                        for (int j = 0; j < Zr[k].Length; j++)
                        {
                            ZrR[k][j][oct] = Zr[k][j].Real;
                            ZrI[k][j][oct] = Zr[k][j].Imaginary;
                        }
                    }
                }

                MathNet.Numerics.Interpolation.CubicSpline[][] Zr_r = new MathNet.Numerics.Interpolation.CubicSpline[Altitude.Length][];
                MathNet.Numerics.Interpolation.CubicSpline[][] Zr_i = new MathNet.Numerics.Interpolation.CubicSpline[Altitude.Length][];

                for (int k = 0; k < Zr_r.Length; k++)
                {
                    Zr_r[k] = new MathNet.Numerics.Interpolation.CubicSpline[Azimuth.Length];
                    Zr_i[k] = new MathNet.Numerics.Interpolation.CubicSpline[Azimuth.Length];
                    for (int j = 0; j < Zr_r[k].Length; j++)
                    {
                        //Interpolate over curve real and imaginary Zr here...
                        Zr_r[k][j] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(fr, ZrR[k][j]);
                        Zr_i[k][j] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(fr, ZrI[k][j]);
                    }
                }

                for (int k = 0; k < Zr_r.Length; k++)
                {
                    for (int j = 0; j < Zr_r[k].Length; j++)
                    {
                        List <double> freq         = new List <double>();
                        List <double> alpha_interp = new List <double>();
                        for (int l = 0; l < Mat.frequency.Length; l++)
                        {
                            if (Mat.frequency[l] > 10000)
                            {
                                break;
                            }
                            freq.Add(Mat.frequency[l]);
                            alpha_interp.Add(AbsorptionModels.Operations.Finite_Unit_Absorption_Coefficient(Mat.Z[k][j], new System.Numerics.Complex(Zr_r[k][j].Interpolate(Mat.frequency[l]), Zr_i[k][j].Interpolate(Mat.frequency[l])), med.Rho(Utilities.PachTools.RPttoHPt(pt)), med.Sound_Speed(pt)));
                        }
                        MathNet.Numerics.Interpolation.CubicSpline a = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(freq, alpha_interp);
                        for (int oct = 0; oct < 8; oct++)
                        {
                            alpha[k][j][oct] = 1 - a.Integrate(fr[oct], fr[oct + 1]) / (fr[oct + 1] - fr[oct]);
                        }
                    }
                }
            }
        /// <summary>
        /// This function calculates the actual path of the specular reflection.
        /// </summary>
        /// <param name="Images">The list of images.</param>
        /// <param name="Sequence">The list of surface indices for reflection.</param>
        /// <param name="Threadid">The id of the calling thread.</param>
        private void ProcessImages(Hare.Geometry.Point[][] Images, int[] Sequence, int Threadid)
        {
            for (int rec_id = 0; rec_id < Rec.Length; rec_id++)
            {
                double c_sound =  Room.Sound_speed(Rec[rec_id]);

                double[][] Trans_Mod = new double[Images.Length][];
                int[] Seq_Polys = new int[Sequence.Length];
                List<Hare.Geometry.Point[]> PathVertices = new List<Hare.Geometry.Point[]>();
                Hare.Geometry.Point S = Src.H_Origin();
                Hare.Geometry.Point E = Rec[rec_id];
                double df = SampleRate * .5 / 4096;

                //Find all Path Legs from Receiver to Source
                
                for (int r = 0; r < Images.Length; r++)
                {
                    Trans_Mod[r] = new double[8];
                    for (int t_oct = 0; t_oct < 8; t_oct++) Trans_Mod[r][t_oct] = 1;
                
                    Hare.Geometry.Point[] path = new Hare.Geometry.Point[Sequence.Length + 2];
                    path[0] = S;
                    path[path.Length - 1] = E;

                    for (int q = Sequence.Length - 1; q >= 0; q--)
                    {
                        if (Sequence[q] > Room.PlaneCount - 1)
                        {
                            //It's an edge!
                            int EdgeID = Sequence[q] - Room.PlaneCount;
                            //for (int i = 1; i < Room.Edge_Nodes[EdgeID].EdgeSources.Count; i++)
                            if (!OcclusionIntersectED(path[q + 2], Images[r][q], Sequence[q], ref Trans_Mod[r], ref path[q + 1], Threadid))// ref Trans_Mod, , ref Seq_Polys[q], 
                            {
                                path = null;
                                break;
                            }
                        }
                        else
                        {
                            if (!OcclusionIntersect(path[q + 2], Images[r][q], Sequence[q], ref Trans_Mod[r], ref path[q + 1], ref Seq_Polys[q], Threadid))
                            {
                                path = null;
                                break;
                            }
                        }
                    }
                    PathVertices.Add(path);
                }

                //Check that any path was unoccluded... if so, then record this entry. If not, move on...
                if (PathVertices.Count(item => item != null) == 0) continue; //goto Next;
                
                //Final Occlusion Check:
                for (int r = 0; r < PathVertices.Count; r++)
                {
                    if (PathVertices[r] == null) continue;
                    if (Sequence[0] < Room.PlaneCount)
                    {
                        if (FinalOcclusion(PathVertices[r][0], PathVertices[r][1], Sequence[0], ref Trans_Mod[r], Threadid))
                            PathVertices[r] = null;
                    }
                    else
                    {
                        int edge_id = Sequence[0] - Room.PlaneCount;
                        if (FinalOcclusion(PathVertices[r][0], PathVertices[r][1], 0.00001, Room.Edge_Nodes[edge_id].ParentBreps[0], Room.Edge_Nodes[edge_id].ParentBreps[1], ref Trans_Mod[r], Threadid))
                            PathVertices[r] = null;
                    }
                }

                //Check again for null(occluded) paths...
                if (PathVertices.Count(item => item != null) == 0) continue; //goto Next;

                ///Process all paths for pulse entry...
                if (PathVertices.Count == 0) continue;//goto Next;

                if (PathVertices.Count == 1)
                {
                    ThreadPaths[rec_id, Threadid].Add(new Specular_Path(PathVertices[0], Sequence, Seq_Polys, Room, Src, Speed_of_Sound, Trans_Mod[0], ref Direct_Time[rec_id], Threadid, Rnd[Threadid].Next()));
                    continue;
                }

                //Process Compound Path before storing it.
                double[] H = new double[0];
                Environment.Material[] M = new Environment.Material[Sequence.Length];
                for (int i = 0; i < M.Length; i++) M[i] = (Sequence[i] < Room.PlaneCount) ? Room.Surface_Material(Sequence[i]) : null;

                //Arrange all information to build filtered response...
                List<List<double>> Times = new List<List<double>>();
                List<List<double>> Pr = new List<List<double>>();
                List<double> Time = new List<double>();
                List<double> Bs = new List<double>();
                List<double> X = new List<double>();
                List<double> Y = new List<double>();
                List<double> Z = new List<double>();
                List<List<double>> Xe = new List<List<double>>();
                List<List<double>> Ye = new List<List<double>>();
                List<List<double>> Ze = new List<List<double>>();
                List<double> X_ = new List<double>();
                List<double> Y_ = new List<double>();
                List<double> Z_ = new List<double>();
                List<List<double>> Xs = new List<List<double>>();
                List<List<double>> Ys = new List<List<double>>();
                List<List<double>> Zs = new List<List<double>>();

                double deltaS = 0;
                double dt = 1.0f / SampleRate;
                List<double[]> t_limits = new List<double[]>();
                    
                    for (int i = 0; i < PathVertices.Count; i++)
                    {
                        if (PathVertices[i] == null)
                        {
                            if (Bs.Count > 0)
                            {
                                t_limits.Add(new double[2] { Time.Min(), Time.Max() });
                                Pr.Add(Bs);
                                Bs = new List<double>();
                                Times.Add(Time);
                                Time = new List<double>();
                                Xe.Add(X);
                                X = new List<double>();
                                Ye.Add(Y);
                                Y = new List<double>();
                                Ze.Add(Z);
                                Z = new List<double>();
                                Xs.Add(X_);
                                X_ = new List<double>();
                                Ys.Add(Y_);
                                Y_ = new List<double>();
                                Zs.Add(Z_);
                                Z_ = new List<double>();
                            }
                            continue;
                        }
                        double l = 0;
                        double[] dm = null, dl = null;
                        double length1 = 0, length2 = 0;
                        double Pres = 1;
                        int s, c, e;
                        for (s = 0, c = 1, e = 2; e < PathVertices[i].Length; s++, c++, e++)
                        {
                            if (Sequence[s] < Room.PlaneCount)
                            {
                                length1 += (PathVertices[i][1] - PathVertices[i][c]).Length();
                                length2 = length1;
                                dl = new double[2] { (PathVertices[i][c] - PathVertices[i][e]).Length(), (PathVertices[i][c] - PathVertices[i][e]).Length() };
                            }
                            else if (Sequence[s] >= Room.PlaneCount)
                            {
                                double m = 0;
                                double B = Room.Edge_Nodes[Sequence[s] - Room.PlaneCount].EdgeSources[i].Flex_Solve(PathVertices[i][s], PathVertices[i][e], ref m, ref l, ref dm, ref dl);
                                Pres *= B;
                                length1 += dm[0];
                                length2 += dm[1];
                            }
                            else { throw new NotImplementedException("...well isn't that novel..."); }
                        }
                        length1 += dl[0];
                        length2 += dl[1];

                        double duration_s = SampleRate * Math.Abs(length2 - length1) / c_sound;

                        Vector DIR;
                        DIR = PathVertices[i][c-1] - PathVertices[i][e-1];
                        DIR.Normalize();
                        Pres /= duration_s;
                        double Tn = 0.5 * (length1 + length2) / c_sound;
                        if (Time.Count > 2)
                        {
                            double dtnew = Time[Time.Count - 2] - Tn;
                            if (deltaS != 0 && (dtnew > 0) != (deltaS > 0))
                            {
                                //Break it...
                                t_limits.Add(new double[2] { Time.Min(), Time.Max() });
                                if (Bs.Last() < Pres) { t_limits[t_limits.Count - 1][0] += dt; }
                                else { t_limits[t_limits.Count - 1][1] -= dt; }
                                Pr.Add(Bs);
                                Bs = new List<double>();
                                Times.Add(Time);
                                Time = new List<double>();
                                Xe.Add(X);
                                X = new List<double>();
                                Ye.Add(Y);
                                Y = new List<double>();
                                Ze.Add(Z);
                                Z = new List<double>();
                                Xs.Add(X_);
                                X_ = new List<double>();
                                Ys.Add(Y_);
                                Y_ = new List<double>();
                                Zs.Add(Z_);
                                Z_ = new List<double>();
                                ///Ensure Continuity...
                                //Time.Add(Times[Times.Count - 1].Last());
                                //Bs.Add(Pr[Pr.Count - 1].Last());
                                //X.Add(Xe[Xe.Count - 1].Last());
                                //Y.Add(Ye[Ye.Count - 1].Last());
                                //Z.Add(Ze[Ze.Count - 1].Last());
                                //X_.Add(Xs[Xs.Count - 1].Last());
                                //Y_.Add(Ys[Ys.Count - 1].Last());
                                //Z_.Add(Zs[Zs.Count - 1].Last());
                                //dtnew *= -1;
                            }
                            deltaS = dtnew;
                        }
                        Vector DIRs = PathVertices[i][1] - PathVertices[i][0];
                        DIRs.Normalize();
                        X_.Add(DIRs.x);
                        Y_.Add(DIRs.y);
                        Z_.Add(DIRs.z);

                        Bs.Add(Pres);
                        Time.Add(Tn);
                        X.Add(DIR.x);
                        Y.Add(DIR.y);
                        Z.Add(DIR.z);
                    }

                    if (Bs.Count > 0)
                    {
                        t_limits.Add(new double[2] { Time.Min(), Time.Max() });
                        Pr.Add(Bs);
                        Times.Add(Time);
                        Xe.Add(X);
                        Ye.Add(Y);
                        Ze.Add(Z);
                        Xs.Add(X_);
                        Ys.Add(Y_);
                        Zs.Add(Z_);
                    }
                    MathNet.Numerics.Interpolation.CubicSpline[] Pr_Spline = new MathNet.Numerics.Interpolation.CubicSpline[Pr.Count];
                    MathNet.Numerics.Interpolation.CubicSpline[] X_Spline = new MathNet.Numerics.Interpolation.CubicSpline[Xe.Count];
                    MathNet.Numerics.Interpolation.CubicSpline[] Y_Spline = new MathNet.Numerics.Interpolation.CubicSpline[Ye.Count];
                    MathNet.Numerics.Interpolation.CubicSpline[] Z_Spline = new MathNet.Numerics.Interpolation.CubicSpline[Ze.Count];
                    MathNet.Numerics.Interpolation.CubicSpline[] Xs_Spline = new MathNet.Numerics.Interpolation.CubicSpline[Xs.Count];
                    MathNet.Numerics.Interpolation.CubicSpline[] Ys_Spline = new MathNet.Numerics.Interpolation.CubicSpline[Ys.Count];
                    MathNet.Numerics.Interpolation.CubicSpline[] Zs_Spline = new MathNet.Numerics.Interpolation.CubicSpline[Zs.Count];
                    double min = double.PositiveInfinity;
                    for (int i = 0; i < Times.Count; i++)
                    {
                        Pr_Spline[i] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(Times[i], Pr[i]);
                        X_Spline[i] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(Times[i], Xe[i]);
                        Y_Spline[i] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(Times[i], Ye[i]);
                        Z_Spline[i] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(Times[i], Ze[i]);
                        Xs_Spline[i] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(Times[i], Xs[i]);
                        Ys_Spline[i] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(Times[i], Ys[i]);
                        Zs_Spline[i] = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(Times[i], Zs[i]);

                        min = Math.Min(min, t_limits[i][1]);
                    }

                    //TODO: Find a way to include absorption/transmission effects... which will not affect the entire multipath reflection...
                    Dictionary<int, double> H_d = new Dictionary<int, double>();
                    Dictionary<int, double>[] H_directional = new Dictionary<int, double>[6];
                    for (int i = 0; i < 6; i++) H_directional[i] = new Dictionary<int, double>(); 

                    for (int i = 0; i < t_limits.Count; i++)
                    {
                        for (double t = t_limits[i][0]; t < t_limits[i][1]; t += dt)
                        {
                            Vector dir = new Vector(Xs_Spline[i].Interpolate(t), Ys_Spline[i].Interpolate(t), Zs_Spline[i].Interpolate(t));

                            ////Compose Impulse Response...
                            //double T_current = (lengths[p_id] + dl[0]) / Room.Sound_speed(new Hare.Geometry.Point(0, 0, 0));
                            //double T_duration = (length2 + dl[1]) / Room.Sound_speed(new Hare.Geometry.Point(0, 0, 0)) - T_current;

                            ///Apply TransMod to TF...
                            ///Each sample will have it's own unique air attenuation and occlusion conditions, which means that it needs to be treated individually for input signal (for air attenuation and absorption).
                            //double[] TF = Audio.Pach_SP.Magnitude_Filter(new double[8] { Math.Sqrt(Trans_Mod[p_id][0] * SW[0]), Math.Sqrt(Trans_Mod[p_id][1] * SW[1]), Math.Sqrt(Trans_Mod[p_id][2] * SW[2]), Math.Sqrt(Trans_Mod[p_id][3] * SW[3]), Math.Sqrt(Trans_Mod[p_id][4] * SW[4]), Math.Sqrt(Trans_Mod[p_id][5] * SW[5]), Math.Sqrt(Trans_Mod[p_id][6] * SW[6]), Math.Sqrt(Trans_Mod[p_id][7] * SW[7]) }, 44100, 4096, Threadid);
                            double[] SW = Src.DirPower(Threadid, this.Rnd[Threadid].Next(), dir);
                            foreach (Environment.Material m in M)
                            {
                                if (m is Environment.Basic_Material) for (int oct = 0; oct < 8; oct++)
                                    {
                                        SW[oct] *= 1 - m.Coefficient_A_Broad(oct);
                                        //SW[oct] *= Trans_Mod[j][oct];
                                    }
                            }

                            System.Numerics.Complex[] TF = Audio.Pach_SP.Filter.Spectrum(new double[8] { Math.Sqrt(SW[0]), Math.Sqrt(SW[1]), Math.Sqrt(SW[2]), Math.Sqrt(SW[3]), Math.Sqrt(SW[4]), Math.Sqrt(SW[5]), Math.Sqrt(SW[6]), Math.Sqrt(SW[7]) }, 44100, 4096, Threadid);
                        //double[] ms = Audio.Pach_SP.Magnitude_Spectrum(new double[8] { Math.Sqrt(SW[0]), Math.Sqrt(SW[1]), Math.Sqrt(SW[2]), Math.Sqrt(SW[3]), Math.Sqrt(SW[4]), Math.Sqrt(SW[5]), Math.Sqrt(SW[6]), Math.Sqrt(SW[7]) }, 44100, 4096, Threadid);
                        //double[] ms = Audio.Pach_SP.Magnitude_Spectrum(new double[8] { Math.Sqrt(SW[0]), Math.Sqrt(SW[1]), Math.Sqrt(SW[2]), Math.Sqrt(SW[3]), Math.Sqrt(SW[4]), Math.Sqrt(SW[5]), Math.Sqrt(SW[6]), Math.Sqrt(SW[7]) }, 88200, 8096, Threadid);

                        //System.Numerics.Complex[] TF = new System.Numerics.Complex[ms.Length];
                        //    for (int j = 0; j < TF.Length; j++) TF[j] = ms[j];
                                //Array.Resize(ref TF, TF.Length / 2);

                            ///Apply Air attenuation to TF...
                            double[] atten = new double[0];
                            double[] freq = new double[0];
                            Room.AttenuationFilter(4096, 44100, t * c_sound, ref freq, ref atten, Rec[rec_id]);//sig is the magnitude response of the air attenuation filter...
                            //Room.AttenuationFilter(4096, 88200, t * c_sound, ref freq, ref atten, Rec[rec_id]);//sig is the magnitude response of the air attenuation filter...
                            for (int j = 0; j < TF.Length; j++) TF[j] *= atten[j];
                            
                            for (int j = 0; j < M.Length; j++)
                            {
                                if (!(M[j] is Environment.Basic_Material))
                                {
                                    if (Sequence[j] < Room.PlaneCount)
                                    {
                                        System.Numerics.Complex[] spec = M[j].Reflection_Spectrum(44100, 4096 / 2, Room.Normal(Sequence[j]), PathVertices[i][j] - PathVertices[i][j - 1], Threadid);
                                        for (int k = 0; k < TF.Length; k++) TF[k] *= spec[k];
                                    }
                                }
                            }

                            //Audio.Pach_SP.Filter.Response(TF, SampleRate, Threadid);

                            double[] pulse = Audio.Pach_SP.IFFT_Real4096(Audio.Pach_SP.Mirror_Spectrum(TF), Threadid);
                            //double[] pulse = new double[prepulse.Length];
                            Audio.Pach_SP.Scale(ref pulse);
                            //for (int j = 0; j < prepulse.Length; j++)
                            //{
                            //    pulse[j] = prepulse[(j + prepulse.Length/2) % prepulse.Length];
                            //}
                            ////////////////////////////////////////////////////////
                            //Pachyderm_Acoustic.Audio.Pach_SP.resample(ref pulse);
                            ////////////////////////////////////////////////////////
                            //Audio.Pach_SP.Raised_Cosine_Window(ref pulse);
                            //Manual convolution of each distinct contribution of edge...
                            int index = (int)Math.Floor(t * SampleRate);
                            double omni_pr = Pr_Spline[i].Interpolate(t);
                            dir = new Vector(X_Spline[i].Interpolate(t), Y_Spline[i].Interpolate(t), Z_Spline[i].Interpolate(t));
                            double[] dir_c = new double[6];
                            if (dir.x > 0) dir_c[0] = dir.x; else dir_c[1] = -dir.x;
                            if (dir.y > 0) dir_c[2] = dir.y; else dir_c[3] = -dir.y;
                            if (dir.z > 0) dir_c[4] = dir.z; else dir_c[5] = -dir.z;

                            for (int j = 0; j < pulse.Length; j++)
                            {
                                //Todo: confirm that pulse comes in at right times...
                                int t_c = index + j;
                                double p_t = omni_pr * pulse[j] / 4096;

                                if (!H_d.Keys.Contains<int>(index + j))
                                {
                                    H_d.Add(t_c, p_t);
                                    H_directional[0].Add(t_c, p_t * dir_c[0]);
                                    H_directional[1].Add(t_c, p_t * dir_c[1]);
                                    H_directional[2].Add(t_c, p_t * dir_c[2]);
                                    H_directional[3].Add(t_c, p_t * dir_c[3]);
                                    H_directional[4].Add(t_c, p_t * dir_c[4]);
                                    H_directional[5].Add(t_c, p_t * dir_c[5]);
                                }
                                else
                                {
                                    H_d[t_c] += (float)(p_t);
                                    H_directional[0][t_c] += p_t * dir_c[0];
                                    H_directional[1][t_c] += p_t * dir_c[1];
                                    H_directional[2][t_c] += p_t * dir_c[2];
                                    H_directional[3][t_c] += p_t * dir_c[3];
                                    H_directional[4][t_c] += p_t * dir_c[4];
                                    H_directional[5][t_c] += p_t * dir_c[5];
                                }
                            }
                        }
                    }
                    int minsample = H_d.Keys.Min();
                    int maxsample = H_d.Keys.Max();
                    double T0 = (double)minsample / SampleRate;
                    H = new double[maxsample - minsample];
                    double[][] Hdir = new double[6][];
                    for(int j = 0; j < 6; j++) Hdir[j] = new double[maxsample - minsample];
                    for (int j = minsample; j < maxsample; j++) if (H_d.Keys.Contains<int>(j))
                        {
                            H[j - minsample] = H_d[j];
                            Hdir[0][j - minsample] = H_directional[0][j];
                            Hdir[1][j - minsample] = H_directional[1][j];
                            Hdir[2][j - minsample] = H_directional[2][j];
                            Hdir[3][j - minsample] = H_directional[3][j];
                            Hdir[4][j - minsample] = H_directional[4][j];
                            Hdir[5][j - minsample] = H_directional[5][j];
                        }
                    ///Enter the reflection
                    PathVertices.RemoveAll(item => item == null);
                    ThreadPaths[rec_id, Threadid].Add(new Compound_Path(PathVertices.ToArray(), Sequence, Src.Source_ID(), H, Hdir, T0, Speed_of_Sound, ref Direct_Time[rec_id], Threadid));
            }
        }
            public void ISO9613_1_Spline(double Tk, double Pa, double Hr)
            {
                double[] freq = new double[1024];
                double df = 22050/1024;
                for (int i = 1; i < 1025; i++)
                {
                    freq[i-1] = df * i;
                }

                Spectrum = MathNet.Numerics.Interpolation.CubicSpline.InterpolateAkima(freq, ISO9613_1_attencoef(freq, Tk, Pa, Hr));
            }