/// <summary> /// Writes a Pac1 file. [Useable by scripts and interface components alike.] /// </summary> /// <param name="Direct_Data">Array of Completed Direct Sound Simulations Required</param> /// <param name="IS_Data">Array of Completed Image Source Simulations. Enter null if opted out.</param> /// <param name="Receiver">Array of Completed Ray-Tracing Simulation Receivers. Enter null if opted out.</param> public static void Write_Pac1(Direct_Sound[] Direct_Data, ImageSourceData[] IS_Data = null, Environment.Receiver_Bank[] Receiver = null) { System.Windows.Forms.SaveFileDialog sf = new System.Windows.Forms.SaveFileDialog(); sf.DefaultExt = ".pac1"; sf.AddExtension = true; sf.Filter = "Pachyderm Ray Data file (*.pac1)|*.pac1|" + "All Files|"; if (sf.ShowDialog() == System.Windows.Forms.DialogResult.OK) { Write_Pac1(sf.FileName, Direct_Data, IS_Data, Receiver); } }
public void GetSims(ref Direct_Sound[] D, ref ImageSourceData[] IS, ref Receiver_Bank[] RT) { if (Direct_Data != null) D = Direct_Data; if (IS_Data != null) IS = IS_Data; if (Receiver != null) RT = Receiver; }
/// <summary> /// Approximation of the 5 second order ambisonics channels. (Fig8 3Axis and omni are the first four). /// </summary> /// <param name="Direct"></param> /// <param name="ISData"></param> /// <param name="RTData"></param> /// <param name="CO_Time"></param> /// <param name="Sampling_Frequency"></param> /// <param name="Rec_ID"></param> /// <param name="Start_at_Zero"></param> /// <param name="xpos_alt"></param> /// <param name="xpos_azi"></param> /// <param name="degrees"></param> /// <returns></returns> public static double[][] PTCurve_Ambisonics2(Direct_Sound Direct, ImageSourceData ISData, Receiver_Bank RTData, double CO_Time_ms, int Sampling_Frequency, int Rec_ID, bool Start_at_Zero, double xpos_alt, double xpos_azi, bool degrees) { double[][] Histogram = new double[5][]; if (RTData != null) { double[][] hist_temp = RTData.Pressure_3Axis(Rec_ID); Histogram[0] = new double[hist_temp[0].Length]; Histogram[1] = new double[hist_temp[0].Length]; Histogram[2] = new double[hist_temp[0].Length]; Histogram[3] = new double[hist_temp[0].Length]; Histogram[4] = new double[hist_temp[0].Length]; for (int i = 0; i < hist_temp[0].Length; i++) { Hare.Geometry.Vector Vpos = PachTools.Rotate_Vector(PachTools.Rotate_Vector(new Hare.Geometry.Vector(hist_temp[0][i], hist_temp[2][i], hist_temp[4][i]), xpos_azi, 0, true), 0, xpos_alt, true); Hare.Geometry.Vector Vneg = PachTools.Rotate_Vector(PachTools.Rotate_Vector(new Hare.Geometry.Vector(-hist_temp[1][i], -hist_temp[3][i], -hist_temp[5][i]), xpos_azi, 0, true), 0, xpos_alt, true); double magpos = Math.Sqrt(Vpos.x * Vpos.x + Vpos.y * Vpos.y + Vpos.z * Vpos.z); double magneg = Math.Sqrt(Vneg.x * Vneg.x + Vneg.y * Vneg.y + Vneg.z * Vneg.z); double phipos = Math.Asin(Vpos.z / magpos); double phineg = Math.Asin(Vneg.z / magneg); double thetapos = Math.Asin(Vpos.y / magpos / Math.Cos(phipos)); double thetaneg = Math.Asin(Vneg.y / magneg / Math.Cos(phineg)); double rt3_2 = Math.Sqrt(3) / 2; double sin2phpos = Math.Sin(2 * phipos); double sin2phneg = Math.Sin(2 * phineg); double cossqphpos = Math.Cos(phipos) * Math.Cos(phipos); double cossqphneg = Math.Cos(phineg) * Math.Cos(phineg); Histogram[0][i] = magpos * (3 * (Math.Sin(phipos) * Math.Sin(phipos) - 1) / 2 + magneg * 3 * Math.Sin(phineg) * Math.Sin(phineg) - 1) / 2; Histogram[1][i] = rt3_2 * (Math.Cos(thetapos) * sin2phpos * magpos + Math.Cos(thetaneg) * sin2phneg * magneg); Histogram[2][i] = rt3_2 * (Math.Sin(thetapos) * sin2phpos * magpos + Math.Sin(thetaneg) * sin2phneg * magneg); Histogram[3][i] = rt3_2 * (Math.Cos(2 * thetapos) * cossqphpos * magpos + Math.Cos(2 * thetaneg) * cossqphneg * magneg); Histogram[4][i] = rt3_2 * (Math.Sin(2 * thetapos) * cossqphpos * magpos + Math.Sin(2 * thetaneg) * cossqphneg * magneg); } } else { Histogram[0] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency) + 4096]; Histogram[1] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency) + 4096]; Histogram[2] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency) + 4096]; Histogram[4] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency) + 4096]; Histogram[5] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency) + 4096]; } if (Direct != null && Direct.IsOccluded(Rec_ID)) { int D_Start = 0; if (!Start_at_Zero) D_Start = (int)Math.Ceiling(Direct.Time(Rec_ID) * Sampling_Frequency); double[][] V = Direct.Dir_Pressure(Rec_ID, xpos_alt, xpos_azi, degrees, true); for (int i = 0; i < V.Length; i++) { double mag = Math.Sqrt(V[i][0] * V[i][0] + V[i][1] * V[i][1] + V[i][2] * V[i][2]); double phi = Math.Asin(V[i][2] / mag); double theta = Math.Asin(V[i][1] / mag / Math.Cos(phi)); double rt3_2 = Math.Sqrt(3) / 2; double sin2phi = Math.Sin(2 * phi); double cossqphi = Math.Cos(phi) * Math.Cos(phi); Histogram[0][i + D_Start] += mag * 3 * (Math.Sin(phi) * Math.Sin(phi) - 1) / 2; Histogram[1][i + D_Start] += rt3_2 * Math.Cos(theta) * sin2phi * mag; Histogram[2][i + D_Start] += rt3_2 * Math.Sin(theta) * sin2phi * mag; Histogram[3][i + D_Start] += rt3_2 * Math.Cos(2 * theta) * cossqphi * mag; Histogram[4][i + D_Start] += rt3_2 * Math.Sin(2 * theta) * cossqphi * mag; } } if (ISData != null) { foreach (Deterministic_Reflection value in ISData.Paths[Rec_ID]) { if (Math.Ceiling(Sampling_Frequency * value.TravelTime) < Histogram[0].Length - 1) { int R_Start = (int)Math.Ceiling(Sampling_Frequency * value.TravelTime); double[][] V = value.Dir_Pressure(Rec_ID, xpos_alt, xpos_azi, degrees, Sampling_Frequency); Hare.Geometry.Vector dir = value.Path[0][value.Path[0].Length - 1] - value.Path[0][value.Path[0].Length - 2]; dir.Normalize(); for (int i = 0; i < V.Length; i++) { double mag = Math.Sqrt(V[i][0] * V[i][0] + V[i][1] * V[i][1] + V[i][2] * V[i][2]); double phi = Math.Asin(V[i][2] / mag); double theta = Math.Asin(V[i][1] / mag / Math.Cos(phi)); double rt3_2 = Math.Sqrt(3) / 2; double sin2phi = Math.Sin(2 * phi); double cossqphi = Math.Cos(phi) * Math.Cos(phi); Histogram[0][i + R_Start] += mag * 3 * (Math.Sin(phi) * Math.Sin(phi) - 1) / 2; Histogram[1][i + R_Start] += rt3_2 * Math.Cos(theta) * sin2phi * mag; Histogram[2][i + R_Start] += rt3_2 * Math.Sin(theta) * sin2phi * mag; Histogram[3][i + R_Start] += rt3_2 * Math.Cos(2 * theta) * cossqphi * mag; Histogram[4][i + R_Start] += rt3_2 * Math.Sin(2 * theta) * cossqphi * mag; } } } } return Histogram; }
public static double[][] PTCurve_Ambisonics3(IEnumerable<Direct_Sound> Direct, IEnumerable<ImageSourceData> ISData, IEnumerable<Environment.Receiver_Bank> RTData, double CO_Time_ms, int Sampling_Frequency, int Rec_ID, List<int> SrcIDs, bool StartAtZero, double alt, double azi, bool degrees) { double[][] Histogram = new double[7][]; if (Direct == null) Direct = new Direct_Sound[SrcIDs[SrcIDs.Count - 1] + 1]; if (ISData == null) ISData = new ImageSourceData[SrcIDs[SrcIDs.Count - 1] + 1]; if (RTData == null) RTData = new Environment.Receiver_Bank[SrcIDs[SrcIDs.Count - 1] + 1]; double maxdelay = 0; List<double> delays = new List<double>(); if (Direct.ElementAt<Direct_Sound>(0) != null) { foreach (Direct_Sound d in Direct) { delays.Add(d.Delay_ms); maxdelay = Math.Max(maxdelay, d.Delay_ms); } } else if (RTData.ElementAt<Receiver_Bank>(0) != null) { foreach (Receiver_Bank r in RTData) { delays.Add(r.delay_ms); maxdelay = Math.Max(maxdelay, r.delay_ms); } } maxdelay *= Sampling_Frequency / 1000; Histogram[0] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency) + 4096 + (int)Math.Ceiling(maxdelay)]; Histogram[1] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency) + 4096 + (int)Math.Ceiling(maxdelay)]; Histogram[2] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency) + 4096 + (int)Math.Ceiling(maxdelay)]; Histogram[3] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency) + 4096 + (int)Math.Ceiling(maxdelay)]; Histogram[4] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency) + 4096 + (int)Math.Ceiling(maxdelay)]; Histogram[5] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency) + 4096 + (int)Math.Ceiling(maxdelay)]; Histogram[6] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency) + 4096 + (int)Math.Ceiling(maxdelay)]; foreach (int s in SrcIDs) { double[][] IR = PTCurve_Ambisonics3(Direct.ElementAt<Direct_Sound>(s), ISData.ElementAt<ImageSourceData>(s), RTData.ElementAt<Receiver_Bank>(s), CO_Time_ms, Sampling_Frequency, Rec_ID, StartAtZero, alt, azi, degrees); for (int d = 0; d < IR.Length; d++) { for (int i = 0; i < IR[0].Length; i++) { Histogram[d][i + (int)Math.Ceiling(delays[s] / 1000 * Sampling_Frequency)] += IR[d][i]; } } } return Histogram; }
public static double[][] PTCurve_Fig8_3Axis(Direct_Sound Direct, ImageSourceData ISData, Receiver_Bank RTData, double CO_Time_ms, int Sampling_Frequency, int Rec_ID, bool Start_at_Zero, double xpos_alt, double xpos_azi, bool degrees) { double[][] Histogram = new double[3][]; if (RTData != null) { double[][] hist_temp = RTData.Pressure_3Axis(Rec_ID); Histogram[0] = new double[hist_temp[0].Length]; Histogram[1] = new double[hist_temp[0].Length]; Histogram[2] = new double[hist_temp[0].Length]; for (int i = 0; i < hist_temp[0].Length; i++) { Hare.Geometry.Vector V = PachTools.Rotate_Vector(PachTools.Rotate_Vector(new Hare.Geometry.Vector(hist_temp[0][i] - hist_temp[1][i], hist_temp[2][i] - hist_temp[3][i], hist_temp[4][i] - hist_temp[5][i]), xpos_azi, 0, true), 0, xpos_alt, true); Histogram[0][i] = V.x; Histogram[1][i] = V.y; Histogram[2][i] = V.z; } } else { Histogram[0] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency) + 4096]; Histogram[1] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency) + 4096]; Histogram[2] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency) + 4096]; } if (Direct != null && Direct.IsOccluded(Rec_ID)) { int D_Start = 0; if (!Start_at_Zero) D_Start = (int)Math.Ceiling(Direct.Time(Rec_ID) * Sampling_Frequency); double[][] V = Direct.Dir_Pressure(Rec_ID, xpos_alt, xpos_azi, degrees, true); for (int i = 0; i < V.Length; i++) { Histogram[0][D_Start + i] += V[i][0]; Histogram[1][D_Start + i] += V[i][1]; Histogram[2][D_Start + i] += V[i][2]; } } if (ISData != null) { foreach (Deterministic_Reflection value in ISData.Paths[Rec_ID]) { if (Math.Ceiling(Sampling_Frequency * value.TravelTime) < Histogram[0].Length - 1) { int R_Start = (int)Math.Ceiling(Sampling_Frequency * value.TravelTime); double[][] V = value.Dir_Pressure(Rec_ID, xpos_alt, xpos_azi, degrees, Sampling_Frequency); Hare.Geometry.Vector dir = value.Path[0][value.Path[0].Length - 1] - value.Path[0][value.Path[0].Length - 2]; dir.Normalize(); for (int i = 0; i < value.Pressure.Length; i++) { Histogram[0][R_Start + i] += V[i][0]; Histogram[1][R_Start + i] += V[i][1]; Histogram[2][R_Start + i] += V[i][2]; } } } } return Histogram; }
/// <summary> /// Writes a Pac1 file. [Useable by scripts and interface components alike.] /// </summary> /// <param name="filename">The location of the final saved file...</param> /// <param name="Direct_Data">Array of Completed Direct Sound Simulations Required</param> /// <param name="IS_Data">Array of Completed Image Source Simulations. Enter null if opted out.</param> /// <param name="Receiver">Array of Completed Ray-Tracing Simulation Receivers. Enter null if opted out.</param> public static void Write_Pac1(string filename, Direct_Sound[] Direct_Data, ImageSourceData[] IS_Data = null, Environment.Receiver_Bank[] Receiver = null) { if (Direct_Data == null && IS_Data == null && IS_Data == null && Receiver != null) { System.Windows.Forms.MessageBox.Show("There is no simulated data to save."); return; } Pachyderm_Acoustic.UI.PachydermAc_PlugIn plugin = Pachyderm_Acoustic.UI.PachydermAc_PlugIn.Instance; System.IO.FileStream file = System.IO.File.Open(filename, System.IO.FileMode.Create); if (file.CanWrite) { System.IO.BinaryWriter sw = new System.IO.BinaryWriter(file); //1. Date & Time sw.Write(System.DateTime.Now.ToString()); //2. Plugin Version... if less than 1.1, assume only 1 source. sw.Write(plugin.Version); //3. Cut off Time (seconds) and SampleRate sw.Write((double)Receiver[0].CO_Time);//CO_TIME.Value); sw.Write(Receiver[0].SampleRate); //4.0 Source Count(int) Rhino.Geometry.Point3d[] SRC; plugin.SourceOrigin(out SRC); sw.Write(SRC.Length); for (int i = 0; i < SRC.Length; i++) { //4.1 Source Location x (double) sw.Write(SRC[i].X); //4.2 Source Location y (double) sw.Write(SRC[i].Y); //4.3 Source Location z (double) sw.Write(SRC[i].Z); } //5. No of Receivers sw.Write(Receiver[0].Rec_List.Length); //6. Write the coordinates of each receiver point //6b. Write the environmental characteristics at each receiver point (Rho * C); V2.0 only... for (int q = 0; q < Receiver[0].Rec_List.Length; q++) { sw.Write(Receiver[0].Rec_List[q].H_Origin.x); sw.Write(Receiver[0].Rec_List[q].H_Origin.y); sw.Write(Receiver[0].Rec_List[q].H_Origin.z); sw.Write(Receiver[0].Rec_List[q].Rho_C); } for (int s = 0; s < SRC.Length; s++) { if (Direct_Data != null) { //7. Write Direct Sound Data Direct_Data[s].Write_Data(ref sw); } if (IS_Data[0] != null) { //8. Write Image Source Sound Data IS_Data[s].Write_Data(ref sw); } if (Receiver != null) { //9. Write Ray Traced Sound Data Receiver[s].Write_Data(ref sw); } } sw.Write("End"); sw.Close(); } else { System.Windows.Forms.MessageBox.Show("Cannot write to file. It may be open in another application."); return; } }
public static bool Read_Pac1(string filename, ref Direct_Sound[] Direct_Data, ref ImageSourceData[] IS_Data, ref Environment.Receiver_Bank[] Receiver) { System.IO.BinaryReader sr = new System.IO.BinaryReader(System.IO.File.Open(filename, System.IO.FileMode.Open)); try { //1. Date & Time string Savedate = sr.ReadString(); //2. Plugin Version string Pach_version = sr.ReadString(); //3. Cut off Time and SampleRate double CO_TIME = sr.ReadDouble(); int SampleRate = sr.ReadInt32(); //4. Source Count int SrcCt = 1; if (double.Parse(Pach_version.Substring(0, 3)) >= 1.1) SrcCt = sr.ReadInt32(); //4.1 Source Location x //4.2 Source Location y //4.3 Source Location z Hare.Geometry.Point[] SrcPt = new Hare.Geometry.Point[SrcCt]; for (int s = 0; s < SrcCt; s++) SrcPt[s] = new Hare.Geometry.Point(sr.ReadDouble(), sr.ReadDouble(), sr.ReadDouble()); //5. No of Receivers int Rec_Ct = sr.ReadInt32(); //6. Write the coordinates of each receiver point //6b. Write the environmental characteristics at each receiver point (Rho * C); V2.0 only... Hare.Geometry.Point[] Recs = new Hare.Geometry.Point[Rec_Ct]; double[] Rho_C = new double[Rec_Ct]; for (int q = 0; q < Rec_Ct; q++) { Recs[q] = new Hare.Geometry.Point(sr.ReadDouble(), sr.ReadDouble(), sr.ReadDouble()); if (double.Parse(Pach_version.Substring(0, 3)) >= 2.0) Rho_C[q] = sr.ReadDouble(); else Rho_C[q] = 400; } Direct_Data = new Direct_Sound[SrcCt]; IS_Data = new ImageSourceData[SrcCt]; Receiver = new Environment.Receiver_Bank[SrcCt]; int DDCT = 0; int ISCT = 0; int RTCT = 0; do { string readin = sr.ReadString(); switch (readin) { case "Direct_Sound": case "Direct_Sound w sourcedata": //9. Read Direct Sound Data Direct_Data[DDCT] = Direct_Sound.Read_Data(ref sr, Recs, SrcPt[DDCT], Rho_C, Pach_version); Direct_Data[DDCT].CO_Time = CO_TIME; Direct_Data[DDCT].SampleFreq = (int)SampleRate; DDCT++; break; case "Image-Source_Data": //10. Read Image Source Sound Data IS_Data[ISCT] = ImageSourceData.Read_Data(ref sr, Recs.Length, Direct_Data[DDCT - 1], false, ISCT, Pach_version); ISCT++; break; case "Ray-Traced_Data": //11. Read Ray Traced Sound Data Receiver[RTCT] = Environment.Receiver_Bank.Read_Data(ref sr, Rec_Ct, Recs, Rho_C, Direct_Data[RTCT].Delay_ms, ref SampleRate, Pach_version); RTCT++; break; case "End": sr.Close(); return true; } } while (true); } catch (System.Exception X) { sr.Close(); System.Windows.Forms.MessageBox.Show("File Read Failed...", String.Format("Results file was corrupt or incomplete. We apologize for this inconvenience. Please report this to the software author. It will be much appreciated. \r\n Exception Message: {0}. \r\n Method: {1}" , X.Message, X.TargetSite)); return false; } }
/// <summary> /// Takes ETC, and extrapolates a pressure domain impulse response. /// </summary> /// <param name="DirectIn"></param> /// <param name="SpecularIn"></param> /// <param name="DiffuseIn"></param> /// <param name="CutOffTime"></param> /// <param name="sample_frequency_out">The desired sample frequency.</param> /// <param name="Rec_ID">The index of the receiver.</param> /// <returns></returns> public static double[] Expand_Dir_Response(Direct_Sound[] DirectIn, ImageSourceData[] SpecularIn, Environment.Receiver_Bank[] DiffuseIn, double CutOffTime, int sample_frequency_out, int Rec_ID, List<int> SrcID, double alt, double azi, bool degrees) { Random Rnd = new Random(); int length = (int)Math.Pow(2, 11); int sample_frequency_in = DiffuseIn[0].SampleRate; //fftwlib.fftw. FFT = new MathNet.Numerics.IntegralTransforms.Algorithms.DiscreteFourierTransform(); double[] IR = new double[(int)Math.Floor(sample_frequency_out * CutOffTime) + 2 * (int)length]; double[][] Octave_ETC = new double[8][]; double BW = (double)sample_frequency_out / (double)sample_frequency_in; //Convert to Pressure & Interpolate full resolution IR for (int oct = 0; oct < 8; oct++) { Octave_ETC[oct] = AcousticalMath.ETCurve_Directional(DirectIn, SpecularIn, DiffuseIn, CutOffTime, sample_frequency_in, oct, Rec_ID, SrcID, false, alt, azi, degrees); } return ETCToPTC(Octave_ETC, CutOffTime, sample_frequency_in, sample_frequency_out, DirectIn[0].Rho_C[Rec_ID]); }
public static double[] PTCurve(Direct_Sound Direct, ImageSourceData ISData, Environment.Receiver_Bank RTData, double CO_Time_ms, int samplerate, int Octave, int Rec_ID, bool StartAtZero, Numerics.ComplexComponent Output_Type) { Direct_Sound[] ArrDirect = new Direct_Sound[1]; ArrDirect[0] = Direct; ImageSourceData[] ArrIS = new ImageSourceData[1]; ArrIS[0] = ISData; Environment.Receiver_Bank[] ArrRT = new Environment.Receiver_Bank[1]; ArrRT[0] = RTData; double[] P; PTCurve(ArrDirect, ArrIS, ArrRT, CO_Time_ms*0.001, samplerate, Rec_ID, 0, StartAtZero, out P); double[] Pressure = new double[P.Length]; for (int i = 0; i < Pressure.Length; i++) Pressure[i] = P[i]; return Pressure; }
public static double[] ETCurve(Direct_Sound Direct, ImageSourceData ISData, Environment.Receiver_Bank RTData, double CO_Time_ms, int samplerate, int Octave, int Rec_ID, bool StartAtZero) { Direct_Sound[] ArrDirect = new Direct_Sound[1]; ArrDirect[0] = Direct; ImageSourceData[] ArrIS = new ImageSourceData[1]; ArrIS[0] = ISData; Receiver_Bank[] ArrRT = new Environment.Receiver_Bank[1]; ArrRT[0] = RTData; return ETCurve(ArrDirect, ArrIS, ArrRT, CO_Time_ms, samplerate, Octave, Rec_ID, 0, StartAtZero); }
public static double[] PTCurve(Direct_Sound[] Direct, ImageSourceData[] ISData, Environment.Receiver_Bank[] RTData, double CO_Time_ms, int Sampling_Frequency, int Rec_ID, List<int> SrcIDs, bool StartAtZero) { if (Direct == null) Direct = new Direct_Sound[SrcIDs[SrcIDs.Count - 1] + 1]; if (ISData == null) ISData = new ImageSourceData[SrcIDs[SrcIDs.Count - 1] + 1]; if (RTData == null) RTData = new Environment.Receiver_Bank[SrcIDs[SrcIDs.Count - 1] + 1]; double maxdelay = 0; List<double> delays = new List<double>(); if (Direct.ElementAt<Direct_Sound>(0) != null) { foreach (Direct_Sound d in Direct) { delays.Add(d.Delay_ms); maxdelay = Math.Max(maxdelay, d.Delay_ms); } } else if (RTData.ElementAt<Receiver_Bank>(0) != null) { foreach (Receiver_Bank r in RTData) { delays.Add(r.delay_ms); maxdelay = Math.Max(maxdelay, r.delay_ms); } } maxdelay *= Sampling_Frequency / 1000; double[] Histogram = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency) + 4096*2 + (int)Math.Ceiling(maxdelay)]; foreach (int s in SrcIDs) { double[] P; PTCurve(Direct, ISData, RTData, CO_Time_ms, Sampling_Frequency, Rec_ID, s, StartAtZero, out P); for (int i = 0; i < P.Length; i++) { Histogram[i + (int)Math.Ceiling(delays[s] /1000 * Sampling_Frequency)] += P[i]; } } return Histogram; }
public static double[] SPLTCurve_Pressure(Direct_Sound[] Direct, ImageSourceData[] ISData, Environment.Receiver_Bank[] RTData, double CO_Time, int samplerate, int Octave, int Rec_ID, int SrcID, bool Start_at_Zero) { double[] P;//, Imag; PTCurve(Direct, ISData, RTData, CO_Time, samplerate, Rec_ID, SrcID, Start_at_Zero, out P);//, out Imag); float[] Pressure = new float[P.Length]; double[] SPL = new double[Pressure.Length]; for (int i = 0; i < Pressure.Length; i++) { SPL[i] = SPL_Pressure(Pressure[i]); } return SPL; }
/// <summary> /// Calculates SPL-time curve from simulation output. /// </summary> /// <param name="Direct"></param> /// <param name="ISData"></param> /// <param name="RTData"></param> /// <param name="CO_Time"></param> /// <param name="samplerate"></param> /// <param name="Octave">the chosen octave band.</param> /// <param name="Rec_ID">the id of the selected receiver.</param> /// <returns></returns> public static double[] SPLTCurve_Intensity(Direct_Sound[] Direct, ImageSourceData[] ISData, Environment.Receiver_Bank[] RTData, double CO_Time, int samplerate, int Octave, int Rec_ID, int SrcID, bool Start_at_Zero) { double[] Energy = ETCurve(Direct, ISData, RTData, CO_Time, samplerate, Octave, Rec_ID, SrcID, Start_at_Zero); double[] SPL = new double[Energy.Length]; for (int i = 0; i < Energy.Length; i++) { SPL[i] = SPL_Intensity(Energy[i]); } return SPL; }
public static double[] PTCurve_Directional(Direct_Sound Direct, ImageSourceData ISData, Receiver_Bank RTData, double CO_Time_ms, int Sampling_Frequency, int Octave, int Rec_ID, bool Start_at_Zero, double alt, double azi, bool degrees) { double[] Histogram; if (RTData != null) { int[] ids = new int[3]; ids[0] = (azi > 90 && azi < 270) ? 1 : 0; ids[0] = (azi <= 180) ? 3 : 4; ids[0] = (alt > 0) ? 4 : 5; double[][] hist_temp = RTData.Pressure_3Axis(Rec_ID); Histogram = new double[hist_temp[0].Length]; for (int i = 0; i < hist_temp[0].Length; i++) { Hare.Geometry.Vector V = PachTools.Rotate_Vector(PachTools.Rotate_Vector(new Hare.Geometry.Vector(hist_temp[ids[0]][i], hist_temp[ids[1]][i], hist_temp[ids[2]][i]), azi, 0, true), 0, alt, true); Histogram[i] = V.x; } } else { Histogram = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency) + 4096]; } if (Direct != null && Direct.IsOccluded(Rec_ID)) { int D_Start = 0; if (!Start_at_Zero) D_Start = (int)Math.Ceiling(Direct.Time(Rec_ID) * Sampling_Frequency); double[][] V = Direct.Dir_Pressure(Rec_ID, alt, azi, degrees, false); for (int i = 0; i < V.Length; i++) { Histogram[D_Start + i] += V[i][0]; } } if (ISData != null) { foreach (Deterministic_Reflection value in ISData.Paths[Rec_ID]) { if (Math.Ceiling(Sampling_Frequency * value.TravelTime) < Histogram.Length - 1) { int R_Start = (int)Math.Ceiling(Sampling_Frequency * value.TravelTime); double[] V = value.Dir_Pressure(Rec_ID, alt, azi, degrees, false, Sampling_Frequency); for (int i = 0; i < value.Pressure.Length; i++) { Histogram[R_Start + i] += V[i]; } } } } return Histogram; }
public void GetSims(ref Hare.Geometry.Point[] Src, ref Hare.Geometry.Point[] Rec, ref Direct_Sound[] D, ref ImageSourceData[] IS, ref Receiver_Bank[] RT) { Src = new Hare.Geometry.Point[Source.Length]; for (int i = 0; i < Source.Length; i++) Src[i] = Source[i].H_Origin(); Rec = Recs; if (Direct_Data != null) D = Direct_Data; if (IS_Data != null) IS = IS_Data; if (Receiver != null) RT = Receiver; }
public static double[] Expand_Response(Direct_Sound[] DirectIn, ImageSourceData[] SpecularIn, Environment.Receiver_Bank[] DiffuseIn, double CutOffTime, int sample_frequency_out, int Rec_ID, List<int> SrcID) { int length = (int)Math.Pow(2, 11); int sample_frequency_in = DiffuseIn[0].SampleRate; double[] IR = new double[(int)Math.Floor(sample_frequency_out * CutOffTime) + 2 * (int)length]; double[][] Octave_ETC = new double[8][]; double BW = (double)sample_frequency_out / (double)sample_frequency_in; //Convert to Pressure & Interpolate full resolution IR for (int oct = 0; oct < 8; oct++) { Octave_ETC[oct] = AcousticalMath.ETCurve(DirectIn, SpecularIn, DiffuseIn, CutOffTime, sample_frequency_in, oct, Rec_ID, SrcID, false); } return ETCToPTC(Octave_ETC, CutOffTime, sample_frequency_in, sample_frequency_out, DirectIn[0].Rho_C[Rec_ID]); }
/// <summary> /// Calculates Energy-time curve from simulation output. /// </summary> /// <param name="Direct"></param> /// <param name="ISData"></param> /// <param name="RTData"></param> /// <param name="CO_Time"></param> /// <param name="Sampling_Frequency"></param> /// <param name="Octave">the chosen octave band.</param> /// <param name="Rec_ID">the id of the selected receiver.</param> /// <returns></returns> public static double[] ETCurve(Direct_Sound[] Direct, ImageSourceData[] ISData, Environment.Receiver_Bank[] RTData, double CO_Time_ms, int Sampling_Frequency, int Octave, int Rec_ID, int Src_ID, bool Start_at_Zero) { double[] Histogram = null; if (RTData[Src_ID] != null) { Histogram = RTData[Src_ID].GetEnergyHistogram(Octave, Rec_ID); } else { Histogram = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency)]; } if (Direct[Src_ID] != null && Direct[Src_ID].IsOccluded(Rec_ID)) { int D_Start = 0; if (!Start_at_Zero) D_Start = (int)Math.Ceiling(Direct[Src_ID].Time(Rec_ID) * Sampling_Frequency); for (int i = 0; i < Direct[Src_ID].Io[Rec_ID].GetLength(0); i++) { double DirectValue = 0; switch (Octave) { case 8: DirectValue = Direct[Src_ID].EnergySum(Rec_ID,i); break; default: DirectValue = Direct[Src_ID].EnergyValue(Octave, Rec_ID)[i]; break; } Histogram[D_Start + i] += DirectValue; } } if (ISData[Src_ID] != null) { switch (Octave) { case 8: foreach (Deterministic_Reflection value in ISData[Src_ID].Paths[Rec_ID]) { if (Math.Ceiling(Sampling_Frequency * value.TravelTime) < Histogram.Length - 1) { for (int oct = 0; oct < 8; oct++) { double[] e = value.Energy(oct); for (int t = 0; t < e.Length; t++) Histogram[(int)Math.Ceiling(Sampling_Frequency * value.TravelTime) + t] += e[t]; } } } break; default: foreach (Deterministic_Reflection value in ISData[Src_ID].Paths[Rec_ID]) { if (Math.Ceiling(Sampling_Frequency * value.TravelTime) < Histogram.Length - 1) { double[] e = value.Energy(Octave); for(int t = 0; t < e.Length; t++) Histogram[(int)Math.Ceiling(Sampling_Frequency * value.TravelTime) + t] += e[t]; } } break; } } return Histogram; }
/// <summary> /// Writes a Pac1 file. [Useable by scripts and interface components alike.] /// </summary> /// <param name="Direct_Data">Empty array of Direct Sound Simulations Required</param> /// <param name="IS_Data">Empty array of Image Source Simulations. Enter null if opted out.</param> /// <param name="Receiver">Empty array of Ray-Tracing Simulation Receivers. Enter null if opted out.</param> public static bool Read_Pac1(ref Direct_Sound[] Direct_Data, ref ImageSourceData[] IS_Data, ref Environment.Receiver_Bank[] Receiver) { System.Windows.Forms.OpenFileDialog sf = new System.Windows.Forms.OpenFileDialog(); sf.DefaultExt = ".pac1"; sf.AddExtension = true; sf.Filter = "Pachyderm Simulation (*.pac1)|*.pac1|" + "All Files|"; if (sf.ShowDialog() != System.Windows.Forms.DialogResult.OK) return false; return Read_Pac1(sf.FileName, ref Direct_Data, ref IS_Data, ref Receiver); }
/// <summary> /// Calculates pressure impulse response from simulation output. /// </summary> /// <param name="Direct"></param> /// <param name="ISData"></param> /// <param name="RTData"></param> /// <param name="CO_Time"></param> /// <param name="Sampling_Frequency"></param> /// <param name="Octave">the chosen octave band.</param> /// <param name="Rec_ID">the id of the selected receiver.</param> /// <returns></returns> public static void PTCurve(Direct_Sound[] Direct, ImageSourceData[] ISData, Environment.Receiver_Bank[] RTData, double CO_Time_ms, int Sampling_Frequency, int Rec_ID, int Src_ID, bool Start_at_Zero, out double[] P) { if (RTData[Src_ID] != null) { RTData[Src_ID].GetPressure(Rec_ID, out P);//8, } else { P = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency)]; } if (Direct[Src_ID] != null && Direct[Src_ID].IsOccluded(Rec_ID)) { int D_Start = 0; if (!Start_at_Zero) D_Start = (int)Math.Ceiling(Direct[Src_ID].Time(Rec_ID) * Sampling_Frequency); for (int i = 0; i < Direct[Src_ID].P[Rec_ID].GetLength(0); i++) { P[D_Start + i] += Direct[Src_ID].P[Rec_ID][i]; } } if (ISData[Src_ID] != null) { foreach (Deterministic_Reflection value in ISData[Src_ID].Paths[Rec_ID]) { if (Math.Ceiling(Sampling_Frequency * value.TravelTime) < P.Length - 1) { int end = value.Pressure.Length < P.Length - (int)Math.Ceiling(Sampling_Frequency * value.TravelTime) ? value.Pressure.Length : P.Length - (int)Math.Ceiling(Sampling_Frequency * value.TravelTime); for (int t = 0; t < end; t++) P[(int)Math.Ceiling(Sampling_Frequency * value.TravelTime) + t] += (float)value.Pressure[t]; } } } }
public static double[][] ETCurve_1d(Direct_Sound Direct, ImageSourceData ISData, Receiver_Bank RTData, double CO_Time_ms, int Sampling_Frequency, int Octave, int Rec_ID, bool Start_at_Zero, double alt, double azi, bool degrees) { double[][] Histogram = new double[3][]; Histogram[0] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency)]; Histogram[1] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency)]; Histogram[2] = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency)]; if (RTData != null) { for (int i = 0; i < Histogram[0].Length; i++) { Hare.Geometry.Vector Vpos = RTData.Directions_Pos(Octave, i, Rec_ID, alt, azi, degrees); Hare.Geometry.Vector Vneg = RTData.Directions_Neg(Octave, i, Rec_ID, alt, azi, degrees); double E = RTData.Rec_List[Rec_ID].Energy(i, Octave); Hare.Geometry.Vector VTot = new Hare.Geometry.Vector(Math.Abs(Vpos.x) - Math.Abs(Vneg.x), Math.Abs(Vpos.y) - Math.Abs(Vneg.y), Math.Abs(Vpos.z) - Math.Abs(Vneg.z)); VTot.Normalize(); VTot *= E; Histogram[0][i] = VTot.x; Histogram[1][i] = VTot.y; Histogram[2][i] = VTot.z; } } if (Direct != null && Direct.IsOccluded(Rec_ID)) { int D_Start = 0; if (!Start_at_Zero) D_Start = (int)Math.Ceiling(Direct.Time(Rec_ID) * Sampling_Frequency); Hare.Geometry.Vector[] DirectValue; switch (Octave) { case 8: DirectValue = Direct.Dir_Energy_Sum(Rec_ID, alt, azi, degrees); break; default: DirectValue = Direct.Dir_Energy(Octave, Rec_ID, alt, azi, degrees); break; } for (int i = 0; i < DirectValue.Length; i++) { Histogram[0][D_Start + i] += Math.Abs(DirectValue[i].x); Histogram[1][D_Start + i] += Math.Abs(DirectValue[i].y); Histogram[2][D_Start + i] += Math.Abs(DirectValue[i].z); } } if (ISData != null) { switch (Octave) { case 8: foreach (Deterministic_Reflection value in ISData.Paths[Rec_ID]) { if (Math.Ceiling(Sampling_Frequency * value.TravelTime) < Histogram[0].Length - 1) { Hare.Geometry.Vector[] E_Sum = value.Dir_EnergySum(alt, azi, degrees); for (int i = 0; i < E_Sum.Length; i++) { Histogram[0][(int)Math.Ceiling(Sampling_Frequency * value.TravelTime + i / Sampling_Frequency)] += Math.Abs(E_Sum[i].x); Histogram[1][(int)Math.Ceiling(Sampling_Frequency * value.TravelTime + i / Sampling_Frequency)] += Math.Abs(E_Sum[i].y); Histogram[2][(int)Math.Ceiling(Sampling_Frequency * value.TravelTime + i / Sampling_Frequency)] += Math.Abs(E_Sum[i].z); } } } break; default: foreach (Deterministic_Reflection value in ISData.Paths[Rec_ID]) { if (Math.Ceiling(Sampling_Frequency * value.TravelTime) < Histogram[0].Length - 1) { Hare.Geometry.Vector[] E_Dir = value.Dir_Energy(Octave, alt, azi, degrees); for (int i = 0; i < E_Dir.Length; i++) { Histogram[0][(int)Math.Ceiling(Sampling_Frequency * value.TravelTime + i / Sampling_Frequency)] += Math.Abs(E_Dir[i].x); Histogram[1][(int)Math.Ceiling(Sampling_Frequency * value.TravelTime + i / Sampling_Frequency)] += Math.Abs(E_Dir[i].y); Histogram[2][(int)Math.Ceiling(Sampling_Frequency * value.TravelTime + i / Sampling_Frequency)] += Math.Abs(E_Dir[i].z); } } } break; } } return Histogram; }
public static double[] ETCurve_Directional(Direct_Sound Direct, ImageSourceData ISData, Receiver_Bank RTData, double CO_Time_ms, int Sampling_Frequency, int Octave, int Rec_ID, bool Start_at_Zero, double alt, double azi, bool degrees) { double[] Histogram = new double[(int)(CO_Time_ms * 0.001 * Sampling_Frequency)]; if (RTData != null) { for (int i = 0; i < Histogram.Length; i++) { Hare.Geometry.Vector Vpos = RTData.Directions_Pos(Octave, i, Rec_ID, alt, azi, degrees); Hare.Geometry.Vector Vneg = RTData.Directions_Neg(Octave, i, Rec_ID, alt, azi, degrees); double E = RTData.Rec_List[Rec_ID].Energy(i, Octave); Hare.Geometry.Vector VTot = new Hare.Geometry.Vector(Math.Abs(Vpos.x) - Math.Abs(Vneg.x), Math.Abs(Vpos.y) - Math.Abs(Vneg.y), Math.Abs(Vpos.z) - Math.Abs(Vneg.z)); if (Vpos.x > 0) { Histogram[i] += Math.Abs(Vpos.x); } if (Vneg.x > 0) { Histogram[i] += Math.Abs(Vneg.x); } double L = VTot.Length(); if (L > 0) Histogram[i] *= E / L; if (AcousticalMath.SPL_Intensity(Histogram[i]) > 200) { Rhino.RhinoApp.Write("Super high SPLs... what's going on, man?"); } } } if (Direct != null && Direct.IsOccluded(Rec_ID)) { int D_Start = 0; if (!Start_at_Zero) D_Start = (int)Math.Ceiling(Direct.Time(Rec_ID) * Sampling_Frequency); Hare.Geometry.Vector[] DirectValue; switch (Octave) { case 8: DirectValue = Direct.Dir_Energy_Sum(Rec_ID, alt, azi, degrees); break; default: DirectValue = Direct.Dir_Energy(Octave, Rec_ID, alt, azi, degrees); break; } for (int i = 0; i < DirectValue.Length; i++) { if (DirectValue[i].x > 0) Histogram[D_Start + i] += Math.Abs(DirectValue[i].x); } } if (ISData != null) { switch (Octave) { case 8: foreach (Deterministic_Reflection value in ISData.Paths[Rec_ID]) { if (Math.Ceiling(Sampling_Frequency * value.TravelTime) < Histogram.Length - 1) { Hare.Geometry.Vector[] E_Sum = value.Dir_EnergySum(alt, azi, degrees); for (int i = 0; i < E_Sum.Length; i++) { if (E_Sum[i].x > 0) Histogram[(int)Math.Ceiling(Sampling_Frequency * value.TravelTime + i)] += Math.Abs(E_Sum[i].x); } } } break; default: foreach (Deterministic_Reflection value in ISData.Paths[Rec_ID]) { if (Math.Ceiling(Sampling_Frequency * value.TravelTime) < Histogram.Length - 1) { Hare.Geometry.Vector[] E_Dir = value.Dir_Energy(Octave, alt, azi, degrees); for (int i = 0; i < E_Dir.Length; i++) { if (E_Dir[i].x > 0) Histogram[(int)Math.Ceiling(Sampling_Frequency * value.TravelTime + i)] += Math.Abs(E_Dir[i].x); } } } break; } } return Histogram; }
public static bool Read_Pac1(string filename, ref Direct_Sound[] Direct_Data, ref ImageSourceData[] IS_Data, ref Environment.Receiver_Bank[] Receiver) { System.IO.BinaryReader sr = new System.IO.BinaryReader(System.IO.File.Open(filename, System.IO.FileMode.Open)); try { //1. Date & Time string Savedate = sr.ReadString(); //2. Plugin Version string Pach_version = sr.ReadString(); //3. Cut off Time and SampleRate double CO_TIME = sr.ReadDouble(); int SampleRate = sr.ReadInt32(); //4. Source Count int SrcCt = 1; if (double.Parse(Pach_version.Substring(0, 3)) >= 1.1) { SrcCt = sr.ReadInt32(); } //4.1 Source Location x //4.2 Source Location y //4.3 Source Location z Hare.Geometry.Point[] SrcPt = new Hare.Geometry.Point[SrcCt]; for (int s = 0; s < SrcCt; s++) { SrcPt[s] = new Hare.Geometry.Point(sr.ReadDouble(), sr.ReadDouble(), sr.ReadDouble()); } //5. No of Receivers int Rec_Ct = sr.ReadInt32(); //6. Write the coordinates of each receiver point //6b. Write the environmental characteristics at each receiver point (Rho * C); V2.0 only... Hare.Geometry.Point[] Recs = new Hare.Geometry.Point[Rec_Ct]; double[] Rho_C = new double[Rec_Ct]; for (int q = 0; q < Rec_Ct; q++) { Recs[q] = new Hare.Geometry.Point(sr.ReadDouble(), sr.ReadDouble(), sr.ReadDouble()); if (double.Parse(Pach_version.Substring(0, 3)) >= 2.0) { Rho_C[q] = sr.ReadDouble(); } else { Rho_C[q] = 400; } } Direct_Data = new Direct_Sound[SrcCt]; IS_Data = new ImageSourceData[SrcCt]; Receiver = new Environment.Receiver_Bank[SrcCt]; int DDCT = 0; int ISCT = 0; int RTCT = 0; do { string readin = sr.ReadString(); switch (readin) { case "Direct_Sound": case "Direct_Sound w sourcedata": //9. Read Direct Sound Data Direct_Data[DDCT] = Direct_Sound.Read_Data(ref sr, Recs, SrcPt[DDCT], Rho_C, Pach_version); Direct_Data[DDCT].CO_Time = CO_TIME; Direct_Data[DDCT].SampleFreq = (int)SampleRate; DDCT++; break; case "Image-Source_Data": //10. Read Image Source Sound Data IS_Data[ISCT] = ImageSourceData.Read_Data(ref sr, Recs.Length, Direct_Data[DDCT - 1], false, ISCT, Pach_version); ISCT++; break; case "Ray-Traced_Data": //11. Read Ray Traced Sound Data Receiver[RTCT] = Environment.Receiver_Bank.Read_Data(ref sr, Direct_Data[RTCT].SWL, Rec_Ct, Recs, Rho_C, Direct_Data[RTCT].Delay_ms, ref SampleRate, Pach_version); RTCT++; break; case "End": sr.Close(); return(true); } } while (true); } catch (System.Exception X) { sr.Close(); System.Windows.Forms.MessageBox.Show("File Read Failed...", String.Format("Results file was corrupt or incomplete. We apologize for this inconvenience. Please report this to the software author. It will be much appreciated. \r\n Exception Message: {0}. \r\n Method: {1}", X.Message, X.TargetSite)); return(false); } }
/// <summary> /// Writes a Pac1 file. [Useable by scripts and interface components alike.] /// </summary> /// <param name="filename">The location of the final saved file...</param> /// <param name="Direct_Data">Array of Completed Direct Sound Simulations Required</param> /// <param name="IS_Data">Array of Completed Image Source Simulations. Enter null if opted out.</param> /// <param name="Receiver">Array of Completed Ray-Tracing Simulation Receivers. Enter null if opted out.</param> public static void Write_Pac1(string filename, ref Direct_Sound[] Direct_Data, ref ImageSourceData[] IS_Data, ref Environment.Receiver_Bank[] Receiver) { if (Direct_Data == null && IS_Data == null && IS_Data == null && Receiver != null) { System.Windows.Forms.MessageBox.Show("There is no simulated data to save."); return; } Pachyderm_Acoustic.UI.PachydermAc_PlugIn plugin = Pachyderm_Acoustic.UI.PachydermAc_PlugIn.Instance; //use StreamWriter to write to csv files System.IO.StreamWriter sw = System.IO.File.CreateText(filename); //1. Date & Time sw.WriteLine("Current Date and Time"); sw.WriteLine(System.DateTime.Now.ToString()); //2. Plugin Version... if less than 1.1, assume only 1 source. sw.WriteLine("Plugin Version"); sw.WriteLine(plugin.Version); //3. Cut off Time (seconds) and SampleRate sw.WriteLine("Cut off Time"); sw.WriteLine((double)Receiver[0].CO_Time);//CO_TIME.Value); sw.WriteLine("Sample Rate"); sw.WriteLine(Receiver[0].SampleRate); //4.0 Source Count(int) Rhino.Geometry.Point3d[] SRC; plugin.SourceOrigin(out SRC); sw.WriteLine("Source Count"); sw.WriteLine(SRC.Length); //4 Source Location x,y,z (double) sw.WriteLine("Source Location : x y z"); for (int i = 0; i < SRC.Length; i++) sw.WriteLine(Helper_Functions.ConvertToCSVString(SRC[i].X, SRC[i].Y, SRC[i].Z)); //5. No of Receivers sw.WriteLine("Number of Receivers"); sw.WriteLine(Receiver[0].Rec_List.Length); //6. Write the coordinates of each receiver point //6b. Write the environmental characteristics at each receiver point (Rho * C); V2.0 only... for (int q = 0; q < Receiver[0].Rec_List.Length; q++) { string origin_and_rhoC = Helper_Functions.ConvertToCSVString( Receiver[0].Rec_List[q].H_Origin.x, Receiver[0].Rec_List[q].H_Origin.y, Receiver[0].Rec_List[q].H_Origin.z, Receiver[0].Rec_List[q].Rho_C); sw.WriteLine(origin_and_rhoC); } for (int s = 0; s < SRC.Length; s++) { if (Direct_Data != null) { //7. Write Direct Sound Data Direct_Data[s].Write_Data(ref sw); } if (IS_Data[0] != null) { //8. Write Image Source Sound Data IS_Data[s].Write_Data(ref sw); } if (Receiver != null) { //9. Write Ray Traced Sound Data Receiver[s].Write_Data(ref sw); } } sw.Write("End"); sw.Close(); }