int get_tal_timestamp_digit_cnt(struct edfhdrblock *hdr) { int timestamp_digits; char scratchpad[256]; long long time; if(hdr==NULL) { return(-1); } time = (hdr->datarecords * hdr->long_data_record_duration) / TIME_DIMENSION; #ifdef _WIN32 timestamp_digits = __mingw_snprintf(scratchpad, 256, "%lli", time); #else timestamp_digits = snprintf(scratchpad, 256, "%lli", time); #endif return(timestamp_digits); }
int save_annotations(UI_Mainwindow *mainwindow, FILE *outputfile, struct edfhdrblock *hdr, struct annotationblock *annotlist) { int i, j, k, n, p=0, new_edfsignals=0, signalslist[MAXSIGNALS], datarecords, annot_len, annot_smp_per_record, annot_recordsize, timestamp_decimals, timestamp_digits, annots_per_datrec, space, progress_steps; char *readbuf, scratchpad[256], *annot_buf; long long time; FILE *inputfile; struct annotationblock *annot; inputfile = hdr->file_hdl; for(i=0; i<hdr->edfsignals; i++) { if(!hdr->edfparam[i].annotation) { signalslist[new_edfsignals] = i; new_edfsignals++; } } datarecords = hdr->datarecords; time = (hdr->datarecords * hdr->long_data_record_duration) / TIME_DIMENSION; timestamp_decimals = get_tal_timestamp_decimal_cnt(hdr); if(timestamp_decimals < 0) { return(1); } timestamp_digits = get_tal_timestamp_digit_cnt(hdr); if(timestamp_digits < 0) { return(1); } annot = annotlist; annot_len = get_max_annotation_strlen(&annot); i = edfplus_annotation_count(&annot); annots_per_datrec = i / datarecords; if(i % datarecords) { annots_per_datrec++; } annot_recordsize = (annot_len * annots_per_datrec) + timestamp_digits + timestamp_decimals + 4; if(timestamp_decimals) { annot_recordsize++; } if(hdr->edf) { annot_smp_per_record = annot_recordsize / 2; if(annot_recordsize % annot_smp_per_record) { annot_smp_per_record++; annot_recordsize = annot_smp_per_record * 2; } } else { annot_smp_per_record = annot_recordsize / 3; if(annot_recordsize % annot_smp_per_record) { annot_smp_per_record++; annot_recordsize = annot_smp_per_record * 3; } } readbuf = (char *)malloc(hdr->recordsize); if(readbuf==NULL) { return(1); } annot_buf = (char *)malloc(annot_recordsize + 10); if(annot_buf==NULL) { free(readbuf); return(1); } /////////////////////////////////////////////////////////////////// rewind(outputfile); if(hdr->edf) { fprintf(outputfile, "0 "); } else { fprintf(outputfile, "XBIOSEMI"); rewind(outputfile); fputc(255, outputfile); fseeko(outputfile, 0LL, SEEK_END); } fseeko(inputfile, 8LL, SEEK_SET); if((hdr->edfplus)||(hdr->bdfplus)) { if(fread(scratchpad, 176, 1, inputfile)!=1) { free(readbuf); free(annot_buf); return(2); } if((hdr->genuine_nk) && (hdr->nk_triggers_read)) { space = 0; for(n=80; n<160; n++) { if(scratchpad[n] == ' ') { space++; if(space > 3) { break; } } } n += 14; if(n<150) { if(!strncmp(scratchpad + n, "EEG", 3)) { scratchpad[n] = 'e'; scratchpad[n+1] = 'e'; scratchpad[n+2] = 'g'; } } } if(fwrite(scratchpad, 176, 1, outputfile)!=1) { free(readbuf); free(annot_buf); return(3); } } else { sprintf(scratchpad, "X X X X "); if(fread(scratchpad + 8, 80, 1, inputfile)!=1) { free(readbuf); free(annot_buf); return(2); } if(fwrite(scratchpad, 80, 1, outputfile)!=1) { free(readbuf); free(annot_buf); return(3); } sprintf(scratchpad, "Startdate X X X X "); if(fread(scratchpad + 18, 80, 1, inputfile)!=1) { free(readbuf); free(annot_buf); return(2); } if(fwrite(scratchpad, 80, 1, outputfile)!=1) { free(readbuf); free(annot_buf); return(3); } if(fread(scratchpad, 16, 1, inputfile)!=1) { free(readbuf); free(annot_buf); return(2); } if(fwrite(scratchpad, 16, 1, outputfile)!=1) { free(readbuf); free(annot_buf); return(3); } } fprintf(outputfile, "%-8i", (new_edfsignals * 256) + 512); if(hdr->edf) { fprintf(outputfile, "EDF+C"); } else { fprintf(outputfile, "BDF+C"); } for(i=0; i<39; i++) { fputc(' ', outputfile); } fprintf(outputfile, "%-8i", datarecords); snprintf(scratchpad, 256, "%.12f", hdr->data_record_duration); remove_trailing_zeros(scratchpad); strcat(scratchpad, " "); if((!strncmp(scratchpad, "0.", 2)) && (scratchpad[8] != ' ')) { scratchpad[9] = 0; fprintf(outputfile, "%s", scratchpad + 1); } else { scratchpad[8] = 0; fprintf(outputfile, "%s", scratchpad); } fprintf(outputfile, "%-4i", new_edfsignals + 1); for(i=0; i<new_edfsignals; i++) { fprintf(outputfile, "%s", hdr->edfparam[signalslist[i]].label); } if(hdr->edf) { fprintf(outputfile, "%s", "EDF Annotations "); } else { fprintf(outputfile, "%s", "BDF Annotations "); } for(i=0; i<new_edfsignals; i++) { fprintf(outputfile, "%s", hdr->edfparam[signalslist[i]].transducer); } for(i=0; i<80; i++) { fputc(' ', outputfile); } for(i=0; i<new_edfsignals; i++) { fprintf(outputfile, "%s", hdr->edfparam[signalslist[i]].physdimension); } for(i=0; i<8; i++) { fputc(' ', outputfile); } for(i=0; i<new_edfsignals; i++) { snprintf(scratchpad, 256, "%f", hdr->edfparam[signalslist[i]].phys_min); for(k=0; k<8; k++) { if(scratchpad[k]=='.') { for(j=7; j>=0; j--) { if((scratchpad[j]!='.')&&(scratchpad[j]!='0')) { break; } if(scratchpad[j]=='.') { scratchpad[j] = ' '; break; } scratchpad[j] = ' '; } break; } scratchpad[8] = 0; } fprintf(outputfile, "%s", scratchpad); } fprintf(outputfile, "-1 "); for(i=0; i<new_edfsignals; i++) { snprintf(scratchpad, 256, "%f", hdr->edfparam[signalslist[i]].phys_max); for(k=0; k<8; k++) { if(scratchpad[k]=='.') { for(j=7; j>=0; j--) { if((scratchpad[j]!='.')&&(scratchpad[j]!='0')) { break; } if(scratchpad[j]=='.') { scratchpad[j] = ' '; break; } scratchpad[j] = ' '; } break; } } scratchpad[8] = 0; fprintf(outputfile, "%s", scratchpad); } fprintf(outputfile, "1 "); for(i=0; i<new_edfsignals; i++) { fprintf(outputfile, "%-8i", hdr->edfparam[signalslist[i]].dig_min); } if(hdr->edf) { fprintf(outputfile, "%s", "-32768 "); } else { fprintf(outputfile, "%s", "-8388608"); } for(i=0; i<new_edfsignals; i++) { fprintf(outputfile, "%-8i", hdr->edfparam[signalslist[i]].dig_max); } if(hdr->edf) { fprintf(outputfile, "%s", "32767 "); } else { fprintf(outputfile, "%s", "8388607 "); } for(i=0; i<new_edfsignals; i++) { fprintf(outputfile, "%s", hdr->edfparam[signalslist[i]].prefilter); } for(i=0; i<80; i++) { fputc(' ', outputfile); } for(i=0; i<new_edfsignals; i++) { fprintf(outputfile, "%-8i", hdr->edfparam[signalslist[i]].smp_per_record); } fprintf(outputfile, "%-8i", annot_smp_per_record); for(i=0; i<((new_edfsignals * 32) + 32); i++) { fputc(' ', outputfile); } /////////////////////////////////////////////////////////////////// QProgressDialog progress("Saving file...", "Abort", 0, datarecords, mainwindow); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); progress_steps = datarecords / 100; if(progress_steps < 1) { progress_steps = 1; } fseeko(inputfile, (long long)(hdr->hdrsize), SEEK_SET); annot = annotlist; time = hdr->starttime_offset; for(k=0; k<datarecords; k++) { if(!(k%progress_steps)) { progress.setValue(k); qApp->processEvents(); if(progress.wasCanceled() == true) { free(readbuf); free(annot_buf); return(4); } } if(fread(readbuf, hdr->recordsize, 1, inputfile) != 1) { free(readbuf); free(annot_buf); return(2); } if(hdr->edf) { for(i=0; i<new_edfsignals; i++) { for(j=0; j<hdr->edfparam[signalslist[i]].smp_per_record; j++) { fputc(*((unsigned char *)(readbuf + hdr->edfparam[signalslist[i]].buf_offset + (j * 2))), outputfile); fputc(*((unsigned char *)(readbuf + hdr->edfparam[signalslist[i]].buf_offset + (j * 2) + 1)), outputfile); } } } else { for(i=0; i<new_edfsignals; i++) { for(j=0; j<hdr->edfparam[signalslist[i]].smp_per_record; j++) { fputc(*((unsigned char *)(readbuf + hdr->edfparam[signalslist[i]].buf_offset + (j * 3))), outputfile); fputc(*((unsigned char *)(readbuf + hdr->edfparam[signalslist[i]].buf_offset + (j * 3) + 1)), outputfile); fputc(*((unsigned char *)(readbuf + hdr->edfparam[signalslist[i]].buf_offset + (j * 3) + 2)), outputfile); } } } #ifdef Q_OS_WIN32 switch(timestamp_decimals) { case 0 : p = __mingw_snprintf(annot_buf, 16, "+%lli", time / TIME_DIMENSION); break; case 1 : p = __mingw_snprintf(annot_buf, 16, "+%lli.%01lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 1000000LL); break; case 2 : p = __mingw_snprintf(annot_buf, 16, "+%lli.%02lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 100000LL); break; case 3 : p = __mingw_snprintf(annot_buf, 16, "+%lli.%03lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 10000LL); break; case 4 : p = __mingw_snprintf(annot_buf, 16, "+%lli.%04lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 1000LL); break; case 5 : p = __mingw_snprintf(annot_buf, 16, "+%lli.%05lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 100LL); break; case 6 : p = __mingw_snprintf(annot_buf, 16, "+%lli.%06lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 10LL); break; case 7 : p = __mingw_snprintf(annot_buf, 16, "+%lli.%07lli", time / TIME_DIMENSION, time % TIME_DIMENSION); break; } #else switch(timestamp_decimals) { case 0 : p = snprintf(annot_buf, 16, "+%lli", time / TIME_DIMENSION); break; case 1 : p = snprintf(annot_buf, 16, "+%lli.%01lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 1000000LL); break; case 2 : p = snprintf(annot_buf, 16, "+%lli.%02lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 100000LL); break; case 3 : p = snprintf(annot_buf, 16, "+%lli.%03lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 10000LL); break; case 4 : p = snprintf(annot_buf, 16, "+%lli.%04lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 1000LL); break; case 5 : p = snprintf(annot_buf, 16, "+%lli.%05lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 100LL); break; case 6 : p = snprintf(annot_buf, 16, "+%lli.%06lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 10LL); break; case 7 : p = snprintf(annot_buf, 16, "+%lli.%07lli", time / TIME_DIMENSION, time % TIME_DIMENSION); break; } #endif annot_buf[p++] = 20; annot_buf[p++] = 20; annot_buf[p++] = 0; if(annot!=NULL) { for(i=0; i<annots_per_datrec; i++) { if(annot!=NULL) { if(annot->onset<0) { #ifdef Q_OS_WIN32 p += __mingw_snprintf(annot_buf + p, 20, "-%lli.%07lli", -(annot->onset / TIME_DIMENSION), -(annot->onset % TIME_DIMENSION)); #else p += snprintf(annot_buf + p, 20, "-%lli.%07lli", -(annot->onset / TIME_DIMENSION), -(annot->onset % TIME_DIMENSION)); #endif } else { #ifdef Q_OS_WIN32 p += __mingw_snprintf(annot_buf + p, 20, "+%lli.%07lli", annot->onset / TIME_DIMENSION, annot->onset % TIME_DIMENSION); #else p += snprintf(annot_buf + p, 20, "+%lli.%07lli", annot->onset / TIME_DIMENSION, annot->onset % TIME_DIMENSION); #endif } for(j=0; j<7; j++) { if(annot_buf[p - j - 1] != '0') { break; } } if(j) { p -= j; if(j == 7) { p--; } } if(annot->duration[0]) { annot_buf[p++] = 21; p += sprintf(annot_buf + p, "%s", annot->duration); } annot_buf[p++] = 20; p += sprintf(annot_buf + p, "%s", annot->annotation); annot_buf[p++] = 20; annot_buf[p++] = 0; annot = annot->next_annotation; } } } for(; p<annot_recordsize; p++) { annot_buf[p] = 0; } if(fwrite(annot_buf, annot_recordsize, 1, outputfile) != 1) { free(readbuf); free(annot_buf); return(3); } time += hdr->long_data_record_duration; } progress.reset(); free(readbuf); free(annot_buf); return(0); }
int get_max_annotation_strlen(struct annotationblock **list) { int j, len, annot_descr_len=0, annot_duration_len=0, timestamp_digits=0, timestamp_decimals=0; char scratchpad[256]; struct annotationblock *annot; annot = list[0]; if(annot==NULL) { return(0); } while(annot!=NULL) { #ifdef _WIN32 len = __mingw_snprintf(scratchpad, 256, "%lli", annot->onset / TIME_DIMENSION); #else len = snprintf(scratchpad, 256, "%lli", annot->onset / TIME_DIMENSION); #endif if(len > timestamp_digits) { timestamp_digits = len; } j = 10; for(len=7; len>0; len--) { if(annot->onset % j) { break; } j *= 10; } if(len > timestamp_decimals) { timestamp_decimals = len; } len = strlen(annot->annotation); if(len>annot_descr_len) { annot_descr_len = len; } len = strlen(annot->duration); if(len>annot_duration_len) { annot_duration_len = len; } annot = annot->next_annotation; } if(annot_duration_len) { annot_duration_len++; } if(timestamp_decimals) { timestamp_decimals++; } // printf("annot_descr_len is %i\n" // "annot_duration_len is %i\n" // "timestamp_digits is %i\n" // "timestamp_decimals is %i\n", // annot_descr_len, // annot_duration_len, // timestamp_digits, // timestamp_decimals); return(annot_descr_len + annot_duration_len + timestamp_digits + timestamp_decimals + 4); }
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_OS_WIN32 __mingw_snprintf(str, 2048, "Done. Converted %lli 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(); }