private bool ReadBuffer() { string errMsg = null; Wfdb.WFDB_SampleArray frameData = null; bool result = WfdbAccess.GetSignalFrame(ref frameData, siArray, numSignals, ref errMsg); if (result && (frameData.getitem(0) == 0)) { // Something weird! errMsg = null; // just for a flag } if (!result) { MessageBox.Show(errMsg); doneReading = true; // give up actual reading return(false); } // No error -- read frame data into buffer: for (int samp = 0; samp < buffSize; samp++) { frameBuffer[samp] = frameData.getitem(samp); //if (frameBuffer[samp] == 0) //{ // Something weird! // result = false; // just for a flag //} } // And, reset buffer pointer bufferPointer = 0; return(true); }
/* * /// <summary> * /// Minimal constructor. Note that if you use this constructor, you must set * /// recordName before calling init(), otherwise an exception will be raised. * /// </summary> * /// <param name="secondsPerStep">Interval between samples, in seconds or fraction thereof, * /// e.g. 1 KHz = 1 ms per sample would have secondsPerStep = 0.001. If * /// autoOutput is TRUE and the file header has its own sample period value, * /// then this param is ignored and the value in the file header is used * /// instead.</param> * /// <param name="autoOutput">If TRUE, then we push data out to the Followers AND try to * /// use the sample period value from the file header; if FALSE, we wait * /// for whoever to pull out the data.</param> * public WfdbReader ( double secondsPerStep, bool autoOutput ) * : base ( secondsPerStep, autoOutput ) * { // Nothing to do. * } * // */ /// <summary> /// Full constructor: requires a record name and an optional path. /// </summary> /// [param name="secondsPerStep">Interval between samples, in seconds or fraction thereof, /// e.g. 1 KHz = 1 ms per sample would have secondsPerStep = 0.001. If /// autoOutput is TRUE and the file header has its own sample period value, /// then this param is ignored and the value in the file header is used /// instead.[/param> /// <param name="autoOutput">If TRUE, then we push data out to the Followers AND try to /// use the sample period value from the file header; if FALSE, we wait /// for whoever to pull out the data.</param> /// <param name="path">A search path for the record; if null, then the default path is used.</param> /// <param name="rName">Must be an existing record name within the path.</param> public WfdbReader(/* double secondsPerStep, */ bool autoOutput, string path, string rName) : base(/*secondsPerStep*/ 1, autoOutput) { string errMsg = ""; // Save values: searchPath = path.Trim(); recordName = rName.Trim(); // Try the path and record name: if (searchPath != null) { WfdbAccess.SetSearchPath(searchPath); } sampFreq = WfdbAccess.GetSamplingFrequency(recordName); if (sampFreq < 1) { // Problem reading header! //System.Windows.Forms.MessageBox("Unable to access record '" + recordName + "' in path '" + searchPath + "'!"); Exception ex = new ArgumentException("Unable to access header for record '" + recordName + "' in path '" + searchPath + "'."); throw ex; } else { // Set secondsPerStep: this.stepSize = 1 / sampFreq; } numSignals = WfdbAccess.GetSignalCount(recordName, ref errMsg); if (numSignals < 1) { //System.Windows.Forms.MessageBox("Unable to access record '" + recordName + "' in path '" + searchPath + "'!"); Exception ex = new ArgumentException("Unable to access record '" + recordName + "' in path '" + searchPath + "'."); throw ex; } }
private void GoToPositionInFile(long samps, ref string errMsg) { if (samps > (int)samps) { // out of range -- go to max. int. val.: samps = Int32.MaxValue; } WfdbAccess.Seek((int)samps, ref errMsg); // Adjust cur-pos reference: dispSamples = samps; }
/// <summary> /// Releases all Wfdb-related resources. /// </summary> public void ReleaseWfdb() { // Release as needed: WfdbAccess.CloseWfdb(); }
/// <summary> /// Override default behavior to: /// - Save a local copy /// - Get file header info /// - Update iData accordingly /// - Allow using header info to drive the output rates. /// <para>NOTE: This method call GC.Collect() to force garbage collection on the /// managed-code environment. If you are running unmanaged code, before calling /// this method you must ensure that your unmanaged storage allocations are properly /// protected or released.</para> /// </summary> public override void init(ChainInfo iData) { string errMsg = null; // Reset THOROUGHLY: GC.Collect(); GC.WaitForPendingFinalizers(); WfdbAccess.CloseWfdb(); GC.Collect(); GC.WaitForPendingFinalizers(); // Read record header: siArray = WfdbAccess.GetSigInfoArray(numSignals, ref errMsg); bool result = WfdbAccess.GetSignalInfo(recordName, siArray, numSignals, ref errMsg); if (!result) { //System.Windows.Forms.MessageBox("Unable to access header for record '" + recordName + "' in path '" + searchPath + "'!"); Exception ex = new ArgumentException("Unable to access header for record '" + recordName + "' in path '" + searchPath + "'."); throw ex; } // Read useful info from header: WFDB_Siginfo sigInfo = siArray.getitem(0); buffSize = sigInfo.spf; frameBuffer = new int[buffSize]; numSamples = sigInfo.nsamp * sigInfo.spf; sigName = sigInfo.desc; //sampFreq = WfdbAccess.GetSamplingFrequency(recordName); //if (sampFreq < 1) //{ // Problem reading header! // //System.Windows.Forms.MessageBox("Unable to access record '" + recordName + "' in path '" + searchPath + "'!"); // Exception ex = new ArgumentException("Unable to access header for record '" + recordName + "' in path '" + searchPath + "'."); // throw ex; //} adcZeroRef = sigInfo.adczero; adcResBits = sigInfo.adcres; adcMaxValue = (int)Math.Pow(2, adcResBits); baseline = sigInfo.baseline; ampGain = sigInfo.gain; if (ampGain == 0) { // Use default: ampGain = 200; } dataUnits = sigInfo.units; if ((dataUnits == null) || (dataUnits.Length == 0)) { // Assign arbitrarily? dataUnits = "mV"; } // Save a local handle: if (autoSend) { // Point to the input data structure: initValues = iData; } else { // Make our own data structure: initValues = new ChainInfo(); initValues.samplingPeriodSec = iData.samplingPeriodSec; } if (autoSend && doneReading) // We previously terminated the timer - restart it: { // Init the TimerThread: sendTimer = new TimerThread( new System.Threading.ThreadStart(this.next), true); } // Init. what needs it: dispSamples = 0; // just started, nothing retrieved yet doneReading = false; if (initValues.patientInfo == null) { initValues.patientInfo = new PatientInfo("", "", ""); } if (initValues.dataInfo == null) { initValues.dataInfo = new DataInfo(sigInfo.desc, DateTime.Now.ToString()); } // And, apply the REAL values: initValues.dataInfo.BitsPerSample = adcResBits; initValues.dataInfo.ScaleMultiplier = ampGain.ToString(); if (adcResBits == 0) { // Missing some info -- go with a default: initValues.dataInfo.FullScaleReferenceVoltage = "2.0"; initValues.dataInfo.ZeroOffset = "0.0"; initValues.dataInfo.ZeroReferenceVoltage = "-2.0"; } else { initValues.dataInfo.FullScaleReferenceVoltage = ((adcMaxValue - baseline) / ampGain).ToString(); initValues.dataInfo.ZeroOffset = baseline.ToString(); initValues.dataInfo.ZeroReferenceVoltage = (-baseline / ampGain).ToString(); } initValues.dataInfo.ValueUnits = dataUnits; if (initValues.fileInfo == null) { initValues.fileInfo = new FileHandler(); } if (initValues.samplingPeriodSec != stepSize) { // Update the sampling period: initValues.samplingPeriodSec = stepSize; } //// Init. the sampling period: //this.stepSize = initValues.samplingPeriodSec; // Init output buffer: ReadBuffer(); // Apply values and propagate downstream: base.init(iData); // iData may have been changed or not }