int configure_channels(struct xdf* xdf, unsigned int neeg, unsigned int nsens) { unsigned int i; struct xdfch* ch = NULL; /* Set the default settings of the next channels. There is no need to setup the stored data type (XDF_CF_STOTYPE) neither the digital min or max since BDF supports only int24 data type and those settings are thus set by default */ xdf_set_conf(xdf, XDF_CF_ARRTYPE, XDFFLOAT, XDF_CF_ARRINDEX, 0, XDF_CF_ARROFFSET, 0,/* starting offset (will be automatically incremented after a channel is added) */ XDF_CF_TRANSDUCTER, "Active Electrode", XDF_CF_PREFILTERING, "HP: DC; LP: 100 Hz", XDF_CF_PMIN, -2.0, XDF_CF_PMAX, 2.0, XDF_CF_UNIT, "uV", XDF_CF_RESERVED, "EEG", XDF_NOF); /* Add EEG channels */ for (i = 0; i < neeg; i++) if (xdf_add_channel(xdf, eeglabels[i]) == NULL) return -1;; /* Setup and add sensor channels */ xdf_set_conf(xdf, XDF_CF_ARRTYPE, XDFDOUBLE, XDF_CF_ARRINDEX, 1, XDF_CF_ARROFFSET, 0, XDF_NOF); for (i = 0; i < nsens; i++) if (xdf_add_channel(xdf, senslabels[i]) == NULL) return -1; /* Add and setup trigger channel (show another way to setup a channel) */ ch = xdf_add_channel(xdf, "Status"); if (ch == NULL) return -1; xdf_set_chconf(ch, XDF_CF_ARRTYPE, XDFINT32, XDF_CF_ARRINDEX, 2, XDF_CF_ARROFFSET, 0, XDF_CF_TRANSDUCTER, "Triggers and Status", XDF_CF_PREFILTERING, "No filtering", XDF_CF_PMIN, -8388608.0, XDF_CF_PMAX, 8388607.0, XDF_CF_UNIT, "Boolean", XDF_CF_RESERVED, "TRI", XDF_NOF); return 0; }
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; }