Main Page | Data Structures | File List | Data Fields | Globals | Related Pages

openedf.c

Go to the documentation of this file.
00001 /*
00002 NeuroServer
00003  
00004 A collection of programs to translate between EEG data and TCP network
00005 messages. This is a part of the OpenEEG project, see http://openeeg.sf.net
00006 for details.
00007     
00008 Copyright (C) 2003, 2004 Rudi Cilibrasi (cilibrar@ofb.net)
00009      
00010 This library is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU Lesser General Public
00012 License as published by the Free Software Foundation; either
00013 version 2.1 of the License, or (at your option) any later version.
00014          
00015 This library is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 Lesser General Public License for more details.
00019              
00020 You should have received a copy of the GNU Lesser General Public
00021 License along with this library; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00023 */
00024                 
00025 #include <assert.h>
00026 #include <time.h>
00027 #include <stdio.h>
00028 #include <malloc.h>
00029 #include <string.h>
00030 #include <stdlib.h>
00031 #include <stdarg.h>
00032 #include <stddef.h>
00033 #include <openedf.h>
00034 #include <unistd.h>
00035 #include <edfmacros.h>
00036 #include <nsutil.h>
00037 
00038 #define MAXERRORLEN 1024
00039 
00040 static char errorBuffer[MAXERRORLEN];
00041 
00042 void setLastError(const char *fmt, ...);
00043 
00044 int EDFUnpackInt(const char *inp, int fieldLen)
00045 {
00046         return atoi(EDFUnpackString(inp, fieldLen));
00047 }
00048 
00049 double EDFUnpackDouble(const char *inp, int fieldLen)
00050 {
00051         return atof(EDFUnpackString(inp, fieldLen));
00052 }
00053 
00054 const char *EDFUnpackString(const char *inp, int fieldLen)
00055 {
00056         static char retbuf[256];
00057         strncpy(retbuf, inp, fieldLen);
00058         retbuf[fieldLen] = '\0';
00059         return retbuf;
00060 }
00061 
00062 void storeEDFString(char *packet, size_t memsize, const char *str)
00063 {
00064         char fmt[8];
00065         char buf[257];
00066         sprintf(fmt, "%%- %ds", memsize);
00067         sprintf(buf, fmt, str);
00068         memcpy(packet, buf, memsize);
00069 }
00070 
00071 // TODO: Make this more correct for combinations of d and memsize
00072 void storeEDFDouble(char *packet, size_t memsize, double d)
00073 {
00074         char buf[64];
00075         sprintf(buf, "%g", d);
00076         storeEDFString(packet, memsize, buf);
00077 }
00078 
00079 void storeEDFInt(char *packet, size_t memsize, int i)
00080 {
00081         char buf[64];
00082         sprintf(buf, "%d", i);
00083         storeEDFString(packet, memsize, buf);
00084 }
00085 
00086 int EDFEncodePacket(char *packet, const struct EDFDecodedConfig *cfg)
00087 {
00088         int whichChannel, totalChannels;
00089         STOREHFS(dataFormat, cfg->hdr.dataFormat);
00090         STOREHFS(localPatient, cfg->hdr.localPatient);
00091         STOREHFS(localRecorder, cfg->hdr.localRecorder);
00092         STOREHFS(recordingStartDate, cfg->hdr.recordingStartDate);
00093         STOREHFS(recordingStartTime, cfg->hdr.recordingStartTime);
00094         STOREHFI(headerRecordBytes, cfg->hdr.headerRecordBytes);
00095         STOREHFS(manufacturerID, cfg->hdr.manufacturerID);
00096         STOREHFI(dataRecordCount, cfg->hdr.dataRecordCount);
00097         STOREHFD(dataRecordSeconds, cfg->hdr.dataRecordSeconds);
00098         STOREHFI(dataRecordChannels, cfg->hdr.dataRecordChannels);
00099         totalChannels = cfg->hdr.dataRecordChannels;
00100         packet += 256;
00101         for (whichChannel = 0; whichChannel < totalChannels; whichChannel++) {
00102                 STORECFS(label, cfg->chan[whichChannel].label);
00103                 STORECFS(transducer, cfg->chan[whichChannel].transducer);
00104                 STORECFS(dimUnit, cfg->chan[whichChannel].dimUnit);
00105                 STORECFD(physMin, cfg->chan[whichChannel].physMin);
00106                 STORECFD(physMax, cfg->chan[whichChannel].physMax);
00107                 STORECFD(digiMin, cfg->chan[whichChannel].digiMin);
00108                 STORECFD(digiMax, cfg->chan[whichChannel].digiMax);
00109                 STORECFS(prefiltering, cfg->chan[whichChannel].prefiltering);
00110                 STORECFI(sampleCount, cfg->chan[whichChannel].sampleCount);
00111                 STORECFS(reserved, cfg->chan[whichChannel].reserved);
00112         }
00113         return 0;
00114 }
00115 
00116 void EDFDecodeChannelHeader(struct EDFDecodedChannelHeader *result, const char *packet, int whichChannel, int totalChannels)
00117 {
00118         memset((char *) result, 0, sizeof(*result));
00119         LOADCFS(label);
00120         LOADCFS(transducer);
00121         LOADCFS(dimUnit);
00122         LOADCFD(physMin);
00123         LOADCFD(physMax);
00124         LOADCFD(digiMin);
00125         LOADCFD(digiMax);
00126         LOADCFS(prefiltering);
00127         LOADCFI(sampleCount);
00128         LOADCFS(reserved);
00129 }
00130 
00131 void EDFDecodeHeaderPreamble(struct EDFDecodedHeader *result, const char *packet) {
00132         memset((char *) result, 0, sizeof(*result));
00133         LOADHFS(dataFormat);
00134         LOADHFS(localPatient);
00135         LOADHFS(localRecorder);
00136         LOADHFS(recordingStartDate);
00137         LOADHFS(recordingStartTime);
00138         LOADHFI(headerRecordBytes);
00139         LOADHFS(manufacturerID);
00140         LOADHFI(dataRecordCount);
00141         LOADHFD(dataRecordSeconds);
00142         LOADHFI(dataRecordChannels);
00143 }
00144 
00145 int readEDFString(struct EDFDecodedConfig *cfg, const char *buf, int len)
00146 {
00147         int i;
00148         if (len >= 256)
00149                 EDFDecodeHeaderPreamble(&cfg->hdr, buf);
00150         else {
00151                 rprintf("Header too small\n");
00152                 return 1;
00153         }
00154         assert(cfg->hdr.dataRecordChannels > 0);
00155         assert(cfg->hdr.dataRecordChannels < MAXCHANNELS);
00156         setEDFHeaderBytes(cfg);
00157         if (len < cfg->hdr.headerRecordBytes) {
00158                 rprintf("Header too small\n");
00159                 return 1;
00160         }
00161         for (i = 0; i < cfg->hdr.dataRecordChannels; ++i) {
00162                 EDFDecodeChannelHeader(&cfg->chan[i], buf+256, i, cfg->hdr.dataRecordChannels);
00163         }
00164         return 0;
00165 }
00166 
00167 int writeEDFString(const struct EDFDecodedConfig *cfg, char *buf, int *buflen)
00168 {
00169         int retval;
00170         char pktbuf[(MAXCHANNELS+1) * 256];
00171         retval = EDFEncodePacket(pktbuf, cfg);
00172         if (retval) return retval;
00173         if (cfg->hdr.headerRecordBytes <= *buflen) {
00174                 *buflen = cfg->hdr.headerRecordBytes;
00175                 memcpy(buf, pktbuf, *buflen);
00176                 return 0;
00177         }
00178         else {
00179                 *buflen = 0;
00180                 return 1;
00181         }
00182 }
00183 
00184 int writeEDF(int fd, const struct EDFDecodedConfig *cfg)
00185 {
00186         int retval;
00187         char pktbuf[(MAXCHANNELS+1) * 256];
00188         retval = EDFEncodePacket(pktbuf, cfg);
00189         if (retval) return retval;
00190         retval = write(fd, pktbuf, cfg->hdr.headerRecordBytes);
00191         if (retval != cfg->hdr.headerRecordBytes) {
00192                 perror("write");
00193                 return 1;
00194         }
00195         return 0;
00196 }
00197 
00198 int setEDFHeaderBytes(struct EDFDecodedConfig *cfg)
00199 {
00200         cfg->hdr.headerRecordBytes = 256 * (cfg->hdr.dataRecordChannels + 1);
00201         return 0;
00202 }
00203 
00204 int readEDF(int fd, struct EDFDecodedConfig *cfg)
00205 {
00206         int i;
00207         int retval;
00208         char pktbuf[(MAXCHANNELS+1) * 256];
00209         retval = read(fd, pktbuf, 256);
00210         if (retval != 256) {
00211                 perror("read");
00212                 return 1;
00213         }
00214         EDFDecodeHeaderPreamble(&cfg->hdr, pktbuf);
00215         assert(cfg->hdr.dataRecordChannels > 0);
00216         assert(cfg->hdr.dataRecordChannels < MAXCHANNELS);
00217         setEDFHeaderBytes(cfg);
00218         retval = read(fd, pktbuf+256, cfg->hdr.headerRecordBytes - 256);
00219         if (retval != cfg->hdr.headerRecordBytes - 256) {
00220                 perror("read");
00221                 return 1;
00222         }
00223         for (i = 0; i < cfg->hdr.dataRecordChannels; ++i) {
00224                 EDFDecodeChannelHeader(&cfg->chan[i], pktbuf+256, i, cfg->hdr.dataRecordChannels);
00225         }
00226         return 0;
00227 }
00228 
00229 
00230 double getSecondsPerSample(const struct EDFDecodedConfig *cfg, int whichChan)
00231 {
00232         return (double) cfg->hdr.dataRecordSeconds / cfg->chan[whichChan].sampleCount;
00233 }
00234 
00235 double getSamplesPerSecond(const struct EDFDecodedConfig *cfg, int whichChan)
00236 {
00237         return (double) cfg->chan[whichChan].sampleCount / cfg->hdr.dataRecordSeconds;
00238 }
00239 
00240 int getDataRecordChunkSize(const struct EDFDecodedConfig *cfg)
00241 {
00242         int i, sum=0;
00243         for (i = 0; i < cfg->hdr.dataRecordChannels; ++i)
00244                 sum += cfg->chan[i].sampleCount;
00245         return sum * BYTESPERSAMPLE;
00246 }
00247 
00248 struct EDFInputIterator *newEDFInputIterator(const struct EDFDecodedConfig *cfg)
00249 {
00250         struct EDFInputIterator *edfi;
00251         edfi = calloc(1, sizeof(struct EDFInputIterator));
00252         assert(edfi && "out of memory!");
00253         edfi->cfg = *cfg;
00254         edfi->dataRecordNum = 0;
00255         edfi->sampleNum = 0;
00256         edfi->dataRecord = calloc(1, getDataRecordChunkSize(&edfi->cfg));
00257         assert(edfi->dataRecord && "out of memory!");
00258         return edfi;
00259 }
00260 
00261 void freeEDFInputIterator(struct EDFInputIterator *edfi)
00262 {
00263         free(edfi->dataRecord);
00264         edfi->dataRecord = NULL;
00265         free(edfi);
00266 }
00267 
00268 int stepEDFInputIterator(struct EDFInputIterator *edfi)
00269 {
00270         edfi->sampleNum += 1;
00271         if (edfi->sampleNum == edfi->cfg.chan[0].sampleCount) {
00272                 edfi->sampleNum = 0;
00273                 edfi->dataRecordNum += 1;
00274         }
00275         return 0;
00276 }
00277 
00278 
00279 int readDataRecord(const struct EDFInputIterator *edfi, FILE *fp)
00280 {
00281         int retval;
00282         retval = fseek(fp, 
00283                         edfi->cfg.hdr.headerRecordBytes + 
00284                         getDataRecordChunkSize(&edfi->cfg) * edfi->dataRecordNum,
00285                         SEEK_SET);
00286         if (retval != 0) return retval;
00287         retval = fread(edfi->dataRecord, 1, getDataRecordChunkSize(&edfi->cfg), fp);
00288         if (retval != getDataRecordChunkSize(&edfi->cfg))
00289                 return 1;
00290         return 0;
00291 }
00292 
00293 /* Assumes all channels sample at the same frequency */
00294 int fetchSamples(const struct EDFInputIterator *edfi, short *samples, FILE *fp)
00295 {
00296         int retval;
00297         int i;
00298         int sampleCount;
00299         if (edfi->sampleNum == 0) {
00300                 retval = readDataRecord(edfi, fp);
00301                 if (retval != 0) return retval;
00302         }
00303         sampleCount = edfi->cfg.chan[0].sampleCount;
00304         for (i = 0; i < edfi->cfg.hdr.dataRecordChannels; ++i) {
00305                 // TODO: Make this big-endian-safe
00306                 samples[i] = * (short *) 
00307                         (&edfi->dataRecord[BYTESPERSAMPLE*(edfi->sampleNum + i * sampleCount)]);
00308         }
00309         return 0;
00310 }
00311 
00312 int isValidREDF(const struct EDFDecodedConfig *cfg)
00313 {
00314         int i;
00315 /*      if (cfg->hdr.dataRecordSeconds != 1.0) {
00316                 setLastError("The data record must be exactly 1 second, not %f.", 
00317                                                                  cfg->hdr.dataRecordSeconds);
00318                 return 0;
00319         }
00320 */
00321         if (cfg->hdr.dataRecordChannels < 1) {
00322                 setLastError("The data record must have at least one channel.");
00323                 return 0;
00324         }
00325         if (cfg->chan[0].sampleCount < 1) {
00326                 setLastError("Channel 0 must have at least one sample.");
00327                 return 0;
00328         }
00329         for (i = 1; i < cfg->hdr.dataRecordChannels; ++i) {
00330                 if (cfg->chan[i].sampleCount != cfg->chan[0].sampleCount) {
00331                         setLastError("Channel %d has %d samples, but channel 0 has %d.  These must be the same.", cfg->chan[i].sampleCount, cfg->chan[0].sampleCount);
00332                         return 0;
00333                 }
00334         }
00335         return 1;
00336 }
00337 
00338 const char *getDMY(void)
00339 {
00340         static char buf[81];
00341         time_t t;
00342         struct tm *it;
00343         time(&t);
00344         it = localtime(&t);
00345         sprintf(buf, "%02d.%02d.%02d", it->tm_mday, it->tm_mon+1, it->tm_year % 100);
00346         return buf;
00347 }
00348 
00349 const char *getHMS(void)
00350 {
00351         static char buf[81];
00352         time_t t;
00353         struct tm *it;
00354         time(&t);
00355         it = localtime(&t);
00356         sprintf(buf, "%02d.%02d.%02d", it->tm_hour, it->tm_min, it->tm_sec);
00357         return buf;
00358 }
00359 
00360 /* Sets the header byte count correctly and sets the data record
00361  * duration to be 1 second and scaling sampleCount appropriately
00362  * for each channel.  This function assumes only one sampling rate
00363  * is used for all channels.  Also, sets the date and time correctly
00364  * according to the system clock.
00365  */
00366 
00367 int makeREDFConfig(struct EDFDecodedConfig *result, const struct EDFDecodedConfig *source)
00368 {
00369         //int newSamples, i;
00370         *result = *source;
00371 /*
00372         if (source->hdr.dataRecordSeconds != 1.0) {
00373                 result->hdr.dataRecordSeconds = 1;
00374                 newSamples = ((double)source->chan[0].sampleCount) / 
00375                                      source->hdr.dataRecordSeconds;
00376                 for (i = 0; i < source->hdr.dataRecordChannels; ++i)
00377                         result->chan[i].sampleCount = newSamples;
00378         }
00379 */
00380         setEDFHeaderBytes(result);
00381         strcpy(result->hdr.recordingStartDate, getDMY());
00382         strcpy(result->hdr.recordingStartTime, getHMS());
00383         assert(isValidREDF(result));
00384         return 0;
00385 }
00386 
00387 const char *getLastError(void)
00388 {
00389         return errorBuffer;
00390 }
00391 
00392 void setLastError(const char *fmt, ...)
00393 {
00394         va_list ap;
00395         va_start(ap, fmt);
00396         vsnprintf(errorBuffer, MAXERRORLEN-1, fmt, ap);
00397         errorBuffer[MAXERRORLEN-1] = '\0';
00398         va_end(ap);
00399 }
00400 

Generated on Tue Feb 8 00:05:16 2005 for Neuroserver by doxygen 1.3.3