static void* acq_loop_fn(void* arg) { struct acq* acq = arg; struct eegdev* dev = acq->dev; void** buff = acq->buff; int lrun; ssize_t ns; while (1) { // Update status of the loop pthread_mutex_lock(&acq->lock); while (!(lrun = acq->running)) { pthread_cond_wait(&acq->cond, &acq->lock); } pthread_mutex_unlock(&acq->lock); if (lrun < 0) break; // Perform the actual transfer from dev to buffers ns = egd_get_data(dev, CHUNK_NS, buff[0], buff[1], buff[2]); if (ns <= 0) break; // Writes data to file if (xdf_write(acq->xdf, ns, buff[0], buff[1], buff[2]) < 0) break; // Execute callback if (acq->cb) acq->cb(acq->cbdata, ns, buff[0], buff[1], buff[2]); } return NULL; }
int copy_datastream(struct xdf* dst, struct xdf* src) { void* buffer = NULL; int nch; ssize_t nssrc, nsdst = 0; size_t samplesize, stride[1]; xdf_get_conf(src, XDF_F_NCHANNEL, &nch, XDF_NOF); samplesize = nch*sizeof(double); /* double is the biggest supported type */ buffer = malloc(samplesize*NSAMPLE); /* Prepare the data transfer */ stride[0] = samplesize; xdf_define_arrays(src, 1, stride); xdf_define_arrays(dst, 1, stride); xdf_prepare_transfer(src); xdf_prepare_transfer(dst); /* Data copy loop */ while (1) { nssrc = xdf_read(src, NSAMPLE, buffer); if (nssrc <= 0) break; nsdst = xdf_write(dst, nssrc, buffer); if (nsdst < 0) break; } free(buffer); return (nssrc < 0 || nsdst < 0) ? -1 : 0; }
int main(int argc, char *argv[]) { (void) argc; (void) argv; struct xdf *xdf = NULL; int step, retval = EXIT_FAILURE; unsigned int ns, i; size_t strides[NARRAYS] = { NEEG*sizeof(eeg[0]), NSENS*sizeof(sens[0]), sizeof(trigger[0]) }; /************************************************* * File preparation * *************************************************/ step = 0; xdf = xdf_open(filename, XDF_WRITE, XDF_BDF); if (xdf == NULL) goto exit; xdf_set_conf(xdf, XDF_F_SAMPLING_FREQ, FS, XDF_NOF); step++; if (configure_channels(xdf, NEEG, NSENS)) goto exit; step++; if (xdf_define_arrays(xdf, NARRAYS, strides) || xdf_prepare_transfer(xdf) ) goto exit; /************************************************ * Writing loop * *************************************************/ step++; for (i=0; i<TOTAL_NS; i+=NS) { ns = ((TOTAL_NS - i) >= NS) ? NS : (TOTAL_NS - i); generate_signal(NEEG, eeg, NSENS, sens, trigger, FS, ns); if (xdf_write(xdf, ns, eeg, sens, trigger) < 0) goto exit; } retval = EXIT_SUCCESS; exit: if (retval != EXIT_SUCCESS) { fprintf(stderr, "Error while %s : (%i) %s\n", stepmsg[step], errno, strerror(errno)); } xdf_close(xdf); return retval; }
int copy_xdf(const char* genfilename, const char* reffilename, int fformat) { struct xdf *dst = NULL, *src = NULL; struct xdfch *dstch, *srcch; unsigned int ich = 0, samplesize, evttype; int nch, retcode = -1; void* buffer = NULL; ssize_t nssrc, nsdst; size_t nstot, stride[1]; int i, nevent, nevtcode, evtcode, fdref, fdgen; double onset, duration; const char* desc; fdref = open(reffilename, O_RDONLY); src = xdf_fdopen(fdref, XDF_READ | XDF_CLOSEFD, fformat); if (!src) { fprintf(stderr, "\tFailed opening reference file: (%i) %s\n", errno, strerror(errno)); goto exit; } fdgen = open(genfilename, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); dst = xdf_fdopen(fdgen, XDF_WRITE | XDF_CLOSEFD, fformat); if (!dst) { fprintf(stderr, "\tFailed opening file for writing: (%i) %s\n", errno, strerror(errno)); goto exit; } // Copy header and configuration xdf_copy_conf(dst, src); while ((srcch = xdf_get_channel(src, ich))) { xdf_set_chconf(srcch, XDF_CF_ARRINDEX, 0, XDF_NOF); dstch = xdf_add_channel(dst, NULL); if (xdf_copy_chconf(dstch, srcch)) { fprintf(stderr, "\tFailed copying channel %i: (%i) %s\n", ich, errno, strerror(errno)); goto exit; } ich++; } xdf_get_conf(src, XDF_F_NCHANNEL, &nch, XDF_F_NEVENT, &nevent, XDF_F_NEVTTYPE, &nevtcode, XDF_NOF); if (nch != (int)ich) { fprintf(stderr, "\tich=%u, nch=%i\n", ich, nch); goto exit; } // Copy event code table for (i=0; i<nevtcode; i++) { if (xdf_get_evttype(src, i, &evtcode, &desc) < 0 || xdf_add_evttype(dst, evtcode, desc) < 0) goto exit; } samplesize = nch*4; buffer = malloc(samplesize*NSAMPLE); stride[0] = samplesize; xdf_define_arrays(src, 1, stride); xdf_define_arrays(dst, 1, stride); xdf_prepare_transfer(src); xdf_prepare_transfer(dst); if ( (xdf_seek(src, 1000, SEEK_CUR) < 0) || (xdf_seek(src, 0, SEEK_SET) < 0) ) { fprintf(stderr, "\txdf_seek function failed: %s\n", strerror(errno)); goto exit; } nstot = 0; while (1) { nssrc = xdf_read(src, NSAMPLE, buffer); if (nssrc < 0) { fprintf(stderr, "\tfailed reading a chunk of %i samples " "after %u samples\nerror caught (%i), %s\n", (int)NSAMPLE, (unsigned int)nstot, errno, strerror(errno)); goto exit; } if (nssrc == 0) break; nsdst = xdf_write(dst, nssrc, buffer); if (nsdst != nssrc) { fprintf(stderr, "\tfailed writing a chunk of %i samples " "after %i samples\nerror caught (%i), %s\n", (unsigned int)nssrc, (unsigned int)nstot, errno, strerror(errno)); goto exit; } nstot += nsdst; } for (i=0; i<nevent; i++) { if (xdf_get_event(src, i, &evttype, &onset, &duration) < 0 || xdf_add_event(dst, evttype, onset, duration) < 0) goto exit; } retcode = 0; exit: free(buffer); xdf_close(src); xdf_close(dst); return retcode; }
int generate_xdffile(const char* filename) { eeg_t* eegdata; sens_t* exgdata; tri1_t* tri1data; tri2_t* tri2data; int retcode = -1; struct xdf* xdf = NULL; int i,j, evttype1, evttype2; char tmpstr[16]; size_t strides[4] = { NEEG*sizeof(*eegdata), NEXG*sizeof(*exgdata), NTRI*sizeof(*tri1data), NTRI*sizeof(*tri2data), }; // Allocate the temporary buffers for samples eegdata = malloc(NEEG*NSAMPLE*sizeof(*eegdata)); exgdata = malloc(NEXG*NSAMPLE*sizeof(*exgdata)); tri1data = malloc(NTRI*NSAMPLE*sizeof(*tri1data)); tri2data = malloc(NTRI*NSAMPLE*sizeof(*tri2data)); if (!eegdata || !exgdata || !tri1data || !tri2data) goto exit; xdf = xdf_open(filename, XDF_WRITE, XDF_GDF1); if (!xdf) goto exit; xdf_set_conf(xdf, XDF_F_SAMPLING_FREQ, (int)SAMPLINGRATE, XDF_F_SESS_DESC, sess_str, XDF_F_SUBJ_DESC, subj_str, XDF_NOF); // Specify the structure (channels and sampling rate) if (set_default_analog(xdf, 0, EEG_TYPE)) goto exit; for (j=0; j<NEEG; j++) { sprintf(tmpstr, "EEG%i", j); if (!xdf_add_channel(xdf, tmpstr)) goto exit; } if (set_default_analog(xdf, 1, SENS_TYPE)) goto exit; for (j=0; j<NEXG; j++) { sprintf(tmpstr, "EXG%i", j); if (!xdf_add_channel(xdf, tmpstr)) goto exit; } if (set_default_trigger(xdf, 2, TRI1_TYPE, TRI1_MIN, TRI1_MAX)) goto exit; for (j=0; j<NTRI; j++) { sprintf(tmpstr, "TRI1%i", j); if (!xdf_add_channel(xdf, tmpstr)) goto exit; } if (set_default_trigger(xdf, 3, TRI2_TYPE, TRI2_MIN, TRI2_MAX)) goto exit; for (j=0; j<NTRI; j++) { sprintf(tmpstr, "TRI2%i", j); if (!xdf_add_channel(xdf, tmpstr)) goto exit; } // Add events code evttype1 = xdf_add_evttype(xdf, 0x101, NULL); evttype2 = xdf_add_evttype(xdf, 0x204, NULL); if (evttype1 < 0 || evttype2 < 0) goto exit; // Make the the file ready for accepting samples xdf_define_arrays(xdf, 4, strides); if (xdf_prepare_transfer(xdf) < 0) goto exit; // Feed with samples for (i=0; i<NITERATION; i++) { // Set data signals and unscaled them set_signal_values(eegdata, exgdata, tri1data, tri2data); if (xdf_write(xdf, NSAMPLE, eegdata, exgdata, tri1data, tri2data) < 0) goto exit; if (xdf_add_event(xdf, evttype1, NSAMPLE*i/(double)SAMPLINGRATE, -1) || xdf_add_event(xdf, evttype2, (NSAMPLE*(i+1)-1)/(double)SAMPLINGRATE, -1)) goto exit; } retcode = 0; exit: // if phase is non zero, a problem occured if (retcode) fprintf(stderr, "\terror: %s\n", strerror(errno)); // Clean the structures and ressources xdf_close(xdf); free(eegdata); free(exgdata); free(tri1data); free(tri2data); return retcode; }