/// <summary>Loads a waveform and relevant properties from a TDMS file.</summary> /// <param name="filePath">Specifies the absolute path to the .TDMS waveform file on disk.</param> /// <param name="waveformName">(Optional) Specifies the name to use to represent the waveform. The file name will be used by default.</param> /// <returns>The waveform data and associated properties represented in the Waveform type.</returns> public static Waveform LoadWaveformFromTDMS(string filePath, string waveformName = "") { Waveform waveform = new Waveform(); if (string.IsNullOrEmpty(waveformName)) { waveformName = Path.GetFileNameWithoutExtension(filePath); waveformName = FormatWaveformName(waveformName); } waveform.Name = waveformName; NIRfsgPlayback.ReadWaveformFromFileComplex(filePath, ref waveform.Data); NIRfsgPlayback.ReadWaveformFileVersionFromFile(filePath, out string waveformVersion); if (waveformVersion == "1.0.0") { // 1.0.0 waveforms use peak power adjustment = papr + runtime scaling // we will scale the waveform and calculate papr and runtime scaling manually float peak = ComplexSingle.GetMagnitudes(waveform.Data.GetRawData()).Max(); waveform.RuntimeScaling = 20.0 * Math.Log10(peak); NIRfsgPlayback.ReadPeakPowerAdjustmentFromFile(filePath, 0, out double peakPowerAdjustment); waveform.PAPR_dB = peakPowerAdjustment + waveform.RuntimeScaling; // scale the waveform to full scale WritableBuffer <ComplexSingle> waveformBuffer = waveform.Data.GetWritableBuffer(); ComplexSingle scale = ComplexSingle.FromPolar(1.0f / peak, 0.0f); for (int i = 0; i < waveform.Data.SampleCount; i++) { waveformBuffer[i] = waveformBuffer[i] * scale; // multiplication is faster than division } } else { NIRfsgPlayback.ReadPaprFromFile(filePath, 0, out waveform.PAPR_dB); //Version 2.0.0 and later NIRfsgPlayback.ReadRuntimeScalingFromFile(filePath, 0, out waveform.RuntimeScaling); } NIRfsgPlayback.ReadSampleRateFromFile(filePath, 0, out waveform.SampleRate); NIRfsgPlayback.ReadSignalBandwidthFromFile(filePath, 0, out waveform.SignalBandwidth_Hz); if (waveform.SignalBandwidth_Hz == 0.0) { waveform.SignalBandwidth_Hz = 0.8 * waveform.SampleRate; } NIRfsgPlayback.ReadBurstStartLocationsFromFile(filePath, 0, ref waveform.BurstStartLocations); NIRfsgPlayback.ReadBurstStopLocationsFromFile(filePath, 0, ref waveform.BurstStopLocations); //Statement reads: if NOT BurstStartLocations > 0 AND expression is not null (? operand) //In other words, manually set BurstStartLocations when the length is 0 or less or array is null if (!(waveform.BurstStartLocations?.Length > 0)) { waveform.BurstStartLocations = new int[1] { 0 } } ; //Set burst start to the first sample(0) if (!(waveform.BurstStopLocations?.Length > 0)) { waveform.BurstStopLocations = new int[1] { waveform.Data.SampleCount - 1 } } ; //Set burst stop to the last sample (number of samples minus one) // calculating IdleDurationPresent like this also accounts for tools like wlan sfp that put in burst start and stop locations even if there is no idle time in the waveform waveform.IdleDurationPresent = waveform.BurstStopLocations.First() - waveform.BurstStartLocations.First() < waveform.Data.SampleCount - 1; waveform.BurstLength_s = CalculateWaveformDuration(waveform.BurstStartLocations, waveform.BurstStopLocations, waveform.SampleRate); return(waveform); }