コード例 #1
0
void UI_FreqSpectrumWindow::update_curve()
{
  int i, j, k,
      dftblocksize,
      dftblocks,
      samplesleft,
      fft_outputbufsize;

  long long s, s2;

  char str[512];

  double dig_value=0.0,
         f_tmp=0.0;

  union {
          unsigned int one;
          signed int one_signed;
          unsigned short two[2];
          signed short two_signed[2];
          unsigned char four[4];
        } var;

  if(signalcomp == NULL)
  {
    return;
  }

  if(busy)
  {
    return;
  }

  viewbuf = mainwindow->viewbuf;

  if(viewbuf == NULL)
  {
    return;
  }

  busy = 1;

  curve1->setUpdatesEnabled(false);

  samples = signalcomp->samples_on_screen;

  if(signalcomp->samples_on_screen > signalcomp->sample_stop)
  {
    samples = signalcomp->sample_stop;
  }

  samples -= signalcomp->sample_start;

  if((samples < 10) || (viewbuf == NULL))
  {
    curve1->setUpdatesEnabled(true);

    busy = 0;

    curve1->clear();

    return;
  }

  if(buf1 != NULL)
  {
    free(buf1);
  }
  buf1 = (double *)malloc(sizeof(double) * signalcomp->samples_on_screen);
  if(buf1 == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action.\n"
                                  "Decrease the timescale and try again.");
    messagewindow.exec();
    return;
  }

  samples = 0;

  for(s=signalcomp->sample_start; s<signalcomp->samples_on_screen; s++)
  {
    if(s>signalcomp->sample_stop)  break;

    dig_value = 0.0;
    s2 = s + signalcomp->sample_timeoffset - signalcomp->sample_start;

    for(j=0; j<signalcomp->num_of_signals; j++)
    {
      if(signalcomp->edfhdr->bdf)
      {
        var.two[0] = *((unsigned short *)(
          viewbuf
          + signalcomp->viewbufoffset
          + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record))
          + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset
          + ((s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record) * 3)));

        var.four[2] = *((unsigned char *)(
          viewbuf
          + signalcomp->viewbufoffset
          + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record))
          + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset
          + ((s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record) * 3)
          + 2));

        if(var.four[2]&0x80)
        {
          var.four[3] = 0xff;
        }
        else
        {
          var.four[3] = 0x00;
        }

        f_tmp = var.one_signed;
      }

      if(signalcomp->edfhdr->edf)
      {
        f_tmp = *(((short *)(
          viewbuf
          + signalcomp->viewbufoffset
          + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record))
          + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset))
          + (s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record));
      }

      f_tmp += signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].offset;
      f_tmp *= signalcomp->factor[j];

      dig_value += f_tmp;
    }

    if(signalcomp->spike_filter)
    {
      if(s==signalcomp->sample_start)
      {
        spike_filter_restore_buf(signalcomp->spike_filter);
      }

      dig_value = run_spike_filter(dig_value, signalcomp->spike_filter);
    }

    for(k=0; k<signalcomp->filter_cnt; k++)
    {
      dig_value = first_order_filter(dig_value, signalcomp->filter[k]);
    }

    for(k=0; k<signalcomp->ravg_filter_cnt; k++)
    {
      if(s==signalcomp->sample_start)
      {
        ravg_filter_restore_buf(signalcomp->ravg_filter[k]);
      }

      dig_value = run_ravg_filter(dig_value, signalcomp->ravg_filter[k]);
    }

    for(k=0; k<signalcomp->fidfilter_cnt; k++)
    {
      if(s==signalcomp->sample_start)
      {
        memcpy(signalcomp->fidbuf[k], signalcomp->fidbuf2[k], fid_run_bufsize(signalcomp->fid_run[k]));
      }

      dig_value = signalcomp->fidfuncp[k](signalcomp->fidbuf[k], dig_value);
    }

    if(signalcomp->ecg_filter != NULL)
    {
      if(s==signalcomp->sample_start)
      {
        ecg_filter_restore_buf(signalcomp->ecg_filter);
      }

      dig_value = run_ecg_filter(dig_value, signalcomp->ecg_filter);
    }

    if(s>=signalcomp->sample_start)
    {
      buf1[samples++] = dig_value * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue;
    }
  }

  samplefreq = (double)signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record / ((double)signalcomp->edfhdr->long_data_record_duration / TIME_DIMENSION);

  dftblocksize = mainwindow->maxdftblocksize;

  if(dftblocksize & 1)
  {
    dftblocksize--;
  }

  dftblocks = 1;

  if(dftblocksize < samples)
  {
    dftblocks = samples / dftblocksize;
  }
  else
  {
    dftblocksize = samples;
  }

  if(dftblocksize & 1)
  {
    dftblocksize--;
  }

  samplesleft = samples % dftblocksize;

  if(samplesleft & 1)
  {
    samplesleft--;
  }

  freqstep = samplefreq / (double)dftblocksize;

  fft_outputbufsize = dftblocksize / 2;

  steps = fft_outputbufsize;

  if(buf2 != NULL)
  {
    free(buf2);
  }
  buf2 = (double *)calloc(1, sizeof(double) * fft_outputbufsize);
  if(buf2 == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action.");
    messagewindow.exec();
    free(buf1);
    buf1 = NULL;
    return;
  }

  if(buf3 != NULL)
  {
    free(buf3);
  }
  buf3 = (double *)malloc(sizeof(double) * fft_outputbufsize);
  if(buf3 == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action.");
    messagewindow.exec();
    free(buf1);
    free(buf2);
    buf1 = NULL;
    buf2 = NULL;
    return;
  }

  if(buf4 != NULL)
  {
    free(buf4);
  }
  buf4 = (double *)malloc(sizeof(double) * fft_outputbufsize);
  if(buf4 == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action.");
    messagewindow.exec();
    free(buf1);
    free(buf2);
    free(buf3);
    buf1 = NULL;
    buf2 = NULL;
    buf3 = NULL;
    return;
  }

  if(buf5 != NULL)
  {
    free(buf5);
  }
  buf5 = (double *)malloc(sizeof(double) * fft_outputbufsize);
  if(buf5 == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action.");
    messagewindow.exec();
    free(buf1);
    free(buf2);
    free(buf3);
    free(buf4);
    buf1 = NULL;
    buf2 = NULL;
    buf3 = NULL;
    buf4 = NULL;
    return;
  }

  maxvalue = 0.000001;
  maxvalue_sqrt = 0.000001;
  maxvalue_vlog = 0.000001;
  maxvalue_sqrt_vlog = 0.000001;
  minvalue_vlog = 0.0;
  minvalue_sqrt_vlog = 0.0;

#ifdef CHECK_POWERSPECTRUM
  printf("samples is %i   dftblocksize is %i   dftblocks is %i    samplesleft is %i   fft_outputbufsize is %i    steps is %i\n", samples, dftblocksize, dftblocks, samplesleft, fft_outputbufsize, steps);

  double power1=0.0, power2=0.0;

  for(i=0; i<samples; i++)
  {
    power1 += (buf1[i] * buf1[i]);
  }
#endif

  kiss_fftr_cfg cfg;

  kiss_fft_cpx *kiss_fftbuf;

  kiss_fftbuf = (kiss_fft_cpx *)malloc((fft_outputbufsize + 1) * sizeof(kiss_fft_cpx));
  if(kiss_fftbuf == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action.");
    messagewindow.exec();
    free(buf1);
    free(buf2);
    free(buf3);
    free(buf4);
    free(buf5);
    buf1 = NULL;
    buf2 = NULL;
    buf3 = NULL;
    buf4 = NULL;
    buf5 = NULL;
    return;
  }

  cfg = kiss_fftr_alloc(dftblocksize, 0, NULL, NULL);

  for(j=0; j<dftblocks; j++)
  {
    kiss_fftr(cfg, buf1 + (j * dftblocksize), kiss_fftbuf);

    for(i=0; i<fft_outputbufsize; i++)
    {
      buf2[i] += (((kiss_fftbuf[i].r * kiss_fftbuf[i].r) + (kiss_fftbuf[i].i * kiss_fftbuf[i].i)) / fft_outputbufsize);
    }
  }

  if(samplesleft)
  {
    kiss_fftr(cfg, buf1 + (((j-1) * dftblocksize) + samplesleft), kiss_fftbuf);

    for(i=0; i<fft_outputbufsize; i++)
    {
      buf2[i] += (((kiss_fftbuf[i].r * kiss_fftbuf[i].r) + (kiss_fftbuf[i].i * kiss_fftbuf[i].i)) / fft_outputbufsize);

      buf2[i] /= (dftblocks + 1);
    }
  }
  else
  {
    for(i=0; i<fft_outputbufsize; i++)
    {
      buf2[i] /= dftblocks;
    }
  }

  if(signalcomp->ecg_filter == NULL)
  {
    buf2[0] /= 2.0;  // DC!
  }
  else
  {
    buf2[0] = 0.0;  // Remove DC because heart rate is always a positive value
  }

  free(cfg);

  free(kiss_fftbuf);

  for(i=0; i<fft_outputbufsize; i++)
  {
    buf2[i] /= samplefreq;

#ifdef CHECK_POWERSPECTRUM
    power2 += buf2[i];
#endif

    buf3[i] = sqrt(buf2[i] * freqstep);

    if(buf2[i] <= SPECT_LOG_MINIMUM)
    {
      buf4[i] = log10(SPECT_LOG_MINIMUM);
    }
    else
    {
      buf4[i] = log10(buf2[i]);
    }

    if(buf3[i] <= SPECT_LOG_MINIMUM)
    {
      buf5[i] = log10(SPECT_LOG_MINIMUM);
    }
    else
    {
      buf5[i] = log10(buf3[i]);
    }

    if(i)  // don't use the dc-bin for the autogain of the screen
    {
      if(buf2[i] > maxvalue)
      {
        maxvalue = buf2[i];
      }

      if(buf3[i] > maxvalue_sqrt)
      {
        maxvalue_sqrt = buf3[i];
      }

      if(buf4[i] > maxvalue_vlog)
      {
        maxvalue_vlog = buf4[i];
      }

      if(buf5[i] > maxvalue_sqrt_vlog)
      {
        maxvalue_sqrt_vlog = buf5[i];
      }

      if((buf4[i] < minvalue_vlog) && (buf4[i] >= SPECT_LOG_MINIMUM_LOG))
      {
        minvalue_vlog = buf4[i];
      }

      if((buf5[i] < minvalue_sqrt_vlog) && (buf5[i] >= SPECT_LOG_MINIMUM_LOG))
      {
        minvalue_sqrt_vlog = buf5[i];
      }
    }
  }

  if(minvalue_vlog < SPECT_LOG_MINIMUM_LOG)
    minvalue_vlog = SPECT_LOG_MINIMUM_LOG;

  if(minvalue_sqrt_vlog < SPECT_LOG_MINIMUM_LOG)
    minvalue_sqrt_vlog = SPECT_LOG_MINIMUM_LOG;

  if(samplesleft)
  {
    dftblocks++;
  }

#ifdef CHECK_POWERSPECTRUM
  power1 /= samples;
  power2 *= freqstep;

  printf("\n power1 is %f\n power2 is %f\n\n", power1, power2);
#endif

  if(buf1 != NULL)
  {
    free(buf1);

    buf1 = NULL;
  }

  sprintf(str, "FFT resolution: %f Hz   %i blocks of %i samples", freqstep, dftblocks, dftblocksize);

  remove_trailing_zeros(str);

  curve1->setUpperLabel1(str);

  curve1->setUpperLabel2(signallabel);

  sliderMoved(0);

  curve1->setUpdatesEnabled(true);

  busy = 0;
}
コード例 #2
0
void UI_AveragerWindow::process_avg(struct signalcompblock *signalcomp)
{
  int j, k;

  char *viewbuf;

  long long s, s2;

  double dig_value=0.0,
         f_tmp=0.0;

  union {
          unsigned int one;
          signed int one_signed;
          unsigned short two[2];
          signed short two_signed[2];
          unsigned char four[4];
        } var;

  viewbuf = mainwindow->viewbuf;

  if(viewbuf == NULL)
  {
    return;
  }

  if(avgbuf == NULL)
  {
    return;
  }

  for(s=signalcomp->sample_start; s<signalcomp->samples_on_screen; s++)
  {
    if(s>signalcomp->sample_stop)  break;

    dig_value = 0.0;
    s2 = s + signalcomp->sample_timeoffset - signalcomp->sample_start;

    for(j=0; j<signalcomp->num_of_signals; j++)
    {
      if(signalcomp->edfhdr->bdf)
      {
        var.two[0] = *((unsigned short *)(
          viewbuf
          + signalcomp->viewbufoffset
          + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record))
          + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset
          + ((s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record) * 3)));

        var.four[2] = *((unsigned char *)(
          viewbuf
          + signalcomp->viewbufoffset
          + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record))
          + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset
          + ((s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record) * 3)
          + 2));

        if(var.four[2]&0x80)
        {
          var.four[3] = 0xff;
        }
        else
        {
          var.four[3] = 0x00;
        }

        f_tmp = var.one_signed;
      }

      if(signalcomp->edfhdr->edf)
      {
        f_tmp = *(((short *)(
          viewbuf
          + signalcomp->viewbufoffset
          + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record))
          + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset))
          + (s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record));
      }

      f_tmp += signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].offset;
      f_tmp *= signalcomp->factor[j];

      dig_value += f_tmp;
    }

    if(signalcomp->spike_filter)
    {
      if(s==signalcomp->sample_start)
      {
        spike_filter_restore_buf(signalcomp->spike_filter);
      }

      dig_value = run_spike_filter(dig_value, signalcomp->spike_filter);
    }

    for(k=0; k<signalcomp->filter_cnt; k++)
    {
      dig_value = first_order_filter(dig_value, signalcomp->filter[k]);
    }

    for(k=0; k<signalcomp->ravg_filter_cnt; k++)
    {
      if(s==signalcomp->sample_start)
      {
        ravg_filter_restore_buf(signalcomp->ravg_filter[k]);
      }

      dig_value = run_ravg_filter(dig_value, signalcomp->ravg_filter[k]);
    }

    for(k=0; k<signalcomp->fidfilter_cnt; k++)
    {
      if(s==signalcomp->sample_start)
      {
        memcpy(signalcomp->fidbuf[k], signalcomp->fidbuf2[k], fid_run_bufsize(signalcomp->fid_run[k]));
      }

      dig_value = signalcomp->fidfuncp[k](signalcomp->fidbuf[k], dig_value);
    }

    if(signalcomp->ecg_filter != NULL)
    {
      if(s==signalcomp->sample_start)
      {
        ecg_filter_restore_buf(signalcomp->ecg_filter);
      }

      dig_value = run_ecg_filter(dig_value, signalcomp->ecg_filter);
    }

    avgbuf[s] += (dig_value * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue);
  }
}
コード例 #3
0
void print_screen_to_edf(UI_Mainwindow *mainwindow)
{
  int i, j, k, p,
      n=0,
      records,
      records_written,
      signalcomps,
      duration_factor[MAXFILES],
      temp=0,
      edfplus=0,
      tallen,
      annotationlist_nr=0,
      annotations_left=1,
      add_one_sec=0,
      annot_smp_per_record=16,
      type,
      len;

  long long duration,
            smpls_written[MAXSIGNALS],
            s2,
            preamble=0LL,
            smpls_preamble[MAXSIGNALS],
            taltime=0LL,
            l_temp,
            referencetime,
            annot_difftime=0LL;

  char path[MAX_PATH_LENGTH],
       scratchpad[512],
       datrecduration[8],
       *viewbuf;

  double frequency,
         frequency2,
         dig_value;

  FILE *outputfile;


  struct signalcompblock **signalcomp;

  union {
          signed int one_signed;
          signed short two_signed[2];
          unsigned char four[4];
        } wr_var;

  union {
          signed short one_signed;
          unsigned char two[2];
        } null_bytes[MAXSIGNALS];

struct annotationblock *annotations_pntr;

struct date_time_struct date_time;

/////////////////////////////////////////////////////////////////////////

  signalcomps = mainwindow->signalcomps;
  signalcomp = mainwindow->signalcomp;
  viewbuf = mainwindow->viewbuf;

  annotations_pntr = mainwindow->annotationlist[0];

  if((!mainwindow->files_open)||(!signalcomps))
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Print to EDF", "Put a signal on the screen and try again.");
    messagewindow.exec();
    return;
  }

  for(i=0; i<mainwindow->files_open; i++)
  {
    if(mainwindow->edfheaderlist[i]->bdf)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Print to EDF", "BDF files can not be printed to EDF.");
      messagewindow.exec();
      return;
    }

    if(mainwindow->edfheaderlist[i]->discontinuous)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Print to EDF", "Sorry, discontinues EDF files can not be printed to EDF.");
      messagewindow.exec();
      return;
    }

    if(mainwindow->edfheaderlist[i]->edfplus)
    {
      edfplus = 1;

      for(j=0; j<mainwindow->edfheaderlist[i]->nr_annot_chns; j++)
      {
        if(mainwindow->edfheaderlist[i]->edfparam[mainwindow->edfheaderlist[i]->annot_ch[j]].smp_per_record>annot_smp_per_record)
        {
          annot_smp_per_record = mainwindow->edfheaderlist[i]->edfparam[mainwindow->edfheaderlist[i]->annot_ch[j]].smp_per_record;
        }
      }
    }
  }

  annot_smp_per_record += 16;

  taltime = mainwindow->edfheaderlist[mainwindow->sel_viewtime]->starttime_offset;

  duration = 0;

  for(i=0; i<signalcomps; i++)
  {
    if(signalcomp[i]->edfhdr->long_data_record_duration>duration)
    {
      duration = signalcomp[i]->edfhdr->long_data_record_duration;
      n = i;
    }
  }

  fseeko(signalcomp[n]->edfhdr->file_hdl, 244LL, SEEK_SET);
  if(fread(datrecduration, 8, 1, signalcomp[n]->edfhdr->file_hdl)!=1)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile.");
    messagewindow.exec();
    return;
  }

  temp = 0;

  for(i=0; i<signalcomps; i++)
  {
    if(duration % signalcomp[i]->edfhdr->long_data_record_duration)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "This combination of files can not be printed to EDF\n"
                                                                "because the quotient of the datarecordblock durations is not an integer.");
      messagewindow.exec();
      return;
    }

    duration_factor[signalcomp[i]->filenum] = duration / signalcomp[i]->edfhdr->long_data_record_duration;

    temp += signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record;
  }

  path[0] = 0;
  if(mainwindow->recent_savedir[0]!=0)
  {
    strcpy(path, mainwindow->recent_savedir);
    strcat(path, "/");
  }
  len = strlen(path);
  get_filename_from_path(path + len, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename, MAX_PATH_LENGTH - len);
  remove_extension_from_filename(path);
  strcat(path, "_screenprint.edf");

  strcpy(path, QFileDialog::getSaveFileName(0, "Print to EDF", QString::fromLocal8Bit(path), "EDF files (*.edf *.EDF)").toLocal8Bit().data());

  if(!strcmp(path, ""))
  {
    return;
  }

  get_directory_from_path(mainwindow->recent_savedir, path, MAX_PATH_LENGTH);

  if(mainwindow->file_is_opened(path))
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, selected file is in use.");
    messagewindow.exec();
    return;
  }

  outputfile = fopeno(path, "wb");
  if(outputfile==NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not create a file for writing.");
    messagewindow.exec();
    return;
  }

  referencetime = mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime;

  if(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime<0)
  {
    if((-mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime) % TIME_DIMENSION)
    {
      preamble = TIME_DIMENSION - ((-mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime) % TIME_DIMENSION);

      referencetime--;

      add_one_sec = 1;
    }
  }
  else
  {
    preamble = mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime % TIME_DIMENSION;

    if(preamble)  add_one_sec = 1;
  }

  for(i=0; i<signalcomps; i++)
  {
    smpls_preamble[i] = preamble / (signalcomp[i]->edfhdr->long_data_record_duration / signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record);
  }

  referencetime += (mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime / TIME_DIMENSION);

  utc_to_date_time(referencetime, &date_time);

/************************* write EDF-header ***************************************/

  rewind(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl);

  rewind(outputfile);

  if(edfplus)
  {
    if(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->edfplus)
    {
      if(fread(scratchpad, 88, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1)
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile.");
        messagewindow.exec();
        fclose(outputfile);
        return;
      }

      if(fwrite(scratchpad, 88, 1, outputfile)!=1)
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
        messagewindow.exec();
        fclose(outputfile);
        return;
      }
    }
    else
    {
      fprintf(outputfile, "0       X X X X ");

      if(fread(scratchpad, 88, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1)
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile.");
        messagewindow.exec();
        fclose(outputfile);
        return;
      }

      if(fwrite(scratchpad + 8, 72, 1, outputfile)!=1)
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
        messagewindow.exec();
        fclose(outputfile);
        return;
      }
    }

    fprintf(outputfile, "Startdate %02i-", date_time.day);

    switch(date_time.month)
    {
      case  1 : fprintf(outputfile, "JAN");
                break;
      case  2 : fprintf(outputfile, "FEB");
                break;
      case  3 : fprintf(outputfile, "MAR");
                break;
      case  4 : fprintf(outputfile, "APR");
                break;
      case  5 : fprintf(outputfile, "MAY");
                break;
      case  6 : fprintf(outputfile, "JUN");
                break;
      case  7 : fprintf(outputfile, "JUL");
                break;
      case  8 : fprintf(outputfile, "AUG");
                break;
      case  9 : fprintf(outputfile, "SEP");
                break;
      case 10 : fprintf(outputfile, "OCT");
                break;
      case 11 : fprintf(outputfile, "NOV");
                break;
      case 12 : fprintf(outputfile, "DEC");
                break;
      default : fprintf(outputfile, "ERR");
                break;
    }

    fprintf(outputfile, "-%04i ", date_time.year);

    if(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->edfplus)
    {
      if(fread(scratchpad, 80, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1)
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile.");
        messagewindow.exec();
        fclose(outputfile);
        return;
      }

      if(scratchpad[10]=='X')
      {
        if(fwrite(scratchpad + 12, 58, 1, outputfile)!=1)
        {
          QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
          messagewindow.exec();
          fclose(outputfile);
          return;
        }
      }
      else
      {
        if(fwrite(scratchpad + 22, 58, 1, outputfile)!=1)
        {
          QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
          messagewindow.exec();
          fclose(outputfile);
          return;
        }
      }
    }
    else
    {
      fprintf(outputfile, "X X X ");

      if(fread(scratchpad, 80, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1)
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile.");
        messagewindow.exec();
        fclose(outputfile);
        return;
      }

      if(fwrite(scratchpad + 28, 52, 1, outputfile)!=1)
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
        messagewindow.exec();
        fclose(outputfile);
        return;
      }
    }
  }
  else
  {
    if(fread(scratchpad, 168, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile.");
      messagewindow.exec();
      fclose(outputfile);
      return;
    }

    if(fwrite(scratchpad, 168, 1, outputfile)!=1)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
      messagewindow.exec();
      fclose(outputfile);
      return;
    }
  }

  fprintf(outputfile,
          "%02i.%02i.%02i%02i.%02i.%02i",
          date_time.day,
          date_time.month,
          date_time.year % 100,
          date_time.hour,
          date_time.minute,
          date_time.second);

  fprintf(outputfile, "%-8i", (signalcomps + edfplus) * 256 + 256);

  if(edfplus)
  {
    fprintf(outputfile, "EDF+C");

    for(i=0; i<39; i++)  fputc(' ', outputfile);
  }
  else  for(i=0; i<44; i++)  fputc(' ', outputfile);

  records = (int)(mainwindow->pagetime / duration);

  if(add_one_sec)
  {
    records += TIME_DIMENSION / duration;
  }

  fprintf(outputfile, "%-8i", records);

  if(fwrite(datrecduration, 8, 1, outputfile)!=1)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
    messagewindow.exec();
    fclose(outputfile);
    return;
  }

  fprintf(outputfile, "%-4i", signalcomps + edfplus);

  for(i=0; i<signalcomps; i++)
  {
    strcpy(scratchpad, signalcomp[i]->signallabel);
    strcat(scratchpad, "                ");
    if(fwrite(scratchpad, 16, 1, outputfile)!=1)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
      messagewindow.exec();
      fclose(outputfile);
      return;
    }
  }

  if(edfplus)
  {
    if(fwrite("EDF Annotations ", 16, 1, outputfile)!=1)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
      messagewindow.exec();
      fclose(outputfile);
      return;
    }
  }

  for(i=0; i<signalcomps; i++)
  {
    if(fwrite(signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].transducer, 80, 1, outputfile)!=1)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
      messagewindow.exec();
      fclose(outputfile);
      return;
    }
  }

  if(edfplus)
  {
    for(i=0; i<80; i++)  fputc(' ', outputfile);
  }

  for(i=0; i<signalcomps; i++)
  {
    strcpy(scratchpad, signalcomp[i]->physdimension);
    strcat(scratchpad, "        ");
    if(fwrite(scratchpad, 8, 1, outputfile)!=1)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
      messagewindow.exec();
      fclose(outputfile);
      return;
    }
  }

  if(edfplus)
  {
    for(i=0; i<8; i++)  fputc(' ', outputfile);
  }

  for(i=0; i<signalcomps; i++)
  {
    if((signalcomp[i]->ecg_filter == NULL) && (signalcomp[i]->zratio_filter == NULL))
    {
      fseeko(signalcomp[i]->edfhdr->file_hdl, (long long)((signalcomp[i]->edfsignal[0] * 8) + (104 * signalcomp[i]->edfhdr->edfsignals) + 256), SEEK_SET);
      if(fread(scratchpad, 8, 1, signalcomp[i]->edfhdr->file_hdl)!=1)
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile.");
        messagewindow.exec();
        fclose(outputfile);
        return;
      }
      if(fwrite(scratchpad, 8, 1, outputfile)!=1)
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
        messagewindow.exec();
        fclose(outputfile);
        return;
      }
    }

    if(signalcomp[i]->ecg_filter != NULL)
    {
      if(fwrite("0       ", 8, 1, outputfile)!=1)
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
        messagewindow.exec();
        fclose(outputfile);
        return;
      }
    }

    if(signalcomp[i]->zratio_filter != NULL)
    {
      if(fwrite("-1      ", 8, 1, outputfile)!=1)
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
        messagewindow.exec();
        fclose(outputfile);
        return;
      }
    }
  }

  if(edfplus)
  {
    if(fwrite("-1      ", 8, 1, outputfile)!=1)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
      messagewindow.exec();
      fclose(outputfile);
      return;
    }
  }

  for(i=0; i<signalcomps; i++)
  {
    if((signalcomp[i]->ecg_filter == NULL) && (signalcomp[i]->zratio_filter == NULL))
    {
      fseeko(signalcomp[i]->edfhdr->file_hdl, (long long)((signalcomp[i]->edfsignal[0] * 8) + (112 * signalcomp[i]->edfhdr->edfsignals) + 256), SEEK_SET);
      if(fread(scratchpad, 8, 1, signalcomp[i]->edfhdr->file_hdl)!=1)
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile.");
        messagewindow.exec();
        fclose(outputfile);
        return;
      }
      if(fwrite(scratchpad, 8, 1, outputfile)!=1)
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
        messagewindow.exec();
        fclose(outputfile);
        return;
      }
    }

    if(signalcomp[i]->ecg_filter != NULL)
    {
      if(fwrite("1000    ", 8, 1, outputfile)!=1)
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
        messagewindow.exec();
        fclose(outputfile);
        return;
      }
    }

    if(signalcomp[i]->zratio_filter != NULL)
    {
      if(fwrite("1       ", 8, 1, outputfile)!=1)
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
        messagewindow.exec();
        fclose(outputfile);
        return;
      }
    }
  }

  if(edfplus)
  {
    if(fwrite("1       ", 8, 1, outputfile)!=1)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
      messagewindow.exec();
      fclose(outputfile);
      return;
    }
  }

  for(i=0; i<signalcomps; i++)
  {
    if((signalcomp[i]->ecg_filter == NULL) && (signalcomp[i]->zratio_filter == NULL))
    {
      fprintf(outputfile, "%-8i", signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min);

      if(signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min<0)
      {
        null_bytes[i].one_signed = 0;
      }
      else
      {
        null_bytes[i].one_signed = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min;
      }
    }
    else
    {
      if(fwrite("-32768  ", 8, 1, outputfile)!=1)
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
        messagewindow.exec();
        fclose(outputfile);
        return;
      }

      null_bytes[i].one_signed = -32768;
    }
  }

  if(edfplus)
  {
    if(fwrite("-32768  ", 8, 1, outputfile)!=1)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
      messagewindow.exec();
      fclose(outputfile);
      return;
    }
  }

  for(i=0; i<signalcomps; i++)
  {
    if((signalcomp[i]->ecg_filter == NULL) && (signalcomp[i]->zratio_filter == NULL))
    {
      fprintf(outputfile, "%-8i", signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max);
    }
    else
    {
      if(fwrite("32767   ", 8, 1, outputfile)!=1)
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
        messagewindow.exec();
        fclose(outputfile);
        return;
      }
    }
  }

  if(edfplus)
  {
    if(fwrite("32767   ", 8, 1, outputfile)!=1)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
      messagewindow.exec();
      fclose(outputfile);
      return;
    }
  }

  for(i=0; i<signalcomps; i++)
  {
    strcpy(scratchpad, signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].prefilter);
    strcat(scratchpad, "                                                                                ");
    for(p = strlen(scratchpad) - 1; p>=0; p--)
    {
      if(scratchpad[p]!=' ')  break;
    }
    p++;
    if(p) p++;

    for(j=0; j<signalcomp[i]->filter_cnt; j++)
    {
      if(signalcomp[i]->filter[j]->is_LPF == 1)
      {
        p += sprintf(scratchpad + p, "LP:%f", signalcomp[i]->filter[j]->cutoff_frequency);
      }

      if(signalcomp[i]->filter[j]->is_LPF == 0)
      {
        p += sprintf(scratchpad + p, "HP:%f", signalcomp[i]->filter[j]->cutoff_frequency);
      }

      for(k=(p-1); k>0; k--)
      {
        if(scratchpad[k]!='0')  break;
      }

      if(scratchpad[k]=='.')  scratchpad[k] = 0;
      else  scratchpad[k+1] = 0;

      strcat(scratchpad, "Hz ");

      p = strlen(scratchpad);

      if(p>80)  break;
    }

    for(j=0; j<signalcomp[i]->fidfilter_cnt; j++)
    {
      type = signalcomp[i]->fidfilter_type[j];

      frequency = signalcomp[i]->fidfilter_freq[j];

      frequency2 = signalcomp[i]->fidfilter_freq2[j];

      if(type == 0)
      {
        p += sprintf(scratchpad + p, "HP:%f", frequency);
      }

      if(type == 1)
      {
        p += sprintf(scratchpad + p, "LP:%f", frequency);
      }

      if(type == 2)
      {
        p += sprintf(scratchpad + p, "N:%f", frequency);
      }

      if(type == 3)
      {
        p += sprintf(scratchpad + p, "BP:%f", frequency);
      }

      if(type == 4)
      {
        p += sprintf(scratchpad + p, "BS:%f", frequency);
      }

      for(k=(p-1); k>0; k--)
      {
        if(scratchpad[k]!='0')  break;
      }

      if(scratchpad[k]=='.')  scratchpad[k] = 0;
      else  scratchpad[k+1] = 0;

      p = strlen(scratchpad);

      if((type == 3) || (type == 4))
      {
        p += sprintf(scratchpad + p, "-%f", frequency2);

        for(k=(p-1); k>0; k--)
        {
          if(scratchpad[k]!='0')  break;
        }

        if(scratchpad[k]=='.')  scratchpad[k] = 0;
        else  scratchpad[k+1] = 0;
      }

      strcat(scratchpad, "Hz ");

      p = strlen(scratchpad);

      if(p>80)  break;
    }

    for(j=0; j<signalcomp[i]->ravg_filter_cnt; j++)
    {
      if(signalcomp[i]->ravg_filter_type[j] == 0)
      {
        p += sprintf(scratchpad + p, "HP:%iSmpls ", signalcomp[i]->ravg_filter[j]->size);
      }

      if(signalcomp[i]->ravg_filter_type[j] == 1)
      {
        p += sprintf(scratchpad + p, "LP:%iSmpls ", signalcomp[i]->ravg_filter[j]->size);
      }

      p = strlen(scratchpad);

      if(p>80)  break;
    }

    if(signalcomp[i]->ecg_filter != NULL)
    {
      p += sprintf(scratchpad + p, "ECG:HR ");
    }

    if(signalcomp[i]->zratio_filter != NULL)
    {
      p += sprintf(scratchpad + p, "Z-ratio ");
    }

    for(;p<81; p++)
    {
      scratchpad[p] = ' ';
    }

    if(fwrite(scratchpad, 80, 1, outputfile)!=1)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
      messagewindow.exec();
      fclose(outputfile);
      return;
    }
  }

  if(edfplus)
  {
    for(i=0; i<80; i++)  fputc(' ', outputfile);
  }

  for(i=0; i<signalcomps; i++)
  {
    fprintf(outputfile, "%-8i", signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record
     * duration_factor[signalcomp[i]->filenum]);
  }

  if(edfplus)
  {
    fprintf(outputfile, "%-8i", annot_smp_per_record);
  }

  for(i=0; i<signalcomps; i++)
  {
    for(j=0; j<32; j++)  fputc(' ', outputfile);
  }

  if(edfplus)
  {
    for(i=0; i<32; i++)  fputc(' ', outputfile);
  }

/////////////////////////////////////////////////////////////////////

  for(i=0; i<MAXSIGNALS; i++)  smpls_written[i] = 0;

  mainwindow->print_to_edf_active = 1;

  mainwindow->setup_viewbuf();

  viewbuf = mainwindow->viewbuf;

  if(viewbuf==NULL)
  {
    fclose(outputfile);
    return;
  }

  QApplication::setOverrideCursor(Qt::WaitCursor);

  for(records_written=0; records_written<records; records_written++)
  {
    qApp->processEvents();

    for(i=0; i<signalcomps; i++)
    {
      for(k=0; k<signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record * duration_factor[signalcomp[i]->filenum]; k++)
      {
        if(smpls_preamble[i])
        {
          smpls_preamble[i]--;

          fputc(null_bytes[i].two[0], outputfile);
          if(fputc(null_bytes[i].two[1], outputfile)==EOF)
          {
            QApplication::restoreOverrideCursor();
            QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
            messagewindow.exec();
            fclose(outputfile);
            return;
          }
        }
        else
        {
          dig_value = 0;

          s2 = smpls_written[i] + signalcomp[i]->sample_timeoffset - signalcomp[i]->sample_start;

          for(j=0; j<signalcomp[i]->num_of_signals; j++)
          {
            if((smpls_written[i]<signalcomp[i]->sample_stop)&&(s2>=0))
            {
              if(signalcomp[i]->edfhdr->edf)
              {
                temp = *(((short *)(
                  viewbuf
                  + signalcomp[i]->viewbufoffset
                  + (signalcomp[i]->edfhdr->recordsize * (s2 / signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record))
                  + signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].buf_offset))
                  + (s2 % signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record));
              }

              temp += signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].offset;
              temp *= signalcomp[i]->factor[j];

              temp -= signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].offset;
            }
            else
            {
              temp = 0;
            }

            dig_value += temp;
          }

          for(p=0; p<signalcomp[i]->filter_cnt; p++)
          {
            if(smpls_written[i]==signalcomp[i]->sample_start)
            {
              if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime==0)
              {
                reset_filter(dig_value, signalcomp[i]->filter[p]);
              }
              else
              {
                signalcomp[i]->filter[p]->old_input = signalcomp[i]->filterpreset_a[p];
                signalcomp[i]->filter[p]->old_output = signalcomp[i]->filterpreset_b[p];
              }
            }

            dig_value = first_order_filter(dig_value, signalcomp[i]->filter[p]);
          }

          for(p=0; p<signalcomp[i]->ravg_filter_cnt; p++)
          {
            if(smpls_written[i]==signalcomp[i]->sample_start)
            {
              if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime!=0)
              {
                ravg_filter_restore_buf(signalcomp[i]->ravg_filter[p]);
              }
            }

            dig_value = run_ravg_filter(dig_value, signalcomp[i]->ravg_filter[p]);
          }

          for(p=0; p<signalcomp[i]->fidfilter_cnt; p++)
          {
            if(smpls_written[i]==signalcomp[i]->sample_start)
            {
              if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime!=0)
              {
                memcpy(signalcomp[i]->fidbuf[p], signalcomp[i]->fidbuf2[p], fid_run_bufsize(signalcomp[i]->fid_run[p]));
              }
            }

            dig_value = signalcomp[i]->fidfuncp[p](signalcomp[i]->fidbuf[p], dig_value);
          }

          if(signalcomp[i]->ecg_filter != NULL)
          {
            if(smpls_written[i]==signalcomp[i]->sample_start)
            {
              if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime != 0)
              {
                ecg_filter_restore_buf(signalcomp[i]->ecg_filter);
              }
            }

            dig_value = run_ecg_filter(dig_value, signalcomp[i]->ecg_filter);

            dig_value = (dig_value * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue * 65.536) - 32768.0;
          }

          if(signalcomp[i]->zratio_filter != NULL)
          {
            if(smpls_written[i]==signalcomp[i]->sample_start)
            {
              if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime != 0)
              {
                zratio_filter_restore_buf(signalcomp[i]->zratio_filter);
              }
            }

            dig_value = run_zratio_filter(dig_value, signalcomp[i]->zratio_filter);

            dig_value = dig_value * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue * 32768.0;
          }

          if((smpls_written[i]>=signalcomp[i]->sample_start)&&(smpls_written[i]<signalcomp[i]->sample_stop))
          {
            wr_var.one_signed = dig_value;

            if((signalcomp[i]->ecg_filter == NULL) && (signalcomp[i]->zratio_filter == NULL))
            {
              if(wr_var.one_signed>signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max)
              {
                wr_var.one_signed = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max;
              }
              if(wr_var.one_signed<signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min)
              {
                wr_var.one_signed = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min;
              }
            }
            else
            {
              if(wr_var.one_signed > 32767)
              {
                wr_var.one_signed = 32767;
              }
              if(wr_var.one_signed < -32768)
              {
                wr_var.one_signed = -32768;
              }
            }

            fputc(wr_var.four[0], outputfile);
            if(fputc(wr_var.four[1], outputfile)==EOF)
            {
              QApplication::restoreOverrideCursor();
              QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
              messagewindow.exec();
              fclose(outputfile);
              return;
            }
          }
          else
          {
            fputc(null_bytes[i].two[0], outputfile);
            if(fputc(null_bytes[i].two[1], outputfile)==EOF)
            {
              QApplication::restoreOverrideCursor();
              QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile.");
              messagewindow.exec();
              fclose(outputfile);
              return;
            }
          }

          smpls_written[i]++;
        }
      }
    }

    if(edfplus)
    {
      tallen = fprintf(outputfile, "+%i.%07i",
      (int)(taltime / TIME_DIMENSION),
      (int)(taltime % TIME_DIMENSION));

      fputc(20, outputfile);
      fputc(20, outputfile);
      fputc(0, outputfile);

      tallen += 3;

      if(annotations_left)
      {
        if(mainwindow->viewtime_sync==VIEWTIME_SYNCED_ABSOLUT)
        {
          annot_difftime = (referencetime - mainwindow->edfheaderlist[annotationlist_nr]->utc_starttime) * TIME_DIMENSION;
        }

        if(mainwindow->viewtime_sync==VIEWTIME_SYNCED_OFFSET)
        {
          annot_difftime = (referencetime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime) * TIME_DIMENSION;
        }

        if((mainwindow->viewtime_sync==VIEWTIME_UNSYNCED) || (mainwindow->viewtime_sync==VIEWTIME_USER_DEF_SYNCED))
        {
          annot_difftime = (referencetime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime) * TIME_DIMENSION;
          annot_difftime += (mainwindow->edfheaderlist[annotationlist_nr]->viewtime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime);
        }

        if(annotationlist_nr != mainwindow->sel_viewtime)
        {
          annot_difftime -= mainwindow->edfheaderlist[mainwindow->sel_viewtime]->starttime_offset;
          annot_difftime += mainwindow->edfheaderlist[annotationlist_nr]->starttime_offset;
        }
      }

      while(annotations_left)
      {
        while(!annotations_pntr)
        {
          annotationlist_nr++;
          if(annotationlist_nr>=mainwindow->files_open)
          {
            annotations_left = 0;
            annotations_pntr = NULL;

            break;
          }
          annotations_pntr = mainwindow->annotationlist[annotationlist_nr];

          if(mainwindow->viewtime_sync==VIEWTIME_SYNCED_ABSOLUT)
          {
            annot_difftime = (referencetime - mainwindow->edfheaderlist[annotationlist_nr]->utc_starttime) * TIME_DIMENSION;
          }

          if(mainwindow->viewtime_sync==VIEWTIME_SYNCED_OFFSET)
          {
            annot_difftime = (referencetime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime) * TIME_DIMENSION;
          }

          if((mainwindow->viewtime_sync==VIEWTIME_UNSYNCED) || (mainwindow->viewtime_sync==VIEWTIME_USER_DEF_SYNCED))
          {
            annot_difftime = (referencetime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime) * TIME_DIMENSION;
            annot_difftime += (mainwindow->edfheaderlist[annotationlist_nr]->viewtime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime);
          }

          if(annotationlist_nr != mainwindow->sel_viewtime)
          {
            annot_difftime -= mainwindow->edfheaderlist[mainwindow->sel_viewtime]->starttime_offset;
            annot_difftime += mainwindow->edfheaderlist[annotationlist_nr]->starttime_offset;
          }
        }

        if(!annotations_left)  break;

        if(annotations_pntr)
        {
          l_temp = annotations_pntr->onset - annot_difftime;

          if((l_temp >= 0LL) && (l_temp < (mainwindow->pagetime + TIME_DIMENSION)))
          {
            tallen += fprintf(outputfile, "%+i.%07i",
            (int)(l_temp / TIME_DIMENSION),
            (int)(l_temp % TIME_DIMENSION));

            if(annotations_pntr->duration[0]!=0)
            {
              fputc(21, outputfile);
              tallen++;

              tallen += fprintf(outputfile, "%s", annotations_pntr->duration);
            }

            fputc(20, outputfile);
            tallen++;

            tallen += fprintf(outputfile, "%s", annotations_pntr->annotation);

            fputc(20, outputfile);
            fputc(0, outputfile);
            tallen += 2;

            annotations_pntr = annotations_pntr->next_annotation;

            break;
          }
          else
          {
            annotations_pntr = annotations_pntr->next_annotation;

            continue;
          }
        }
      }

      for(j=tallen; j<(annot_smp_per_record * 2); j++)
      {
        fputc(0, outputfile);
      }

      taltime += duration;
    }
  }

  QApplication::restoreOverrideCursor();

  fclose(outputfile);
}
コード例 #4
0
void UI_SpectrumDockWindow::update_curve()
{
  int i, j, k, n,
      dftblocksize,
      dftblocks,
      samplesleft,
      fft_outputbufsize;

  long long s, s2;

  char str[512];

  double dig_value=0.0,
         f_tmp=0.0;

  union {
          unsigned int one;
          signed int one_signed;
          unsigned short two[2];
          signed short two_signed[2];
          unsigned char four[4];
        } var;

  if(signalcomp == NULL)
  {
    return;
  }

  if(busy)
  {
    return;
  }

  viewbuf = mainwindow->viewbuf;

  if(viewbuf == NULL)
  {
    return;
  }

  busy = 1;

  curve1->setUpdatesEnabled(false);

  samples = signalcomp->samples_on_screen;

  if(signalcomp->samples_on_screen > signalcomp->sample_stop)
  {
    samples = signalcomp->sample_stop;
  }

  samples -= signalcomp->sample_start;

  if((samples < 10) || (viewbuf == NULL))
  {
    curve1->setUpdatesEnabled(true);

    busy = 0;

    if(spectrum_color != NULL)
    {
      for(i=0; i < spectrum_color->items; i++)
      {
        spectrum_color->value[i] = 0.0;
      }
    }

    curve1->clear();

    return;
  }

  if(buf1 != NULL)
  {
    free(buf1);
  }
  buf1 = (double *)malloc(sizeof(double) * signalcomp->samples_on_screen);
  if(buf1 == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action.\n"
                                  "Decrease the timescale and try again.");
    messagewindow.exec();
    return;
  }

  samples = 0;

  for(s=signalcomp->sample_start; s<signalcomp->samples_on_screen; s++)
  {
    if(s>signalcomp->sample_stop)  break;

    dig_value = 0.0;
    s2 = s + signalcomp->sample_timeoffset - signalcomp->sample_start;

    for(j=0; j<signalcomp->num_of_signals; j++)
    {
      if(signalcomp->edfhdr->bdf)
      {
        var.two[0] = *((unsigned short *)(
          viewbuf
          + signalcomp->viewbufoffset
          + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record))
          + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset
          + ((s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record) * 3)));

        var.four[2] = *((unsigned char *)(
          viewbuf
          + signalcomp->viewbufoffset
          + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record))
          + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset
          + ((s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record) * 3)
          + 2));

        if(var.four[2]&0x80)
        {
          var.four[3] = 0xff;
        }
        else
        {
          var.four[3] = 0x00;
        }

        f_tmp = var.one_signed;
      }

      if(signalcomp->edfhdr->edf)
      {
        f_tmp = *(((short *)(
          viewbuf
          + signalcomp->viewbufoffset
          + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record))
          + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset))
          + (s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record));
      }

      f_tmp += signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].offset;
      f_tmp *= signalcomp->factor[j];

      dig_value += f_tmp;
    }

    if(signalcomp->spike_filter)
    {
      if(s==signalcomp->sample_start)
      {
        spike_filter_restore_buf(signalcomp->spike_filter);
      }

      dig_value = run_spike_filter(dig_value, signalcomp->spike_filter);
    }

    for(k=0; k<signalcomp->filter_cnt; k++)
    {
      dig_value = first_order_filter(dig_value, signalcomp->filter[k]);
    }

    for(k=0; k<signalcomp->ravg_filter_cnt; k++)
    {
      if(s==signalcomp->sample_start)
      {
        ravg_filter_restore_buf(signalcomp->ravg_filter[k]);
      }

      dig_value = run_ravg_filter(dig_value, signalcomp->ravg_filter[k]);
    }

    for(k=0; k<signalcomp->fidfilter_cnt; k++)
    {
      if(s==signalcomp->sample_start)
      {
        memcpy(signalcomp->fidbuf[k], signalcomp->fidbuf2[k], fid_run_bufsize(signalcomp->fid_run[k]));
      }

      dig_value = signalcomp->fidfuncp[k](signalcomp->fidbuf[k], dig_value);
    }

    if(signalcomp->ecg_filter != NULL)
    {
      if(s==signalcomp->sample_start)
      {
        ecg_filter_restore_buf(signalcomp->ecg_filter);
      }

      dig_value = run_ecg_filter(dig_value, signalcomp->ecg_filter);
    }

    if(s>=signalcomp->sample_start)
    {
      buf1[samples++] = dig_value * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue;
    }
  }

  samplefreq = (double)signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record / ((double)signalcomp->edfhdr->long_data_record_duration / TIME_DIMENSION);

  dftblocksize = mainwindow->maxdftblocksize;

  if(dftblocksize & 1)
  {
    dftblocksize--;
  }

  dftblocks = 1;

  if(dftblocksize < samples)
  {
    dftblocks = samples / dftblocksize;
  }
  else
  {
    dftblocksize = samples;
  }

  if(dftblocksize & 1)
  {
    dftblocksize--;
  }

  samplesleft = samples % dftblocksize;

  if(samplesleft & 1)
  {
    samplesleft--;
  }

  freqstep = samplefreq / (double)dftblocksize;

  fft_outputbufsize = dftblocksize / 2;

  steps = fft_outputbufsize;

  if(buf2 != NULL)
  {
    free(buf2);
  }
  buf2 = (double *)calloc(1, sizeof(double) * fft_outputbufsize);
  if(buf2 == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action.");
    messagewindow.exec();
    free(buf1);
    buf1 = NULL;
    return;
  }

  if(buf3 != NULL)
  {
    free(buf3);
  }
  buf3 = (double *)malloc(sizeof(double) * fft_outputbufsize);
  if(buf3 == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action.");
    messagewindow.exec();
    free(buf1);
    free(buf2);
    buf1 = NULL;
    buf2 = NULL;
    return;
  }

  if(buf4 != NULL)
  {
    free(buf4);
  }
  buf4 = (double *)malloc(sizeof(double) * fft_outputbufsize);
  if(buf4 == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action.");
    messagewindow.exec();
    free(buf1);
    free(buf2);
    free(buf3);
    buf1 = NULL;
    buf2 = NULL;
    buf3 = NULL;
    return;
  }

  if(buf5 != NULL)
  {
    free(buf5);
  }
  buf5 = (double *)malloc(sizeof(double) * fft_outputbufsize);
  if(buf5 == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action.");
    messagewindow.exec();
    free(buf1);
    free(buf2);
    free(buf3);
    free(buf4);
    buf1 = NULL;
    buf2 = NULL;
    buf3 = NULL;
    buf4 = NULL;
    return;
  }

  if(init_maxvalue && !set_settings)
  {
    maxvalue = 0.000001;
    maxvalue_sqrt = 0.000001;
    maxvalue_vlog = 0.000001;
    maxvalue_sqrt_vlog = 0.000001;
    minvalue_vlog = 0.0;
    minvalue_sqrt_vlog = 0.0;
  }

  if(set_settings)
  {
    maxvalue = settings.maxvalue;
    maxvalue_sqrt = settings.maxvalue_sqrt;
    maxvalue_vlog = settings.maxvalue_vlog;
    maxvalue_sqrt_vlog = settings.maxvalue_sqrt_vlog;
    minvalue_vlog = settings.minvalue_vlog;
    minvalue_sqrt_vlog = settings.minvalue_sqrt_vlog;
  }

  kiss_fftr_cfg cfg;

  kiss_fft_cpx *kiss_fftbuf;

  kiss_fftbuf = (kiss_fft_cpx *)malloc((fft_outputbufsize + 1) * sizeof(kiss_fft_cpx));
  if(kiss_fftbuf == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action.");
    messagewindow.exec();
    free(buf1);
    free(buf2);
    free(buf3);
    free(buf4);
    free(buf5);
    buf1 = NULL;
    buf2 = NULL;
    buf3 = NULL;
    buf4 = NULL;
    buf5 = NULL;
    return;
  }

  cfg = kiss_fftr_alloc(dftblocksize, 0, NULL, NULL);

  for(j=0; j<dftblocks; j++)
  {
    kiss_fftr(cfg, buf1 + (j * dftblocksize), kiss_fftbuf);

    for(i=0; i<fft_outputbufsize; i++)
    {
      buf2[i] += (((kiss_fftbuf[i].r * kiss_fftbuf[i].r) + (kiss_fftbuf[i].i * kiss_fftbuf[i].i)) / fft_outputbufsize);
    }
  }

  if(samplesleft)
  {
    kiss_fftr(cfg, buf1 + (((j-1) * dftblocksize) + samplesleft), kiss_fftbuf);

    for(i=0; i<fft_outputbufsize; i++)
    {
      buf2[i] += (((kiss_fftbuf[i].r * kiss_fftbuf[i].r) + (kiss_fftbuf[i].i * kiss_fftbuf[i].i)) / fft_outputbufsize);

      buf2[i] /= (dftblocks + 1);
    }
  }
  else
  {
    for(i=0; i<fft_outputbufsize; i++)
    {
      buf2[i] /= dftblocks;
    }
  }

  if(signalcomp->ecg_filter == NULL)
  {
    buf2[0] /= 2.0;  // DC!
  }
  else
  {
    buf2[0] = 0.0;  // Remove DC because heart rate is always a positive value
  }

  free(cfg);

  free(kiss_fftbuf);

  for(i=0; i<fft_outputbufsize; i++)
  {
    buf2[i] /= samplefreq;

    buf3[i] = sqrt(buf2[i] * freqstep);

    if(buf2[i] <= SPECT_LOG_MINIMUM)
    {
      buf4[i] = log10(SPECT_LOG_MINIMUM);
    }
    else
    {
      buf4[i] = log10(buf2[i]);
    }

    if(buf3[i] <= SPECT_LOG_MINIMUM)
    {
      buf5[i] = log10(SPECT_LOG_MINIMUM);
    }
    else
    {
      buf5[i] = log10(buf3[i]);
    }

    if(init_maxvalue && !set_settings)
    {
      if(i)  // don't use the dc-bin for the autogain of the screen
      {
        if(buf2[i] > maxvalue)
        {
          maxvalue = buf2[i];
        }

        if(buf3[i] > maxvalue_sqrt)
        {
          maxvalue_sqrt = buf3[i];
        }

        if(buf4[i] > maxvalue_vlog)
        {
          maxvalue_vlog = buf4[i];
        }

        if(buf5[i] > maxvalue_sqrt_vlog)
        {
          maxvalue_sqrt_vlog = buf5[i];
        }

        if((buf4[i] < minvalue_vlog) && (buf4[i] >= SPECT_LOG_MINIMUM_LOG))
        {
          minvalue_vlog = buf4[i];
        }

        if((buf5[i] < minvalue_sqrt_vlog) && (buf5[i] >= SPECT_LOG_MINIMUM_LOG))
        {
          minvalue_sqrt_vlog = buf5[i];
        }
      }
    }
  }

  if(init_maxvalue)
  {
    if(minvalue_vlog < SPECT_LOG_MINIMUM_LOG)
      minvalue_vlog = SPECT_LOG_MINIMUM_LOG;

    if(minvalue_sqrt_vlog < SPECT_LOG_MINIMUM_LOG)
      minvalue_sqrt_vlog = SPECT_LOG_MINIMUM_LOG;
  }

  if(samplesleft)
  {
    dftblocks++;
  }

  if(buf1 != NULL)
  {
    free(buf1);

    buf1 = NULL;
  }

  sprintf(str, "FFT resolution: %f Hz   %i blocks of %i samples", freqstep, dftblocks, dftblocksize);

  remove_trailing_zeros(str);

  curve1->setUpperLabel1(str);

  curve1->setUpperLabel2(signallabel);

  if(spectrum_color != NULL)
  {
    if(spectrum_color->items > 0)
    {
      spectrum_color->value[0] = 0.0;

      n = 0;

      for(j=0; j<steps; j++)
      {
        if(((freqstep * j) + (freqstep * 0.5)) < spectrum_color->freq[0])
        {
          if(spectrum_color->method == 0)  // sum
          {
            spectrum_color->value[0] += buf2[j];
          }

          if(spectrum_color->method == 1)  // peak
          {
            if(spectrum_color->value[0] < buf2[j])
            {
              spectrum_color->value[0] = buf2[j];
            }
          }

          if(spectrum_color->method == 2)  // average
          {
            spectrum_color->value[0] += buf2[j];

            n++;
          }
        }
      }

      if(spectrum_color->method == 2)  // average
      {
        if(n)
        {
          spectrum_color->value[0] /= n;
        }
      }
    }

    for(i=1; i < spectrum_color->items; i++)
    {
      spectrum_color->value[i] = 0.0;

      n = 0;

      for(j=0; j<steps; j++)
      {
        if((((freqstep * j) + (freqstep * 0.5)) > spectrum_color->freq[i-1]) && (((freqstep * j) + (freqstep * 0.5)) < spectrum_color->freq[i]))
        {
          if(spectrum_color->method == 0)  // sum
          {
            spectrum_color->value[i] += buf2[j];
          }

          if(spectrum_color->method == 1)  // peak
          {
            if(spectrum_color->value[i] < buf2[j])
            {
              spectrum_color->value[i] = buf2[j];
            }
          }

          if(spectrum_color->method == 2)  // average
          {
            spectrum_color->value[i] += buf2[j];

            n++;
          }
        }
      }

      if(spectrum_color->method == 2)  // average
      {
        if(n)
        {
          spectrum_color->value[i] /= n;
        }
      }
    }
  }

  if(mainwindow->spectrumdock_sqrt)
  {
    snprintf(str, 512, "Amplitude Spectrum %s", signallabel);
  }
  else
  {
    snprintf(str, 512, "Power Spectrum %s", signallabel);
  }

  dock->setWindowTitle(str);

  if(set_settings)
  {
    set_settings = 0;

    if((settings.amp >= 1) && (settings.amp <= 2000))
    {
      amplitudeSlider->setValue(settings.amp);
    }

    if((settings.log_min_sl >= 1) && (settings.log_min_sl <= 2000))
    {
      log_minslider->setValue(settings.log_min_sl);
    }

    if((settings.span >= 10) && (settings.span <= 1000))
    {
      spanSlider->setValue(settings.span);
    }

    if((settings.center >= 0) && (settings.center <= 1000))
    {
      centerSlider->setValue(settings.center);
    }

    if(settings.sqrt > 0)
    {
      sqrtButton->setChecked(true);
    }
    else
    {
      sqrtButton->setChecked(false);
    }

    if(settings.log > 0)
    {
      vlogButton->setChecked(true);

      log_minslider->setVisible(true);
    }
    else
    {
      vlogButton->setChecked(false);

      log_minslider->setVisible(false);
    }

    if(settings.colorbar > 0)
    {
      colorBarButton->setChecked(true);
    }
    else
    {
      colorBarButton->setChecked(false);
    }

    if((flywheel_value >= 10) && (flywheel_value <= 100000))
    {
      flywheel_value = settings.wheel;
    }
  }

  sliderMoved(0);

  curve1->setUpdatesEnabled(true);

  busy = 0;

  init_maxvalue = 0;
}