void UI_BIOSEMI2BDFPLUSwindow::SelectFileButton()
{
  int i, j, k,
      error,
      hdl_in,
      hdl_out,
      edfsignals,
      status_signal=0,
      status_samples_in_datarecord=0,
      rising_edge,
      set_duration,
      status[24],
      totalSamplesInDatarecord,
      *buf,
      buf_offset[EDFLIB_MAXSIGNALS],
      sf,
      new_sf,
      samplerate_divider;

  char str[2048],
       triggerlabel[24][64],
       outputfilename[MAX_PATH_LENGTH];

  long long datarecords,
            status_sample_duration,
            trigger_cnt,
            progress_steps;

  struct edf_hdr_struct hdr;

  struct annotationblock *annotlist=NULL;

  struct annotationblock *annotation;


  for(i=0; i<16; i++)
  {
    if(!lineEdit1[i]->text().length())
    {
      sprintf(str, "Trigger Input label %i is empty!", i + 1);
      QMessageBox messagewindow(QMessageBox::Critical, "Error", str);
      messagewindow.exec();
      return;
    }
  }

  for(i=0; i<16; i++)
  {
    for(j=0; j<16; j++)
    {
      if(i != j)
      {
        if(!strcmp(lineEdit1[i]->text().toLocal8Bit().data(), lineEdit1[j]->text().toLocal8Bit().data()))
        {
          sprintf(str, "Trigger Input labels %i and %i are the same!", i + 1, j + 1);
          QMessageBox messagewindow(QMessageBox::Critical, "Error", str);
          messagewindow.exec();
          return;
        }
      }
    }
  }

  str[0] = 0;

  strcpy(inputpath, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "BDF files (*.bdf *.BDF)").toLocal8Bit().data());

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

  get_directory_from_path(recent_opendir, inputpath, MAX_PATH_LENGTH);

  error = edfopen_file_readonly(inputpath, &hdr, EDFLIB_DO_NOT_READ_ANNOTATIONS);

  if(error < 0)
  {
    error = hdr.filetype;

    switch(error)
    {
      case EDFLIB_MALLOC_ERROR                : strcpy(str, "EDFlib: malloc error.");
                                                break;
      case EDFLIB_NO_SUCH_FILE_OR_DIRECTORY   : strcpy(str, "EDFlib: no such file or directory.");
                                                break;
      case EDFLIB_FILE_CONTAINS_FORMAT_ERRORS : strcpy(str, "EDFlib: file contains format errors.\nOpen the file in EDFbrowser to get more info.");
                                                break;
      case EDFLIB_MAXFILES_REACHED            : strcpy(str, "EDFlib: maximum amount of files reached.");
                                                break;
      case EDFLIB_FILE_READ_ERROR             : strcpy(str, "EDFlib: a file read error occurred.");
                                                break;
      case EDFLIB_FILE_ALREADY_OPENED         : strcpy(str, "EDFlib: file is already opened.");
                                                break;
      case EDFLIB_FILETYPE_ERROR              : strcpy(str, "EDFlib: filetype error.");
                                                break;
      case EDFLIB_FILE_WRITE_ERROR            : strcpy(str, "EDFlib: file write error.");
                                                break;
      case EDFLIB_NUMBER_OF_SIGNALS_INVALID   : strcpy(str, "EDFlib: invalid number of signals.");
                                                break;
      case EDFLIB_FILE_IS_DISCONTINUOUS       : strcpy(str, "EDFlib: file is discontinuous.");
                                                break;
      case EDFLIB_INVALID_READ_ANNOTS_VALUE   : strcpy(str, "EDFlib: invalid read annotations argument.");
                                                break;
      default                                 : strcpy(str, "EDFlib: unknown error.");
    }

    QMessageBox messagewindow(QMessageBox::Critical, "Error", str);
    messagewindow.exec();

    return;
  }

  hdl_in = hdr.handle;

/////////////////// check file /////////////////////////////////////////////

  if(hdr.filetype == EDFLIB_FILETYPE_BDFPLUS)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Selected file is already a BDF-plus file.");
    messagewindow.exec();
    edfclose_file(hdl_in);
    return;
  }

  if(hdr.filetype != EDFLIB_FILETYPE_BDF)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Selected file is not a BDF file.");
    messagewindow.exec();
    edfclose_file(hdl_in);
    return;
  }

  if(hdr.datarecord_duration != EDFLIB_TIME_DIMENSION)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Datarecord duration of inputfile must be 1 second.");
    messagewindow.exec();
    edfclose_file(hdl_in);
    return;
  }

  edfsignals = hdr.edfsignals;

  if(edfsignals < 1)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "There are no signals in the selected file.");
    messagewindow.exec();
    edfclose_file(hdl_in);
    return;
  }

  sf = hdr.signalparam[0].smp_in_datarecord;

  for(i=1; i<edfsignals; i++)
  {
    if(hdr.signalparam[i].smp_in_datarecord != sf)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "All signals must have the same samplefrequency.");
      messagewindow.exec();
      edfclose_file(hdl_in);
      return;
    }
  }

  error = 1;

  switch(sf)
  {
    case 16384 : error = 0;
                 break;
    case  8192 : error = 0;
                 break;
    case  4096 : error = 0;
                 break;
    case  2048 : error = 0;
                 break;
    case  1024 : error = 0;
                 break;
    case   512 : error = 0;
                 break;
    case   256 : error = 0;
                 break;
    case   128 : error = 0;
                 break;
    case    64 : error = 0;
                 break;
    case    32 : error = 0;
                 break;
  }

  if(error)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Samplefrequency must be 16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64 or 32 Hz.");
    messagewindow.exec();
    edfclose_file(hdl_in);
    return;
  }

  for(i=0; i<edfsignals; i++)
  {
    if(!(strcmp(hdr.signalparam[i].label, "Status          ")))
    {
      status_signal = i;

      break;
    }
  }

  if(i == edfsignals)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "There is no Status signal in the selected file.");
    messagewindow.exec();
    edfclose_file(hdl_in);
    return;
  }

  totalSamplesInDatarecord = 0;

  for(i=0; i<edfsignals; i++)
  {
    buf_offset[i] = totalSamplesInDatarecord;

    if(i == status_signal)
    {
      status_samples_in_datarecord = hdr.signalparam[i].smp_in_datarecord;
    }

    totalSamplesInDatarecord += hdr.signalparam[i].smp_in_datarecord;
  }

  status_sample_duration = EDFLIB_TIME_DIMENSION / (long long)status_samples_in_datarecord;

  for(i=0; i<16; i++)
  {
    strcpy(&triggerlabel[i][0], lineEdit1[i]->text().toUtf8().data());
    triggerlabel[i][16] = 0;
  }

  strcpy(&triggerlabel[16][0], "new epoch");

  if(radioButton1->isChecked() == true)
  {
    rising_edge = 1;

    for(i=0; i<16; i++)
    {
      status[i] = 1;
    }
  }
  else
  {
    rising_edge = 0;

    for(i=0; i<16; i++)
    {
      status[i] = 0;
    }
  }

  if(checkBox1->isChecked() == true)
  {
    set_duration = 1;
  }
  else
  {
    set_duration = 0;
  }

  for(i=16; i<24; i++)
  {
    status[i] = 1;
  }

  strcpy(outputfilename, inputpath);
  remove_extension_from_filename(outputfilename);
  strcat(outputfilename, "_+.bdf");

  outputpath[0] = 0;
  if(recent_savedir[0]!=0)
  {
    strcpy(outputpath, recent_savedir);
    strcat(outputpath, "/");
  }
  strcat(outputpath, outputfilename);

  strcpy(outputpath, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(outputpath), "BDF files (*.bdf *.BDF)").toLocal8Bit().data());

  if(!strcmp(outputpath, ""))
  {
    edfclose_file(hdl_in);
    return;
  }

  get_directory_from_path(recent_savedir, outputpath, MAX_PATH_LENGTH);

  if(mainwindow->file_is_opened(outputpath))
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Outputfile is already opened in EDFbrowser.\nClose the file and try again.");
    messagewindow.exec();
    edfclose_file(hdl_in);
    return;
  }

  if(!(strcmp(inputpath, outputpath)))
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Inputfile and outputfile are the same.");
    messagewindow.exec();
    edfclose_file(hdl_in);
    return;
  }

  hdl_out = edfopen_file_writeonly(outputpath, EDFLIB_FILETYPE_BDFPLUS, edfsignals);

  if(hdl_out < 0)
  {
    switch(hdl_out)
    {
      case EDFLIB_MALLOC_ERROR                : strcpy(str, "EDFlib: malloc error.");
                                                break;
      case EDFLIB_NO_SUCH_FILE_OR_DIRECTORY   : strcpy(str, "EDFlib: no such file or directory.");
                                                break;
      case EDFLIB_MAXFILES_REACHED            : strcpy(str, "EDFlib: maximum amount of files reached.");
                                                break;
      case EDFLIB_FILE_READ_ERROR             : strcpy(str, "EDFlib: a file read error occurred.");
                                                break;
      case EDFLIB_FILE_ALREADY_OPENED         : strcpy(str, "EDFlib: file is already opened.");
                                                break;
      case EDFLIB_FILETYPE_ERROR              : strcpy(str, "EDFlib: filetype error.");
                                                break;
      case EDFLIB_FILE_WRITE_ERROR            : strcpy(str, "EDFlib: file write error.");
                                                break;
      case EDFLIB_NUMBER_OF_SIGNALS_INVALID   : strcpy(str, "EDFlib: invalid number of signals.");
                                                break;
      default                                 : strcpy(str, "EDFlib: unknown error.");
    }

    QMessageBox messagewindow(QMessageBox::Critical, "Error", str);
    messagewindow.exec();

    edfclose_file(hdl_in);
    return;
  }

/////////////////// copy header /////////////////////////////////////////////

  for(i=0; i<edfsignals; i++)
  {
    edf_set_samplefrequency(hdl_out, i, hdr.signalparam[i].smp_in_datarecord);
    edf_set_physical_maximum(hdl_out, i, hdr.signalparam[i].phys_max);
    edf_set_physical_minimum(hdl_out, i, hdr.signalparam[i].phys_min);
    edf_set_digital_maximum(hdl_out, i, hdr.signalparam[i].dig_max);
    edf_set_digital_minimum(hdl_out, i, hdr.signalparam[i].dig_min);
    edf_set_label(hdl_out, i, hdr.signalparam[i].label);
    edf_set_prefilter(hdl_out, i, hdr.signalparam[i].prefilter);
    edf_set_transducer(hdl_out, i, hdr.signalparam[i].transducer);
    edf_set_physical_dimension(hdl_out, i, hdr.signalparam[i].physdimension);
  }

  edf_set_startdatetime(hdl_out, hdr.startdate_year, hdr.startdate_month, hdr.startdate_day, hdr.starttime_hour, hdr.starttime_minute, hdr.starttime_second);
  edf_set_patientname(hdl_out, hdr.patient);
  edf_set_recording_additional(hdl_out, hdr.recording);

/////////////////// collect triggers /////////////////////////////////////////////

  buf = (int *)malloc(sizeof(int) * status_samples_in_datarecord);
  if(buf == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error (buf).");
    messagewindow.exec();
    edfclose_file(hdl_in);
    edfclose_file(hdl_out);
    return;
  }

  QProgressDialog progress("Collecting triggers...", "Abort", 0, (int)hdr.datarecords_in_file);
  progress.setWindowModality(Qt::WindowModal);
  progress.setMinimumDuration(200);

  progress_steps = hdr.datarecords_in_file / 100LL;
  if(progress_steps < 1LL)
  {
    progress_steps = 1LL;
  }

  trigger_cnt = 0;

  for(datarecords = 0LL; datarecords < hdr.datarecords_in_file; datarecords++)
  {
    if(trigger_cnt >= ((hdr.datarecords_in_file * 32) - 2))
    {
      break;
    }

    if(trigger_cnt >= 100000)
    {
      break;
    }

    if(!(datarecords % progress_steps))
    {
      progress.setValue((int)datarecords);

      qApp->processEvents();

      if(progress.wasCanceled())
      {
        edfclose_file(hdl_in);
        edfclose_file(hdl_out);
        free(buf);
        edfplus_annotation_delete_list(&annotlist);
        return;
      }
    }

    if(edfread_digital_samples(hdl_in, status_signal, status_samples_in_datarecord, buf) < 0)
    {
      progress.reset();
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "A read error occurred during the collection of triggers.");
      messagewindow.exec();
      edfclose_file(hdl_in);
      edfclose_file(hdl_out);
      free(buf);
      edfplus_annotation_delete_list(&annotlist);
      return;
    }

    for(i=0; i<status_samples_in_datarecord; i++)
    {
      for(j=0; j<17; j++)
      {
        if(((buf[i] & (1 << j)) && !status[j]) || (!(buf[i] & (1 << j)) && status[j]))  // rising or falling edge detected
        {
          if(status[j])  // falling edge detected
          {
            if((!rising_edge) && (j < 16))
            {
              annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock));
              if(annotation == NULL)
              {
                progress.reset();
                QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error (annotation).");
                messagewindow.exec();
                edfclose_file(hdl_in);
                edfclose_file(hdl_out);
                free(buf);
                edfplus_annotation_delete_list(&annotlist);
                return;
              }
              annotation->onset = (datarecords * EDFLIB_TIME_DIMENSION) + ((long long)i * status_sample_duration);
              annotation->onset += hdr.starttime_subsecond;
              strcpy(annotation->annotation, triggerlabel[j]);
              edfplus_annotation_add_item(&annotlist, annotation);

              trigger_cnt++;
            }
            else
            {
              if(set_duration)
              {
                k = edfplus_annotation_count(&annotlist);
                for(; k>0; k--)
                {
                  annotation = edfplus_annotation_item(&annotlist, k - 1);
                  if(annotation == NULL)
                  {
                    break;
                  }
                  if(!strcmp(annotation->annotation, triggerlabel[j]))
                  {
                    sprintf(str, "%.4f", (double)((datarecords * EDFLIB_TIME_DIMENSION) + ((long long)i * status_sample_duration) - annotation->onset) / (double)EDFLIB_TIME_DIMENSION);
                    str[15] = 0;
                    strcpy(annotation->duration, str);
                    break;
                  }
                }
              }
            }

            status[j] = 0;
          }
          else  // rising edge detected
          {
            if(rising_edge || (j == 16))
            {
              annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock));
              if(annotation == NULL)
              {
                progress.reset();
                QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error (annotation).");
                messagewindow.exec();
                edfclose_file(hdl_in);
                edfclose_file(hdl_out);
                free(buf);
                edfplus_annotation_delete_list(&annotlist);
                return;
              }
              annotation->onset = (datarecords * EDFLIB_TIME_DIMENSION) + ((long long)i * status_sample_duration);
              annotation->onset += hdr.starttime_subsecond;
              strcpy(annotation->annotation, triggerlabel[j]);
              edfplus_annotation_add_item(&annotlist, annotation);

              trigger_cnt++;
            }
            else
            {
              if(set_duration)
              {
                k = edfplus_annotation_count(&annotlist);
                for(; k>0; k--)
                {
                  annotation = edfplus_annotation_item(&annotlist, k - 1);
                  if(annotation == NULL)
                  {
                    break;
                  }
                  if(!strcmp(annotation->annotation, triggerlabel[j]))
                  {
                    sprintf(str, "%.4f", (double)((datarecords * EDFLIB_TIME_DIMENSION) + ((long long)i * status_sample_duration) - annotation->onset) / (double)EDFLIB_TIME_DIMENSION);
                    str[15] = 0;
                    strcpy(annotation->duration, str);
                    break;
                  }
                }
              }
            }

            status[j] = 1;
          }
        }
      }
    }
  }

  edfwrite_annotation_latin1(hdl_out, 0LL, -1LL, "Recording starts");

  j = edfplus_annotation_count(&annotlist);

  for(i=0; i<j; i++)
  {
    annotation = edfplus_annotation_item(&annotlist, i);

    if(annotation->duration[0] == 0)
    {
      edfwrite_annotation_utf8(hdl_out, annotation->onset / 1000LL, -1LL, annotation->annotation);
    }
    else
    {
      edfwrite_annotation_utf8(hdl_out, annotation->onset / 1000LL, (long long)(atof(annotation->duration) * 10000.0), annotation->annotation);
    }
  }

  free(buf);

  edfwrite_annotation_latin1(hdl_out, hdr.datarecords_in_file * 10000LL, -1LL, "Recording ends");

/////////////////// choose datarecord duration /////////////////////////////////////////////

  samplerate_divider = 1;

  i = edfplus_annotation_count(&annotlist);

  edfplus_annotation_delete_list(&annotlist);

  annotlist = NULL;

  if(i % 2)
  {
    i++;
  }

  i += 2;

  while(i > hdr.datarecords_in_file)
  {
    samplerate_divider *= 2;

    i /= 2;

    if(samplerate_divider == 32)
    {
      break;
    }
  }

  if(samplerate_divider > 1)
  {
    for(i=0; i<edfsignals; i++)
    {
      edf_set_samplefrequency(hdl_out, i, hdr.signalparam[i].smp_in_datarecord / samplerate_divider);
    }

    if(edf_set_datarecord_duration(hdl_out, 100000 / samplerate_divider) == -1)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "edf_set_datarecord_duration() returned an error.");
      messagewindow.exec();
      edfclose_file(hdl_in);
      edfclose_file(hdl_out);
      return;
    }
  }

  new_sf = sf / samplerate_divider;

/////////////////// start conversion /////////////////////////////////////////////

  buf = (int *)malloc(sizeof(int) * totalSamplesInDatarecord);
  if(buf == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error (buf).");
    messagewindow.exec();
    edfclose_file(hdl_in);
    edfclose_file(hdl_out);
    return;
  }

  edfrewind(hdl_in, status_signal);

  progress.setLabelText("Converting...");
  progress.setValue(0);

  for(datarecords = 0LL; datarecords < hdr.datarecords_in_file; datarecords++)
  {
    if(!(datarecords % progress_steps))
    {
      progress.setValue((int)datarecords);

      qApp->processEvents();

      if(progress.wasCanceled())
      {
        edfclose_file(hdl_in);
        edfclose_file(hdl_out);
        free(buf);
        return;
      }
    }

    for(i=0; i<edfsignals; i++)
    {
      if(edfread_digital_samples(hdl_in, i, hdr.signalparam[i].smp_in_datarecord, buf + buf_offset[i]) < 0)
      {
        progress.reset();
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "A read error occurred during the conversion.");
        messagewindow.exec();
        edfclose_file(hdl_in);
        edfclose_file(hdl_out);
        free(buf);
        return;
      }
    }

    for(j=0; j<samplerate_divider; j++)
    {
      for(i=0; i<edfsignals; i++)
      {
        if(edfwrite_digital_samples(hdl_out, buf + buf_offset[i] + (j * new_sf)) < 0)
        {
          progress.reset();
          QMessageBox messagewindow(QMessageBox::Critical, "Error", "A write error occurred during the conversion.");
          messagewindow.exec();
          edfclose_file(hdl_in);
          edfclose_file(hdl_out);
          free(buf);
          return;
        }
      }
    }
  }

  QApplication::setOverrideCursor(Qt::WaitCursor);

  edfclose_file(hdl_in);
  edfclose_file(hdl_out);
  free(buf);

  QApplication::restoreOverrideCursor();

  progress.reset();

#ifdef Q_WS_WIN
  snprintf(str, 2048, "Done. Converted %I64d input trigger events to BDF+ annotations.\n"
                      "\nBDF+ file is located at %s", trigger_cnt, outputpath);
#else
  snprintf(str, 2048, "Done. Converted %lli input trigger events to BDF+ annotations.\n"
                      "\nBDF+ file is located at %s", trigger_cnt, outputpath);
#endif

  QMessageBox messagewindow(QMessageBox::Information, "Ready", str);
  messagewindow.setIconPixmap(QPixmap(":/images/ok.png"));
  messagewindow.exec();
}
Example #2
0
void UI_BI98002EDFwindow::SelectFileButton()
{
  int i, j, n,
      tmp,
      end_of_file,
      samplefreq=0,
      chns = 3,
      hdl,
      samplesize=1,
      bufsize,
      *buf2,
      datablocks,
      blocks_written,
      checked_modelnumber=0,
      checked_samplerate=0,
      checked_recordhours=0,
      checked_recorddate=0,
      checked_recordtime=0,
      startdate_year=0,
      startdate_month=0,
      startdate_day=0,
      starttime_hour=0,
      starttime_minute=0,
      starttime_second=0,
      progress_steps;

  char path[MAX_PATH_LENGTH],
       outputfilename[MAX_PATH_LENGTH],
       str[2048],
       str2[128],
       *buf1,
       tmp2,
       modelnumber_str[32];

  FILE *dcmfile,
       *evtfile;



  strcpy(path, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "DCM files (*.dcm *.DCM)").toLocal8Bit().data());

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

  get_directory_from_path(recent_opendir, path, MAX_PATH_LENGTH);

  get_filename_from_path(outputfilename, path, MAX_PATH_LENGTH);

  dcmfile = fopeno(path, "rb");
  if(dcmfile==NULL)
  {
    snprintf(str, 2048, "Can not open file %s for reading.", path);
    QMessageBox messagewindow(QMessageBox::Critical, "Error", QString::fromLocal8Bit(str));
    messagewindow.exec();
    return;
  }

  remove_extension_from_filename(path);
  strcat(path, ".EVT");
  evtfile = fopeno(path, "rb");
  if(evtfile==NULL)
  {
    remove_extension_from_filename(path);
    strcat(path, ".evt");
    evtfile = fopeno(path, "rb");
    if(evtfile==NULL)
    {
      snprintf(str, 2048, "Can not open file %s for reading.", path);
      QMessageBox messagewindow(QMessageBox::Critical, "Error", str);
      messagewindow.exec();
      fclose(dcmfile);
      return;
    }
  }

/***************** check if the file is valid ******************************/

  for(end_of_file=0; end_of_file == 0; )
  {
    for(i=0; i<256; i++)
    {
      tmp = fgetc(evtfile);

      if(tmp == '\n')
      {
        break;
      }

      if(tmp == EOF)
      {
        end_of_file = 1;

        break;
      }

      str[i] = tmp;
    }

    str[i] = 0;

    if(!(strncmp(str, "Sampling Rate=", 14)))
    {
      samplefreq = atoi(str + 14);
      switch(samplefreq)
      {
        case  128 : break;
        case  256 : break;
        case  512 : break;
        case 1024 : break;

        default : QMessageBox messagewindow(QMessageBox::Critical, "Error", "Unknown samplerate.");
                  messagewindow.exec();
                  fclose(dcmfile);
                  fclose(evtfile);
                  return;
      }

      checked_samplerate = 1;
    }

    if(!(strncmp(str, "Model number=", 13)))
    {
      strncpy(modelnumber_str, str + 13, 8);
      modelnumber_str[8] = 0;

      if(strcmp(modelnumber_str, "TM SD01G") &&
         strcmp(modelnumber_str, "SD SD02G"))
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "Wrong modelnumber.");
        messagewindow.exec();
        fclose(dcmfile);
        fclose(evtfile);
        return;
      }

      checked_modelnumber = 1;
    }

    if(!(strncmp(str, "Record Date=", 12)))
    {
      strncpy(str2, str + 12, 10);
      str2[10] = 0;

      startdate_year = atoi(str2);
      startdate_month = atoi(str2 + 5);
      startdate_day = atoi(str2 + 8);

      if((startdate_year < 1970) || (startdate_year > 3000) ||
         (startdate_month < 1)   || (startdate_month > 12)  ||
         (startdate_day < 1)     || (startdate_day > 31))
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "Wrong record date.");
        messagewindow.exec();
        fclose(dcmfile);
        fclose(evtfile);
        return;
      }

      checked_recorddate = 1;
    }

    if(!(strncmp(str, "Record Time=", 12)))
    {
      strncpy(str2, str + 12, 10);
      str2[8] = 0;

      starttime_hour = atoi(str2);
      starttime_minute = atoi(str2 + 3);
      starttime_second = atoi(str2 + 6);

      if((starttime_hour < 0)  || (starttime_hour > 23)   ||
        (starttime_minute < 0) || (starttime_minute > 59) ||
        (starttime_second < 0) || (starttime_second > 59))
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "Wrong recordtime.");
        messagewindow.exec();
        fclose(dcmfile);
        fclose(evtfile);
        return;
      }

      checked_recordtime = 1;
    }

    if(!(strncmp(str, "Record Hours=", 13)))
    {
      strncpy(str2, str + 13, 10);
      str2[2] = 0;

      if((atoi(str2) != 24) && (atoi(str2) != 48))
      {
        QMessageBox messagewindow(QMessageBox::Critical, "Error", "Wrong record hours.");
        messagewindow.exec();
        fclose(dcmfile);
        fclose(evtfile);
        return;
      }

      checked_recordhours = 1;
    }
  }

  if(!checked_modelnumber ||
     !checked_samplerate  ||
     !checked_recordhours ||
     !checked_recorddate  ||
     !checked_recordtime)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Missing line.");
    messagewindow.exec();
    fclose(dcmfile);
    fclose(evtfile);
    return;
  }

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

  bufsize = chns * samplesize * samplefreq;

  buf1 = (char *)malloc(bufsize);
  if(buf1 == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error.");
    messagewindow.exec();
    fclose(dcmfile);
    fclose(evtfile);
    return;
  }

  buf2 = (int *)malloc(bufsize * sizeof(int));
  if(buf2 == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error.");
    messagewindow.exec();
    fclose(dcmfile);
    fclose(evtfile);
    free(buf1);
    return;
  }

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

  path[0] = 0;
  if(recent_savedir[0]!=0)
  {
    strcpy(path, recent_savedir);
    strcat(path, "/");
  }
  strcat(path, outputfilename);
  remove_extension_from_filename(path);
  strcat(path, ".edf");

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

  if(!strcmp(path, ""))
  {
    fclose(dcmfile);
    fclose(evtfile);
    free(buf1);
    free(buf2);
    return;
  }

  get_directory_from_path(recent_savedir, path, MAX_PATH_LENGTH);

  hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_EDFPLUS, chns);
  if(hdl<0)
  {
    snprintf(str, 2048, "Can not open file %s for writing.", path);
    QMessageBox messagewindow(QMessageBox::Critical, "Error", str);
    messagewindow.exec();
    fclose(dcmfile);
    fclose(evtfile);
    free(buf1);
    free(buf2);
    return;
  }

  for(i=0; i<chns; i++)
  {
    edf_set_samplefrequency(hdl, i, samplefreq);
  }

  for(i=0; i<chns; i++)
  {
    edf_set_digital_maximum(hdl, i, 127);
  }

  for(i=0; i<chns; i++)
  {
    edf_set_digital_minimum(hdl, i, -128);
  }

  for(i=0; i<chns; i++)
  {
    edf_set_physical_maximum(hdl, i, 2442.307692);
  }

  for(i=0; i<chns; i++)
  {
    edf_set_physical_minimum(hdl, i, -2461.538462);
  }

  for(i=0; i<chns; i++)
  {
    edf_set_physical_dimension(hdl, i, "uV");
  }

  edf_set_label(hdl, 0, "channel 1");

  edf_set_label(hdl, 1, "channel 2");

  edf_set_label(hdl, 2, "channel 3");

  edf_set_equipment(hdl, modelnumber_str);

  edf_set_patientname(hdl, "BI9800");

  edf_set_startdatetime(hdl, startdate_year, startdate_month, startdate_day, starttime_hour, starttime_minute, starttime_second);

  fseeko(dcmfile, 0LL, SEEK_END);
  datablocks = ftello(dcmfile) / bufsize;
  fseeko(dcmfile, 0LL, SEEK_SET);

  QProgressDialog progress("Converting...", "Cancel", 0, datablocks, myobjectDialog);
  progress.setWindowModality(Qt::WindowModal);
  progress.setMinimumDuration(200);

  progress_steps = datablocks / 100;
  if(progress_steps < 1)
  {
    progress_steps = 1;
  }

  for(blocks_written=0; ; blocks_written++)
  {
    if(!(blocks_written % progress_steps))
    {
      progress.setValue(blocks_written);

      qApp->processEvents();

      if(progress.wasCanceled() == true)
      {
        break;
      }
    }

    n = fread(buf1, bufsize, 1, dcmfile);
    if(n != 1)
    {
      break;
    }

    for(i=0; i<samplefreq; i++)
    {
      for(j=0; j<chns; j++)
      {
        tmp2 = buf1[(i * chns) + j] + 128;
        buf2[(j * samplefreq) + i] = tmp2;
      }
    }

    edf_blockwrite_digital_samples(hdl, buf2);
  }

  progress.reset();

  edfwrite_annotation_latin1(hdl, 0LL, -1LL, "Recording starts");

  fseeko(evtfile, 0LL, SEEK_SET);

  for(end_of_file=0; end_of_file == 0; )
  {
    for(i=0; i<256; i++)
    {
      tmp = fgetc(evtfile);

      if((tmp == '\n') || (tmp == '\r'))
      {
        break;
      }

      if(tmp == EOF)
      {
        end_of_file = 1;

        break;
      }

      str[i] = tmp;
    }

    str[i] = 0;

    if((isdigit(str[0])) && (isdigit(str[1])))
    {
      starttime_hour = atoi(str);
      starttime_minute = atoi(str + 3);
      starttime_second = atoi(str + 6);

      if((starttime_hour < 0)   || (starttime_hour > 23)   ||
         (starttime_minute < 0) || (starttime_minute > 59) ||
         (starttime_second < 0) || (starttime_second > 59))
      {
      }
      else
      {
        if(strlen(str) > 9)
        {
          edfwrite_annotation_latin1(hdl, (starttime_second + (starttime_minute * 60) + (starttime_hour * 3600)) * 10000, -1, str + 9);
        }
      }
    }
  }

  edfwrite_annotation_latin1(hdl, blocks_written * 10000LL, -1LL, "Recording ends");

  edfclose_file(hdl);

  fclose(dcmfile);
  fclose(evtfile);
  free(buf1);
  free(buf2);
}
void UI_ExportAnnotationswindow::ExportButtonClicked()
{
  int i, j, n,
      len,
      csv_format=0,
      hdl,
      annot_cnt,
      temp,
      include_duration;

  char path[MAX_PATH_LENGTH],
       str[1024],
       separator;

  FILE *annotationfile=NULL;

  struct annotationblock *annot, *annot_list;

  struct edfhdrblock *hdr;

  struct date_time_struct tm;


  if(CSVRadioButton->isChecked() == true)
  {
    if(asciiSecondsRadioButton->isChecked() == true)
    {
      csv_format = 1;
    }

    if(asciiISOtimeRadioButton->isChecked() == true)
    {
      csv_format = 2;
    }

    if(asciiISOtimedateRadioButton->isChecked() == true)
    {
      csv_format = 3;
    }

    if(asciiISOtimeFractionRadioButton->isChecked() == true)
    {
      csv_format = 4;
    }

    if(asciiISOtimedateFractionRadioButton->isChecked() == true)
    {
      csv_format = 5;
    }
  }

  if(EDFplusRadioButton->isChecked() == true)
  {
    csv_format = 0;
  }

  if(XMLRadioButton->isChecked() == true)
  {
    csv_format = 8;
  }

   mainwindow->export_annotations_var->format = csv_format;

  if(separatorBox->currentIndex() == 0)
  {
    separator = ',';
    mainwindow->export_annotations_var->separator = 0;
  }
  else
  {
    separator = '\t';
    mainwindow->export_annotations_var->separator = 1;
  }

  if(durationCheckBox->checkState() == Qt::Checked)
  {
    include_duration = 1;
    mainwindow->export_annotations_var->duration = 1;
  }
  else
  {
    include_duration = 0;
    mainwindow->export_annotations_var->duration = 0;
  }

  if(!mainwindow->files_open)
  {
    ExportAnnotsDialog->close();
    return;
  }

  if(filelist->count() < 1)
  {
    ExportAnnotsDialog->close();
    return;
  }

  ExportButton->setEnabled(false);
  CloseButton->setEnabled(false);

  for(i=0; i<mainwindow->files_open; i++)
  {
    if(!strcmp(mainwindow->edfheaderlist[i]->filename, filelist->item(filelist->currentRow())->text().toLocal8Bit().data()))
    {
      break;
    }
  }

  if(i==mainwindow->files_open)
  {
    ExportAnnotsDialog->close();
    return;
  }

  n = i;

  if(mergeRadioButton->isChecked() == true)
  {
    n = mainwindow->sel_viewtime;
  }

  hdr = mainwindow->edfheaderlist[n];

  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[n]->filename, MAX_PATH_LENGTH - len);
  remove_extension_from_filename(path);
  if((csv_format > 0) && (csv_format < 6))
  {
    strcat(path, "_annotations.txt");

    strcpy(path, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(path), "Text files (*.txt *.TXT *.csv *.CSV)").toLocal8Bit().data());
  }

  if(csv_format == 8)
  {
    strcat(path, "_annotations.xml");

    strcpy(path, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(path), "XML files (*.xml *.XML)").toLocal8Bit().data());
  }

  if(csv_format == 0)
  {
    strcat(path, "_annotations.edf");

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

  if(!strcmp(path, ""))
  {
    ExportAnnotsDialog->close();
    return;
  }

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

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

  annot_list = edfplus_annotation_copy_list(&mainwindow->annotationlist[n]);

  if(mergeRadioButton->isChecked() == true)
  {
    for(i=0; i < mainwindow->files_open; i++)
    {
      if(i != mainwindow->sel_viewtime)
      {
        annot_cnt = edfplus_annotation_count(&mainwindow->annotationlist[i]);

        for(j=0; j < annot_cnt; j++)
        {
          edfplus_annotation_add_copy(&annot_list, edfplus_annotation_item(&mainwindow->annotationlist[i], j));

          annot = edfplus_annotation_item(&annot_list, edfplus_annotation_count(&annot_list) - 1);

          annot->onset -= (mainwindow->edfheaderlist[i]->viewtime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime);
        }
      }
    }

    edfplus_annotation_sort(&annot_list);
  }

  annot_cnt = edfplus_annotation_count(&annot_list);

///////////////////////////// CSV (text) export //////////////////////////////////////

  if((csv_format > 0) && (csv_format < 6))
  {
    annotationfile = fopeno(path, "wb");
    if(annotationfile==NULL)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open annotationfile for writing.");
      messagewindow.exec();
      ExportAnnotsDialog->close();
      edfplus_annotation_delete_list(&annot_list);
      return;
    }

    if(include_duration)
    {
      fprintf(annotationfile, "Onset%cDuration%cAnnotation\n", separator, separator);
    }
    else
    {
      fprintf(annotationfile, "Onset%cAnnotation\n", separator);
    }

    for(j=0; j < annot_cnt; j++)
    {
      annot = edfplus_annotation_item(&annot_list, j);
      if(annot == NULL)
      {
        break;
      }
      strncpy(str, annot->annotation, 1024);
      str[1023] = 0;
      utf8_to_latin1(str);

      len = strlen(str);
      for(i=0; i<len; i++)
      {
        if((((unsigned char *)str)[i] < 32) || (((unsigned char *)str)[i] == ','))
        {
          str[i] = '.';
        }
      }

      if(csv_format == 1)
      {
        if(include_duration)
        {
          fprintf(annotationfile, "%+.7f%c%s%c%s\n", (double)(annot->onset - hdr->starttime_offset) / TIME_DIMENSION, separator, annot->duration, separator, str);
        }
        else
        {
          fprintf(annotationfile, "%+.7f%c%s\n", (double)(annot->onset - hdr->starttime_offset) / TIME_DIMENSION, separator, str);
        }
      }

      if(csv_format == 2)
      {
        temp = annot->onset % TIME_DIMENSION;

        if(temp < 0)
        {
          utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION) - 1, &tm);
        }
        else
        {
          utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION), &tm);
        }

        if(include_duration)
        {
          fprintf(annotationfile, "%02i:%02i:%02i%c%s%c%s\n", tm.hour, tm.minute, tm.second, separator, annot->duration, separator, str);
        }
        else
        {
          fprintf(annotationfile, "%02i:%02i:%02i%c%s\n", tm.hour, tm.minute, tm.second, separator, str);
        }
      }

      if(csv_format == 3)
      {
        temp = annot->onset % TIME_DIMENSION;

        if(temp < 0)
        {
          utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION) - 1, &tm);
        }
        else
        {
          utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION), &tm);
        }

        if(include_duration)
        {
          fprintf(annotationfile, "%04i-%02i-%02iT%02i:%02i:%02i%c%s%c%s\n", tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second, separator, annot->duration, separator, str);
        }
        else
        {
          fprintf(annotationfile, "%04i-%02i-%02iT%02i:%02i:%02i%c%s\n", tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second, separator, str);
        }
      }

      if(csv_format == 4)
      {
        temp = annot->onset % TIME_DIMENSION;

        if(temp < 0)
        {
          utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION) - 1, &tm);

          temp = TIME_DIMENSION + temp;
        }
        else
        {
          utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION), &tm);
        }

        if(include_duration)
        {
          fprintf(annotationfile, "%02i:%02i:%02i.%07i%c%s%c%s\n", tm.hour, tm.minute, tm.second, temp, separator, annot->duration, separator, str);
        }
        else
        {
          fprintf(annotationfile, "%02i:%02i:%02i.%07i%c%s\n", tm.hour, tm.minute, tm.second, temp, separator, str);
        }
      }

      if(csv_format == 5)
      {
        temp = annot->onset % TIME_DIMENSION;

        if(temp < 0)
        {
          utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION) - 1, &tm);

          temp = TIME_DIMENSION + temp;
        }
        else
        {
          utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION), &tm);
        }

        if(include_duration)
        {
          fprintf(annotationfile, "%04i-%02i-%02iT%02i:%02i:%02i.%07i%c%s%c%s\n", tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second, temp, separator, annot->duration, separator, str);
        }
        else
        {
          fprintf(annotationfile, "%04i-%02i-%02iT%02i:%02i:%02i.%07i%c%s\n", tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second, temp, separator, str);
        }
      }
    }

    fclose(annotationfile);

    edfplus_annotation_delete_list(&annot_list);

    QMessageBox messagewindow(QMessageBox::Information, "Ready", "Done.");
    messagewindow.setIconPixmap(QPixmap(":/images/ok.png"));
    messagewindow.exec();

    ExportAnnotsDialog->close();

    return;
  }

///////////////////////////// XML export //////////////////////////////////////

  if(csv_format == 8)
  {
    annotationfile = fopeno(path, "wb");
    if(annotationfile==NULL)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open annotationfile for writing.");
      messagewindow.exec();
      ExportAnnotsDialog->close();
      edfplus_annotation_delete_list(&annot_list);
      return;
    }

    fprintf(annotationfile, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");

    fprintf(annotationfile, "<!-- Generated by " PROGRAM_NAME " " PROGRAM_VERSION " -->\n");

    fprintf(annotationfile, "<annotationlist>\n");

    utc_to_date_time(hdr->utc_starttime, &tm);

    fprintf(annotationfile, " <recording_start_time>%04i-%02i-%02iT%02i:%02i:%02i.%07i</recording_start_time>\n",
                            tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second, (int)hdr->starttime_offset);

    for(j=0; j < annot_cnt; j++)
    {
      annot = edfplus_annotation_item(&annot_list, j);
      if(annot == NULL)
      {
        break;
      }

      temp = annot->onset % TIME_DIMENSION;

      if(temp < 0)
      {
        utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION) - 1, &tm);

        temp = TIME_DIMENSION + temp;
      }
      else
      {
        utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION), &tm);
      }

      fprintf(annotationfile, " <annotation>\n"
                              "  <onset>%04i-%02i-%02iT%02i:%02i:%02i.%07i</onset>\n"
                              "  <duration>%s</duration>\n"
                              "  <description>",
                              tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second, temp, annot->duration);

      xml_fwrite_encode_entity(annotationfile, annot->annotation);

      fprintf(annotationfile,                     "</description>\n"
                              " </annotation>\n");
    }

    fprintf(annotationfile, "</annotationlist>\n");

    fclose(annotationfile);

    edfplus_annotation_delete_list(&annot_list);

    QMessageBox messagewindow(QMessageBox::Information, "Ready", "Done.");
    messagewindow.setIconPixmap(QPixmap(":/images/ok.png"));
    messagewindow.exec();

    ExportAnnotsDialog->close();

    return;
  }

///////////////////////////// EDFplus export //////////////////////////////////////

  if(csv_format == 0)
  {
    hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_EDFPLUS, 0);
    if(hdl < 0)
    {
      switch(hdl)
      {
        case EDFLIB_MALLOC_ERROR : strcpy(str, "EDFlib: malloc error");
                                  break;
        case EDFLIB_NO_SUCH_FILE_OR_DIRECTORY : strcpy(str, "EDFlib: no such file or directory");
                                  break;
        case EDFLIB_MAXFILES_REACHED : strcpy(str, "EDFlib: maximum files reached");
                                  break;
        case EDFLIB_FILE_ALREADY_OPENED : strcpy(str, "EDFlib: file already opened");
                                  break;
        case EDFLIB_NUMBER_OF_SIGNALS_INVALID : strcpy(str, "EDFlib: number of signals is invalid");
                                  break;
        default : strcpy(str, "EDFlib: unknown error");
                                  break;
      }

      QMessageBox messagewindow(QMessageBox::Critical, "Error", str);
      messagewindow.exec();
      edfplus_annotation_delete_list(&annot_list);
      ExportAnnotsDialog->close();
      return;
    }

    utc_to_date_time(hdr->utc_starttime, &tm);
    edf_set_startdatetime(hdl, tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second);

    if((hdr->edfplus) || (hdr->bdfplus))
    {
      edf_set_patientname(hdl, hdr->plus_patient_name);
      edf_set_patientcode(hdl, hdr->plus_patientcode);
      if(!(strcmp(hdr->plus_gender, "Male")))
      {
        edf_set_gender(hdl, 1);
      }
      if(!(strcmp(hdr->plus_gender, "Female")))
      {
        edf_set_gender(hdl, 0);
      }
      if(hdr->plus_birthdate[0] != 0)
      {
        if(!(strncmp(hdr->plus_birthdate + 3, "jan", 3)))  n = 1;
        if(!(strncmp(hdr->plus_birthdate + 3, "feb", 3)))  n = 2;
        if(!(strncmp(hdr->plus_birthdate + 3, "mar", 3)))  n = 3;
        if(!(strncmp(hdr->plus_birthdate + 3, "apr", 3)))  n = 4;
        if(!(strncmp(hdr->plus_birthdate + 3, "may", 3)))  n = 5;
        if(!(strncmp(hdr->plus_birthdate + 3, "jun", 3)))  n = 6;
        if(!(strncmp(hdr->plus_birthdate + 3, "jul", 3)))  n = 7;
        if(!(strncmp(hdr->plus_birthdate + 3, "aug", 3)))  n = 8;
        if(!(strncmp(hdr->plus_birthdate + 3, "sep", 3)))  n = 9;
        if(!(strncmp(hdr->plus_birthdate + 3, "oct", 3)))  n = 10;
        if(!(strncmp(hdr->plus_birthdate + 3, "nov", 3)))  n = 11;
        if(!(strncmp(hdr->plus_birthdate + 3, "dec", 3)))  n = 12;
        edf_set_birthdate(hdl, atoi(hdr->plus_birthdate + 7), n, atoi(hdr->plus_birthdate));
      }
      edf_set_patient_additional(hdl, hdr->plus_patient_additional);
      edf_set_admincode(hdl, hdr->plus_admincode);
      edf_set_technician(hdl, hdr->plus_technician);
      edf_set_equipment(hdl, hdr->plus_equipment);
      edf_set_recording_additional(hdl, hdr->plus_recording_additional);
    }
    else
    {
      edf_set_patientname(hdl, hdr->patient);
      edf_set_recording_additional(hdl, hdr->recording);
    }

    int hasdot,
        decimals;

    for(j=0; j < annot_cnt; j++)
    {
      annot = edfplus_annotation_item(&annot_list, j);
      if(annot == NULL)
      {
        break;
      }

      if(annot->duration[0] == 0)
      {
        edfwrite_annotation_utf8(hdl, annot->onset / 1000LL, -1LL, annot->annotation);
      }
      else
      {
        strcpy(str, annot->duration);

        len = strlen(str);

        hasdot = 0;

        for(i=0; i<len; i++)
        {
          if(str[i] == '.')
          {
            hasdot = 1;

            for(decimals=0; decimals<4; decimals++)
            {
              str[i] = str[i+1];

              if(str[i] == 0)
              {
                for( ; decimals<4; decimals++)
                {
                  str[i] = '0';

                  i++;
                }

                i--;
              }

              i++;
            }

            str[i] = 0;

            break;
          }
        }

        if(!hasdot)
        {
          strcat(str, "0000");
        }

        edfwrite_annotation_utf8(hdl, annot->onset / 1000LL, atoi(str), annot->annotation);
      }
    }

    if(edfclose_file(hdl) != 0)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred: edfclose_file()");
      messagewindow.exec();
    }

    edfplus_annotation_delete_list(&annot_list);

    QMessageBox messagewindow(QMessageBox::Information, "Ready", "Done.");
    messagewindow.setIconPixmap(QPixmap(":/images/ok.png"));
    messagewindow.exec();

    ExportAnnotsDialog->close();
  }
}
Example #4
0
void UI_AverageCurveWindow::export_edf(void)
{
  int i, j, k, p,
      type,
      edf_hdl,
      smp_per_record,
      datarecords,
      smpls_left;

  char path[MAX_PATH_LENGTH],
       str[512];

  double *buf,
         frequency,
         frequency2;


  smp_per_record = signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record;

  datarecords = avg_samples_on_screen / smp_per_record;

  smpls_left = avg_samples_on_screen % smp_per_record;

  path[0] = 0;
  if(mainwindow->recent_savedir[0]!=0)
  {
    strcpy(path, mainwindow->recent_savedir);
    strcat(path, "/");
  }
  get_filename_from_path(path + strlen(path), signalcomp->edfhdr->filename, 512);
  remove_extension_from_filename(path);
  sprintf(path + strlen(path), " averaging %s %i triggers [%s]",
          signalcomp->signallabel,
          avg_cnt,
          avg_annotation);

  if(signalcomp->edfhdr->edf)
  {
    strcat(path, ".edf");

    strcpy(path, QFileDialog::getSaveFileName(0, "Save as EDF", QString::fromLocal8Bit(path), "EDF files (*.edf *.EDF)").toLocal8Bit().data());
  }
  else
  {
    strcat(path, ".bdf");

    strcpy(path, QFileDialog::getSaveFileName(0, "Save as BDF", QString::fromLocal8Bit(path), "BDF files (*.bdf *.BDF)").toLocal8Bit().data());
  }

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

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

  if(signalcomp->edfhdr->edf)
  {
    edf_hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_EDFPLUS, 1);
  }
  else
  {
    edf_hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_BDFPLUS, 1);
  }

  if(edf_hdl < 0)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open output file for writing.");
    messagewindow.exec();
    return;
  }

  edf_set_samplefrequency(edf_hdl, 0, smp_per_record);

  if(edf_set_datarecord_duration(edf_hdl, signalcomp->edfhdr->long_data_record_duration / 100LL))
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Datarecordduration out of range.");
    messagewindow.exec();
    return;
  }

  if(signalcomp->edfhdr->edf)
  {
    edf_set_digital_maximum(edf_hdl, 0, 32767);
    edf_set_digital_minimum(edf_hdl, 0, -32768);
  }
  else
  {
    edf_set_digital_maximum(edf_hdl, 0, 8388607);
    edf_set_digital_minimum(edf_hdl, 0, -8388608);
  }

  edf_set_physical_maximum(edf_hdl, 0, avg_max_value);
  edf_set_physical_minimum(edf_hdl, 0, avg_min_value);
  edf_set_label(edf_hdl, 0, signalcomp->signallabel);
  edf_set_physical_dimension(edf_hdl, 0, signalcomp->physdimension);

  p = 0;

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

    frequency = signalcomp->fidfilter_freq[j];

    frequency2 = signalcomp->fidfilter_freq2[j];

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

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

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

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

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

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

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

    p = strlen(str);

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

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

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

    strcat(str, "Hz ");

    p = strlen(str);

    if(p>80)  break;
  }

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

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

    p = strlen(str);

    if(p>80)  break;
  }

  strcat(str, signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].prefilter);
  edf_set_prefilter(edf_hdl, 0, str);
  edf_set_transducer(edf_hdl, 0, signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].transducer);

  if((signalcomp->edfhdr->edfplus) || (signalcomp->edfhdr->bdfplus))
  {
    edf_set_patientname(edf_hdl, signalcomp->edfhdr->plus_patient_name);
    sprintf(str, "%i triggers \"%s\" averaged. %s", avg_cnt, avg_annotation, signalcomp->edfhdr->plus_recording_additional);
    edf_set_recording_additional(edf_hdl, str);
    edf_set_patientcode(edf_hdl, signalcomp->edfhdr->plus_patientcode);
    if(signalcomp->edfhdr->plus_gender[0] == 'M')
    {
      edf_set_gender(edf_hdl, 1);
    }
    if(signalcomp->edfhdr->plus_gender[0] == 'F')
    {
      edf_set_gender(edf_hdl, 0);
    }
    edf_set_patient_additional(edf_hdl, signalcomp->edfhdr->plus_patient_additional);
    edf_set_admincode(edf_hdl, signalcomp->edfhdr->plus_admincode);
    edf_set_technician(edf_hdl, signalcomp->edfhdr->plus_technician);
    edf_set_equipment(edf_hdl, signalcomp->edfhdr->plus_equipment);
  }
  else
  {
    edf_set_patientname(edf_hdl, signalcomp->edfhdr->patient);
    sprintf(str, "%i triggers \"%s\" averaged. %s", avg_cnt, avg_annotation, signalcomp->edfhdr->recording);
    edf_set_recording_additional(edf_hdl, str);
  }

  for(i=0; i<datarecords; i++)
  {
    edfwrite_physical_samples(edf_hdl, avgbuf + (i * smp_per_record));
  }

  if(smpls_left)
  {
    buf = (double *)calloc(1, smp_per_record * sizeof(double));
    if(buf == NULL)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error (buf).");
      messagewindow.exec();
    }
    else
    {
      for(i=0; i<smpls_left; i++)
      {
        buf[i] = avgbuf[(datarecords * smp_per_record) + i];
      }

      edfwrite_physical_samples(edf_hdl, buf);

      free(buf);
    }
  }

  edfwrite_annotation_latin1(edf_hdl,
                             (avg_period * 10000.0) / (double)avg_trigger_position_ratio,
                             -1,
                             avg_annotation);

  edfclose_file(edf_hdl);
}
Example #5
0
int main(int argc, char *argv[])
{
  int i, j,
      hdl,
      chns=1,
      smp_freq=8192,
      fileduration=300,
      linear=1;

  double buf[smp_freq],
         q,
         sine_1,
         startfreq=10.0,
         stopfreq=4095.0,
         freqspan,
         freq;

  long long samples,
            sampleswritten;

  char str[256];



#ifdef BDF_FORMAT
  hdl = edfopen_file_writeonly("freq_sweep.bdf", EDFLIB_FILETYPE_BDFPLUS, chns);
#else
  hdl = edfopen_file_writeonly("freq_sweep.edf", EDFLIB_FILETYPE_EDFPLUS, chns);
#endif

  if(hdl<0)
  {
    printf("error: edfopen_file_writeonly()\n");

    return(1);
  }

  for(i=0; i<chns; i++)
  {
    if(edf_set_samplefrequency(hdl, i, smp_freq))
    {
      printf("error: edf_set_samplefrequency()\n");

      return(1);
    }
  }

#ifdef BDF_FORMAT
  for(i=0; i<chns; i++)
  {
    if(edf_set_digital_maximum(hdl, i, 8388607))
    {
      printf("error: edf_set_digital_maximum()\n");

      return(1);
    }
  }

  for(i=0; i<chns; i++)
  {
    if(edf_set_digital_minimum(hdl, i, -8388608))
    {
      printf("error: edf_set_digital_minimum()\n");

      return(1);
    }
  }
#else
  for(i=0; i<chns; i++)
  {
    if(edf_set_digital_maximum(hdl, i, 32767))
    {
      printf("error: edf_set_digital_maximum()\n");

      return(1);
    }
  }

  for(i=0; i<chns; i++)
  {
    if(edf_set_digital_minimum(hdl, i, -32768))
    {
      printf("error: edf_set_digital_minimum()\n");

      return(1);
    }
  }
#endif

  for(i=0; i<chns; i++)
  {
    if(edf_set_physical_maximum(hdl, i, 400.0))
    {
      printf("error: edf_set_physical_maximum()\n");

      return(1);
    }
  }

  for(i=0; i<chns; i++)
  {
    if(edf_set_physical_minimum(hdl, i, -400.0))
    {
      printf("error: edf_set_physical_minimum()\n");

      return(1);
    }
  }

  for(i=0; i<chns; i++)
  {
    if(edf_set_physical_dimension(hdl, i, "uV"))
    {
      printf("error: edf_set_physical_dimension()\n");

      return(1);
    }
  }

  if(edf_set_label(hdl, 0, "sweep"))
  {
    printf("error: edf_set_label()\n");

    return(1);
  }

  if(edf_set_equipment(hdl, "Software generated file"))
  {
    printf("edf_set_equipment()\n");

    return(1);
  }

  if(linear)
  {
    sprintf(str, "Linear frequency sweep from %fHz to %fHz", startfreq, stopfreq);
  }
  else
  {
    sprintf(str, "Logarithmic frequency sweep from %fHz to %fHz", startfreq, stopfreq);
  }
  remove_trailing_zeros(str);
  edf_set_patientname(hdl, str);

  edfwrite_annotation_latin1(hdl, 0LL, -1LL, "Recording starts");

  sine_1 = 0.0;

  sampleswritten = 0;

  samples = fileduration * (long long)smp_freq;

  freqspan = stopfreq - startfreq;

  for(j=0; j<fileduration; j++)
  {
    for(i=0; i<smp_freq; i++)
    {
      q = M_PI * 2.0;
      q /= (smp_freq / freq);
      sine_1 += q;
      q = sin(sine_1);
      q *= 200.0;
      buf[i] = q;
      if(linear)
      {
        freq = startfreq + (freqspan * ((double)sampleswritten / (double)samples));
      }
      else
      {
//        freq = exp10((((double)sampleswritten / (double)samples)) * log10(stopfreq));
        freq = exp10(((((startfreq / stopfreq) * ((stopfreq / freqspan) * samples)) + sampleswritten) / ((stopfreq / freqspan) * samples)) * log10(stopfreq));
      }
      sampleswritten++;
    }

    if(edfwrite_physical_samples(hdl, buf))
    {
      printf("error: edfwrite_physical_samples()\n");

      return(1);
    }

    if(!(j%10))
    {
      sprintf(str, "%fHz", freq);
      remove_trailing_zeros(str);
      edfwrite_annotation_latin1(hdl, j * 10000LL, -1LL, str);
    }
  }

  sprintf(str, "%fHz", freq);
  remove_trailing_zeros(str);
  edfwrite_annotation_latin1(hdl, j * 10000LL, -1LL, str);

  edfwrite_annotation_latin1(hdl, fileduration * 10000LL, -1LL, "Recording ends");

  edfclose_file(hdl);

  return(0);
}
/* ==================================================================== */
int sci_edf_set_patientname(char *fname)
{
  SciErr sciErr;
  
  int m1 = 0, n1 = 0;
  int *piAddressVarOne = NULL;
  int* piLenVarOne = NULL;
  double *pdVarOne = NULL;
  int iType1 = 0;  
  
  int m2 = 0, n2 = 0;
  int *piAddressVarTwo = NULL;
  int* piLenVarTwo = NULL;
   char **stringData  = NULL;
  int iType2 = 0;  
  

  int m_out = 0, n_out = 0;
  double *dOut = NULL;

  int i;
  int handle;

  /* --> result = csum(3,8)
  /* check that we have only 2 parameters input */
  /* check that we have only 1 parameters output */
  CheckInputArgument(pvApiCtx,2,2) ;
  CheckOutputArgument(pvApiCtx,1,1) ;   
  
  /* get Address of inputs */
  sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddressVarOne);
  if(sciErr.iErr)
  {
    printError(&sciErr, 0);
    return 0;
  }
  
  sciErr = getVarAddressFromPosition(pvApiCtx, 2, &piAddressVarTwo);
  if(sciErr.iErr)
  {
    printError(&sciErr, 0);
    return 0;
  }
  
  

  /* check input type */
  sciErr = getVarType(pvApiCtx, piAddressVarOne, &iType1);
  if(sciErr.iErr)
  {
    printError(&sciErr, 0);
    return 0;
  } 
   
  if ( iType1 != sci_matrix )
  {
    Scierror(999,"%s: Wrong type for input argument #%d: A integer expected.\n",fname,1);
    return 0;
  }

  sciErr = getVarType(pvApiCtx, piAddressVarTwo, &iType2);
  if(sciErr.iErr)
  {
    printError(&sciErr, 0);
    return 0;
  }   
  
  if ( iType2 != sci_strings )
  {
  	Scierror(999,"%s: Wrong type for input argument #%d: A string expected.\n",fname,2);
  	return 0;
  }




  sciErr = getMatrixOfDouble(pvApiCtx, piAddressVarOne,&m1,&n1,&pdVarOne);
  if(sciErr.iErr)
  {
    printError(&sciErr, 0);
    return 0;
  }


  
 /* get string */
    sciErr = getMatrixOfString(pvApiCtx, piAddressVarTwo,&m2, &n2, NULL, NULL);
  if(sciErr.iErr)
  {
    printError(&sciErr, 0);
    return 0;
  }

    piLenVarTwo = (int*)malloc(sizeof(int) * m2 * n2);
   sciErr = getMatrixOfString(pvApiCtx, piAddressVarTwo, &m2, &n2, piLenVarTwo, NULL);
                if(sciErr.iErr)
                {
                        printError(&sciErr, 0);
                        return 0;
                }

                stringData = (char**)malloc(sizeof(char*) * m2 * n2);
                for(i = 0 ; i < n2 * m2 ; i++)
                {
                        stringData[i] = (char*)malloc(sizeof(char) * (piLenVarTwo[i] + 1));//+ 1 for null termination
                }

                sciErr = getMatrixOfString(pvApiCtx, piAddressVarTwo, &m2, &n2, piLenVarTwo, stringData);
                if(sciErr.iErr)
                {
                        printError(&sciErr, 0);
                        return 0;
                }




  
  /* check size */
  if ( (m1 != 1) || (n1 != 1) ) 
  {
  	Scierror(999,"%s: Wrong size for input argument #%d: A scalar expected.\n",fname,1);
  	return 0;
  }
  if ( (m2 !=1) || (n2 !=1) ) 
  {
  	Scierror(999,"%s: Wrong size for input argument #%d: A single stringr expected.\n",fname,2);
  	return 0;
  }



  
  /* call c function csum */
//  csum(&pdVarOne[0],&pdVarTwo[0],&dOut);


if ( edf_set_patientname(pdVarOne[0],  stringData[0]) <0)
{
     Scierror(999,"Could not write string\n");
    return 0;
}
  

  m_out = 1;  n_out = 1;

  dOut =  (double*)malloc(sizeof(double) * m_out*n_out);
 // CreateVar(1, MATRIX_OF_DOUBLE_DATATYPE, &m_out, &n_out, &dout);
  dOut[0]=0;  
  /* create result on stack */
  createMatrixOfDouble(pvApiCtx, nbInputArgument(pvApiCtx) + 1, m_out, n_out, dOut);
 
  free(dOut);
  AssignOutputVariable(pvApiCtx,1) = nbInputArgument(pvApiCtx) + 1; 
  
  /* This function put on scilab stack, the lhs variable
  which are at the position lhs(i) on calling stack */
  /* You need to add PutLhsVar here because WITHOUT_ADD_PUTLHSVAR 
  was defined and equal to %t */
  /* without this, you do not need to add PutLhsVar here */
  ReturnArguments(pvApiCtx);
  
  return 0;
}
Example #7
0
void UI_WAV2EDFwindow::SelectFileButton()
{
  FILE *inputfile=NULL;

  int i, j,
      edfsignals,
      sf,
      resolution,
      edf_hdl,
      readbufsize,
      *writebuf,
      bytes_per_sample,
      sf_divider;

unsigned int fmt_chunk_offset,
             data_chunk_offset,
             tmp;

  char path[MAX_PATH_LENGTH],
       outputfilename[MAX_PATH_LENGTH],
       scratchpad[512],
       *readbuf;

  long long blocks,
            leftover,
            progress_steps,
            k;

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


  enable_widgets(false);

  if(!(strlen(PatientnameLineEdit->text().toLatin1().data())))
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a subject name.");
    messagewindow.exec();
    enable_widgets(true);
    return;
  }

  if(!(strlen(RecordingLineEdit->text().toLatin1().data())))
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a recording description.");
    messagewindow.exec();
    enable_widgets(true);
    return;
  }

  strcpy(path, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "Text files (*.wav *.WAV)").toLocal8Bit().data());

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

  get_directory_from_path(recent_opendir, path, MAX_PATH_LENGTH);

  inputfile = fopeno(path, "rb");
  if(inputfile==NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading.");
    messagewindow.exec();
    enable_widgets(true);
    return;
  }

/***************** check if the wavefile is valid ******************************/

  rewind(inputfile);

  if(fread(scratchpad, 256, 1, inputfile)!=1)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile.");
    messagewindow.exec();
    fclose(inputfile);
    enable_widgets(true);
    return;
  }

  if((strncmp(scratchpad, "RIFF", 4)) || (strncmp(scratchpad + 8, "WAVE", 4)))
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "File is not a Wave file.");
    messagewindow.exec();
    fclose(inputfile);
    enable_widgets(true);
    return;
  }

  fmt_chunk_offset = 12;

  while(1)
  {
    fseeko(inputfile, (long long)fmt_chunk_offset, SEEK_SET);

    if(fread(scratchpad, 256, 1, inputfile)!=1)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find fmt chunk.");
      messagewindow.exec();
      fclose(inputfile);
      enable_widgets(true);
      return;
    }

    if(strncmp(scratchpad, "fmt ", 4) == 0)
    {
      break;
    }

    tmp = *((unsigned int *)(scratchpad + 4));
    if(tmp < 2)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find fmt chunk.");
      messagewindow.exec();
      fclose(inputfile);
      enable_widgets(true);
      return;
    }

    if(tmp & 1)
    {
      tmp++;
    }

    fmt_chunk_offset += (tmp + 8);
  }

  if(*((signed short *)(scratchpad + 8)) != 1)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "File contains compressed data.\nCan not convert compressed data.");
    messagewindow.exec();
    fclose(inputfile);
    enable_widgets(true);
    return;
  }

  edfsignals = *((unsigned short *)(scratchpad + 10));

  if(edfsignals < 1)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Channels < 1");
    messagewindow.exec();
    fclose(inputfile);
    enable_widgets(true);
    return;
  }

  if(edfsignals > MAXSIGNALS)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Channels > MAXSIGNALS");
    messagewindow.exec();
    fclose(inputfile);
    enable_widgets(true);
    return;
  }

  sf = *((unsigned int *)(scratchpad + 12));

  if(sf < 1)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Samplefrequency < 1");
    messagewindow.exec();
    fclose(inputfile);
    enable_widgets(true);
    return;
  }

  if(sf > 500000)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Samplefrequency > 500000");
    messagewindow.exec();
    fclose(inputfile);
    enable_widgets(true);
    return;
  }

  resolution = *((unsigned short *)(scratchpad + 22));

  if(resolution < 8)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Resolution < 8 bit");
    messagewindow.exec();
    fclose(inputfile);
    enable_widgets(true);
    return;
  }

  if(resolution > 24)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Resolution > 24");
    messagewindow.exec();
    fclose(inputfile);
    enable_widgets(true);
    return;
  }

  if((resolution != 8) && (resolution != 16)  && (resolution != 24))
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Resolution (bitdepth) must be 8, 16 or 24 bit.");
    messagewindow.exec();
    fclose(inputfile);
    enable_widgets(true);
    return;
  }

  bytes_per_sample = 2;

  if(resolution > 16)
  {
    bytes_per_sample = 3;
  }

  if(resolution < 9)
  {
    bytes_per_sample = 1;
  }

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

  data_chunk_offset = 12;

  while(1)
  {
    fseeko(inputfile, (long long)data_chunk_offset, SEEK_SET);

    if(fread(scratchpad, 256, 1, inputfile)!=1)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find data chunk.");
      messagewindow.exec();
      fclose(inputfile);
      enable_widgets(true);
      return;
    }

    if(strncmp(scratchpad, "data", 4) == 0)
    {
      break;
    }

    tmp = *((unsigned int *)(scratchpad + 4));
    if(tmp < 2)
    {
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find data chunk.");
      messagewindow.exec();
      fclose(inputfile);
      enable_widgets(true);
      return;
    }

    if(tmp & 1)
    {
      tmp++;
    }

    data_chunk_offset += (tmp + 8);
  }

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

  sf_divider = 1;

  if((sf % 10) == 0)
  {
    sf_divider = 10;

    sf /= 10;
  }

  blocks = (long long)(*((int *)(scratchpad + 4)));

  blocks /= (sf * edfsignals * bytes_per_sample);

  fseeko(inputfile, 0LL, SEEK_END);

  leftover = ftello(inputfile) - (long long)data_chunk_offset - 8LL;

  leftover /= (sf * edfsignals * bytes_per_sample);

  if(blocks > leftover)
  {
    blocks = leftover;
  }

  if(blocks < 1LL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Not enough data in file.");
    messagewindow.exec();
    fclose(inputfile);
    enable_widgets(true);
    return;
  }

  readbufsize = bytes_per_sample * sf * edfsignals;

  readbuf = (char *)malloc(readbufsize);
  if(readbuf == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (readbuf).");
    messagewindow.exec();
    fclose(inputfile);
    enable_widgets(true);
    return;
  }

  writebuf = (int *)malloc(sf * edfsignals * sizeof(int));
  if(writebuf == NULL)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (writebuf).");
    messagewindow.exec();
    free(readbuf);
    fclose(inputfile);
    enable_widgets(true);
    return;
  }

//  printf("resolution is %i    edfsignals is %i    sf is %i    blocks is %lli\n", resolution, edfsignals, sf, blocks);

/***************** create a new EDF file *****************************************/

  get_filename_from_path(outputfilename, path, MAX_PATH_LENGTH);
  remove_extension_from_filename(outputfilename);
  if(resolution > 16)
  {
    strcat(outputfilename, ".bdf");
  }
  else
  {
    strcat(outputfilename, ".edf");
  }

  path[0] = 0;
  if(recent_savedir[0]!=0)
  {
    strcpy(path, recent_savedir);
    strcat(path, "/");
  }
  strcat(path, outputfilename);

  if(resolution > 16)
  {
    strcpy(path, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(path), "BDF files (*.bdf *.BDF)").toLocal8Bit().data());
  }
  else
  {
    strcpy(path, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(path), "EDF files (*.edf *.EDF)").toLocal8Bit().data());
  }

  if(!strcmp(path, ""))
  {
    enable_widgets(true);
    fclose(inputfile);
    return;
  }

  get_directory_from_path(recent_savedir, path, MAX_PATH_LENGTH);

  if(resolution > 16)
  {
    edf_hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_BDFPLUS, edfsignals);
  }
  else
  {
    edf_hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_EDFPLUS, edfsignals);
  }

  if(edf_hdl < 0)
  {
    QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open output file for writing.");
    messagewindow.exec();
    fclose(inputfile);
    free(readbuf);
    free(writebuf);
    enable_widgets(true);
    return;
  }

  for(i=0; i<edfsignals; i++)
  {
    edf_set_samplefrequency(edf_hdl, i, sf);
  }

  if(sf_divider != 1)
  {
    edf_set_datarecord_duration(edf_hdl, 100000 / sf_divider);
  }

  for(i=0; i<edfsignals; i++)
  {
    if(resolution > 16)
    {
      edf_set_digital_maximum(edf_hdl, i, 8388607);
    }
    else
    {
      if(resolution < 9)
      {
        edf_set_digital_maximum(edf_hdl, i, 127);
      }
      else
      {
        edf_set_digital_maximum(edf_hdl, i, 32767);
      }
    }
  }

  for(i=0; i<edfsignals; i++)
  {
    if(resolution > 16)
    {
      edf_set_digital_minimum(edf_hdl, i, -8388608);
    }
    else
    {
      if(resolution < 9)
      {
        edf_set_digital_minimum(edf_hdl, i, -128);
      }
      else
      {
        edf_set_digital_minimum(edf_hdl, i, -32768);
      }
    }
  }

  for(i=0; i<edfsignals; i++)
  {
    edf_set_physical_maximum(edf_hdl, i, PhysMaxSpinBox->value());
  }

  for(i=0; i<edfsignals; i++)
  {
    edf_set_physical_minimum(edf_hdl, i, PhysMaxSpinBox->value() * -1.0);
  }

  for(i=0; i<edfsignals; i++)
  {
    edf_set_physical_dimension(edf_hdl, i, PhysDimLineEdit->text().toLatin1().data());
  }

  for(i=0; i<edfsignals; i++)
  {
    sprintf(scratchpad, "channel %i", i + 1);

    edf_set_label(edf_hdl, i, scratchpad);
  }

  edf_set_patientname(edf_hdl, PatientnameLineEdit->text().toLatin1().data());

  edf_set_recording_additional(edf_hdl, RecordingLineEdit->text().toLatin1().data());

  edf_set_startdatetime(edf_hdl, StartDatetimeedit->date().year(), StartDatetimeedit->date().month(), StartDatetimeedit->date().day(),
                        StartDatetimeedit->time().hour(), StartDatetimeedit->time().minute(), StartDatetimeedit->time().second());

  edfwrite_annotation_latin1(edf_hdl, 0LL, -1, "Recording starts");

/***************** start conversion **************************************/

  fseeko(inputfile, (long long)data_chunk_offset + 8LL, SEEK_SET);

  QProgressDialog progress("Converting a Wave file ...", "Abort", 0, (int)blocks, myobjectDialog);
  progress.setWindowModality(Qt::WindowModal);
  progress.setMinimumDuration(200);

  progress_steps = blocks / 100LL;
  if(progress_steps < 1LL)
  {
    progress_steps = 1LL;
  }

  for(k=0LL; k<blocks; k++)
  {
    if(!(k%progress_steps))
    {
      progress.setValue((int)k);

      qApp->processEvents();

      if(progress.wasCanceled() == true)
      {
        edfclose_file(edf_hdl);
        fclose(inputfile);
        free(readbuf);
        free(writebuf);
        enable_widgets(true);
        return;
      }
    }

    if(fread(readbuf, readbufsize, 1, inputfile)!=1)
    {
      progress.reset();
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "A read error occurred during conversion.");
      messagewindow.exec();
      edfclose_file(edf_hdl);
      fclose(inputfile);
      free(readbuf);
      free(writebuf);
      enable_widgets(true);
      return;
    }

    if(bytes_per_sample == 1)
    {
      for(i=0; i<sf; i++)
      {
        for(j=0; j<edfsignals; j++)
        {
          writebuf[i + (j * sf)] = (signed char)(*(readbuf + (i * edfsignals) + j) + 128);
        }
      }
    }

    if(bytes_per_sample == 2)
    {
      for(i=0; i<sf; i++)
      {
        for(j=0; j<edfsignals; j++)
        {
          writebuf[i + (j * sf)] = *(((signed short *)readbuf) + (i * edfsignals) + j);
        }
      }
    }

    if(bytes_per_sample == 3)
    {
      for(i=0; i<sf; i++)
      {
        for(j=0; j<edfsignals; j++)
        {
          var.two[0] = *((unsigned short *)(readbuf + (i * edfsignals) + (j * 3)));

          var.four[2] = *((unsigned char *)(readbuf + (i * edfsignals * 3) + (j * 3) + 2));

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

          writebuf[i + (j * sf)] = var.one_signed;
        }
      }
    }

    if(edf_blockwrite_digital_samples(edf_hdl, writebuf))
    {
      progress.reset();
      QMessageBox messagewindow(QMessageBox::Critical, "Error", "A write error occurred during conversion.");
      messagewindow.exec();
      edfclose_file(edf_hdl);
      fclose(inputfile);
      free(readbuf);
      free(writebuf);
      enable_widgets(true);
      return;
    }
  }

  progress.reset();

  edfwrite_annotation_latin1(edf_hdl, (blocks * 10000LL) / sf_divider, -1, "Recording ends");

  edfclose_file(edf_hdl);

  fclose(inputfile);

  QMessageBox messagewindow(QMessageBox::Information, "Ready", "Done.");
  messagewindow.setIconPixmap(QPixmap(":/images/ok.png"));
  messagewindow.exec();

  free(readbuf);
  free(writebuf);

  enable_widgets(true);
}