NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
ReadWave.cpp
Go to the documentation of this file.
1// This file contains an example of reading a wave file.
2#include "./ReadWave.h"
3
4static void
5ReorderBytes(void *p, int bytesPerPoint, long numValues) // Reverses byte order.
6{
7 char ch, *p1, *p2;
8 unsigned char *pEnd;
9
10 pEnd = (unsigned char *)p + numValues*bytesPerPoint;
11 while (p < (void *)pEnd) {
12 p1 = (char *) p;
13 p2 = (char *)p + bytesPerPoint-1;
14 while (p1 < p2) {
15 ch = *p1;
16 *p1++ = *p2;
17 *p2-- = ch;
18 }
19 p = (unsigned char *)p + bytesPerPoint;
20 }
21}
22
23static void
24ReorderShort(void* sp)
25{
26 ReorderBytes(sp, 2, 1);
27}
28
29static void
30ReorderLong(void* lp)
31{
32 ReorderBytes(lp, 4, 1);
33}
34
35static void
37{
38 ReorderBytes(dp, 8, 1);
39}
40
41static void
43{
47}
48
49static void
51{
57}
58
59static void
61{
68}
69
70static void
72{
79 ReorderBytes(&p->dimEUnitsSize, 4, 4);
80 ReorderBytes(&p->dimLabelsSize, 4, 4);
84}
85
86static void
88{
89 ReorderShort(&p->type);
90 ReorderLong(&p->next);
91 // char bname does not need to be reordered.
95 // char dataUnits does not need to be reordered.
96 // char xUnits does not need to be reordered.
97 ReorderLong(&p->npnts);
99 ReorderDouble(&p->hsA);
100 ReorderDouble(&p->hsB);
106 // char useBits does not need to be reordered.
107 // char kindBits does not need to be reordered.
108 ReorderLong(&p->formula);
109 ReorderLong(&p->depID);
111 // char wUnused does not need to be reordered.
112 ReorderLong(&p->modDate);
114 // The wData field marks the start of the wave data which will be reordered separately.
115}
116
117static void
119{
120 ReorderLong(&p->next);
122 ReorderLong(&p->modDate);
123 ReorderLong(&p->npnts);
124 ReorderShort(&p->type);
125 ReorderShort(&p->dLock);
126 // char whpad1 does not need to be reordered.
128 // char bname does not need to be reordered.
129 ReorderLong(&p->whpad2);
130 ReorderLong(&p->dFolder);
131 ReorderBytes(&p->nDim, 4, 4);
132 ReorderBytes(&p->sfA, 8, 4);
133 ReorderBytes(&p->sfB, 8, 4);
134 // char dataUnits does not need to be reordered.
135 // char dimUnits does not need to be reordered.
137 ReorderShort(&p->whpad3);
141 ReorderBytes(&p->dimEUnits, 4, 4);
142 ReorderBytes(&p->dimLabels, 4, 4);
144 ReorderBytes(&p->whUnused, 4, 16);
148 // char useBits does not need to be reordered.
149 // char kindBits does not need to be reordered.
150 ReorderLong(&p->formula);
151 ReorderLong(&p->depID);
152 ReorderShort(&p->whpad4);
156 // The wData field marks the start of the wave data which will be reordered separately.
157}
158
159static int
160Checksum(short *data, int needToReorderBytes, int oldcksum, int numbytes)
161{
162 unsigned short s;
163
164 numbytes >>= 1; // 2 bytes to a short -- ignore trailing odd byte.
165 while(numbytes-- > 0) {
166 s = *data++;
167 if (needToReorderBytes)
168 ReorderShort(&s);
169 oldcksum += s;
170 }
171 return oldcksum&0xffff;
172}
173
174/* NumBytesPerPoint(int type)
175
176 Given a numeric wave type, returns the number of data bytes per point.
177*/
178static int
180{
181 int numBytesPerPoint;
182
183 // Consider the number type, not including the complex bit or the unsigned bit.
184 switch(type & ~(NT_CMPLX | NT_UNSIGNED)) {
185 case NT_I8:
186 numBytesPerPoint = 1; // char
187 break;
188 case NT_I16:
189 numBytesPerPoint = 2; // short
190 break;
191 case NT_I32:
192 numBytesPerPoint = 4; // long
193 break;
194 case NT_FP32:
195 numBytesPerPoint = 4; // float
196 break;
197 case NT_FP64:
198 numBytesPerPoint = 8; // double
199 break;
200 default:
201 return 0;
202 break;
203 }
204
205 if (type & NT_CMPLX)
206 numBytesPerPoint *= 2; // Complex wave - twice as many points.
207
208 return numBytesPerPoint;
209}
210
211/* LoadNumericWaveData(fr, type, npnts, waveDataSize, needToReorderBytes, pp)
212
213 fr is a file reference.
214 type is the Igor number type.
215 npnts is the total number of elements in all dimensions.
216 waveDataSize is the number of data bytes stored in the file.
217 needToReorderBytes if the byte ordering of the file is not the byte ordering of the current platform.
218 pp is a pointer to a pointer.
219
220 If an error occurs, LoadWaveData returns a non-zero error code and sets
221 *pp to NULL.
222
223 If no error occurs, LoadWaveData returns 0 and sets *pp to a pointer allocated
224 via malloc. This pointer must be freed by the calling routine.
225*/
226static int
227LoadNumericWaveData(CP_FILE_REF fr, int type, long npnts, unsigned long waveDataSize, int needToReorderBytes, void**pp)
228{
229 int numBytesPerPoint;
230 unsigned long numBytesToRead, numBytesToAllocate;
231 unsigned long numBytesRead;
232 void* p;
233 int err;
234
235 *pp = NULL; // Assume that we can not allocate memory.
236
237 numBytesPerPoint = NumBytesPerPoint(type);
238 if (numBytesPerPoint <= 0) {
239 printf("Invalid wave type (0x%x).\n", type);
240 return -1;
241 }
242 numBytesToRead = npnts * numBytesPerPoint;
243
244 numBytesToAllocate = numBytesToRead;
245 if (numBytesToAllocate == 0)
246 numBytesToAllocate = 8; // This is just because malloc refuses to allocate a zero byte block.
247 p = malloc(numBytesToAllocate); // Allocate memory to store the wave data.
248 if (p == NULL) {
249 printf("Unable to allocate %ld bytes to store data.\n", numBytesToAllocate);
250 return -1;
251 }
252 if (numBytesToRead > 0) {
253 if (waveDataSize < numBytesToRead) {
254 /* If here, this should be a wave governed by a dependency formula
255 for which no wave data was written to the file. Since we can't
256 execute the dependency formula we have no way to recreate the wave's
257 data. Therefore, we return 0 for all points in the wave.
258 */
259 memset(p, 0, numBytesToRead);
260 }
261 else {
262 if (err = CPReadFile(fr, numBytesToRead, p, &numBytesRead)) {
263 free(p);
264 printf("Error %d occurred while reading the wave data.\n", err);
265 return err;
266 }
267 if (needToReorderBytes) {
268 if (type != 0) // Text wave data does not need to be reordered.
269 ReorderBytes(p, numBytesPerPoint, numBytesToRead/numBytesPerPoint);
270 }
271 }
272 }
273
274 *pp = p; // Return the pointer to the calling routine.
275 return 0;
276}
277
278/* ReadWave(fr, typePtr, npntsPtr, waveDataPtrPtr)
279
280 Reads the wave file and prints some information about it.
281
282 Returns to the calling routine the wave's type, number of points, and the
283 wave data. The calling routine must free *waveDataPtrPtr if it is
284 not null.
285
286 Returns 0 or an error code.
287
288 This routine is written such that it could be used to read waves
289 from an Igor packed experiment file as well as from a standalone
290 Igor binary wave file. In order to achieve this, we must not assume
291 that the wave is at the start of the file. We do assume that, on entry
292 to this routine, the file position is at the start of the wave.
293*/
294int
295ReadWave(CP_FILE_REF fr, int* typePtr, long* npntsPtr, long* ndimptr, double* sfa, double* sfb, void** waveDataPtrPtr, char ** name)
296{
297 unsigned long startFilePos;
298 short version;
299 short check;
300 int binHeaderSize, waveHeaderSize, checkSumSize;
301 unsigned long waveDataSize;
302 unsigned long numBytesRead;
303 int needToReorderBytes;
304 char buffer[512];
305 unsigned long modDate;
306 long wfmSize;
307 long npnts;
308 int type;
309 int err;
310 (* name) = (char *) malloc(64);
311
312 *waveDataPtrPtr = NULL;
313 *typePtr = 0;
314 *npntsPtr = 0;
315
316 if (err = CPGetFilePosition(fr, &startFilePos))
317 return err;
318
319 // Read the file version field.
320 if (err = CPReadFile(fr, 2, &version, &numBytesRead)) {
321 printf("Error %d occurred while reading the file version.\n", err);
322 return err;
323 }
324
325 /* Reorder version field bytes if necessary.
326 If the low order byte of the version field of the BinHeader structure
327 is zero then the file is from a platform that uses different byte-ordering
328 and therefore all data will need to be reordered.
329 */
330 needToReorderBytes = (version & 0xFF) == 0;
331 if (needToReorderBytes)
333
334 // Check the version.
335 switch(version) {
336 case 1:
337 //printf("This is a version 1 file.\n");
338 binHeaderSize = sizeof(BinHeader1);
339 waveHeaderSize = sizeof(WaveHeader2);
340 checkSumSize = binHeaderSize + waveHeaderSize;
341 break;
342 case 2:
343 //printf("This is a version 2 file.\n");
344 binHeaderSize = sizeof(BinHeader2);
345 waveHeaderSize = sizeof(WaveHeader2);
346 checkSumSize = binHeaderSize + waveHeaderSize;
347 break;
348 case 3:
349 //printf("This is a version 3 file.\n");
350 binHeaderSize = sizeof(BinHeader3);
351 waveHeaderSize = sizeof(WaveHeader2);
352 checkSumSize = binHeaderSize + waveHeaderSize;
353 break;
354 case 5:
355 //printf("This is a version 5 file.\n");
356 binHeaderSize = sizeof(BinHeader5);
357 waveHeaderSize = sizeof(WaveHeader5);
358 checkSumSize = binHeaderSize + waveHeaderSize - 4; // Version 5 checksum does not include the wData field.
359 break;
360 default:
361 //printf("This does not appear to be a valid Igor binary wave file. The version field = %d.\n", version);
362 return -1;
363 break;
364 }
365
366 // Load the BinHeader and the WaveHeader into memory.
367 CPSetFilePosition(fr, startFilePos, -1);
368 if (err = CPReadFile(fr, binHeaderSize+waveHeaderSize, buffer, &numBytesRead)) {
369 //printf("Error %d occurred while reading the file headers.\n", err);
370 return err;
371 }
372
373 // Check the checksum.
374 check = Checksum((short*)buffer, needToReorderBytes, 0, checkSumSize);
375 if (check != 0) {
376 //printf("Error in checksum - should be 0, is %d.\n", check);
377 //printf("This does not appear to be a valid Igor binary wave file.\n");
378 return -1;
379 }
380
381 // Do byte reordering if the file is from another platform.
382 if (needToReorderBytes) {
383 switch(version) {
384 case 1:
386 break;
387 case 2:
389 break;
390 case 3:
392 break;
393 case 5:
395 break;
396 }
397 switch(version) {
398 case 1: // Version 1 and 2 files use WaveHeader2.
399 case 2:
400 case 3:
401 ReorderWaveHeader2((WaveHeader2*)(buffer+binHeaderSize));
402 break;
403 case 5:
404 ReorderWaveHeader5((WaveHeader5*)(buffer+binHeaderSize));
405 break;
406 }
407 }
408
409 // Read some of the BinHeader fields.
410 switch(version) {
411 case 1:
412 {
413 BinHeader1* b1;
414 b1 = (BinHeader1*)buffer;
415 wfmSize = b1->wfmSize;
416 }
417 break;
418
419 case 2:
420 {
421 BinHeader2* b2;
422 b2 = (BinHeader2*)buffer;
423 wfmSize = b2->wfmSize;
424 }
425 break;
426
427 case 3:
428 {
429 BinHeader3* b3;
430 b3 = (BinHeader3*)buffer;
431 wfmSize = b3->wfmSize;
432 }
433 break;
434
435 case 5:
436 {
437 BinHeader5* b5;
438 b5 = (BinHeader5*)buffer;
439 wfmSize = b5->wfmSize;
440 }
441 break;
442 }
443
444 // Read some of the WaveHeader fields.
445 switch(version) {
446 case 1:
447 case 2:
448 case 3:
449 {
450 WaveHeader2* w2;
451 w2 = (WaveHeader2*)(buffer+binHeaderSize);
452 modDate = w2->modDate;
453 npnts = w2->npnts;
454 type = w2->type;
455 ndimptr[0] = npnts;
456 ndimptr[1] = 0;
457 ndimptr[2] = 0;
458 ndimptr[3] = 0;
459 sfa[0] = w2->hsA;
460 sfb[0] = w2->hsB;
461 sfa[1] = 0.0;
462 sfa[2] = 0.0;
463 sfa[3] = 0.0;
464 sfb[1] = 0.0;
465 sfb[2] = 0.0;
466 sfb[3] = 0.0;
467 strcpy((*name), w2->bname);
468 }
469 break;
470
471 case 5:
472 {
473 WaveHeader5* w5;
474 w5 = (WaveHeader5*)(buffer+binHeaderSize);
475 modDate = w5->modDate;
476 npnts = w5->npnts;
477 type = w5->type;
478 ndimptr[0] = w5->nDim[0];
479 ndimptr[1] = w5->nDim[1];
480 ndimptr[2] = w5->nDim[2];
481 ndimptr[3] = w5->nDim[3];
482 sfa[0] = w5->sfA[0];
483 sfa[1] = w5->sfA[1];
484 sfa[2] = w5->sfA[2];
485 sfa[3] = w5->sfA[3];
486 sfb[0] = w5->sfB[0];
487 sfb[1] = w5->sfB[1];
488 sfb[2] = w5->sfB[2];
489 sfb[3] = w5->sfB[3];
490 strcpy((*name), w5->bname);
491 }
492 break;
493 }
494 //printf("Wave name=%s, npnts=%ld, type=0x%x, wfmSize=%ld.\n", *name, npnts, type, wfmSize);
495
496 // Return information to the calling routine.
497 *typePtr = type;
498 *npntsPtr = npnts;
499
500 // Determine the number of bytes of wave data in the file.
501 switch(version) {
502 case 1:
503 case 2:
504 case 3:
505 waveDataSize = wfmSize - offsetof(WaveHeader2, wData) - 16;
506 break;
507 case 5:
508 waveDataSize = wfmSize - offsetof(WaveHeader5, wData);
509 break;
510 }
511
512 // Position the file pointer to the start of the wData field.
513 switch(version) {
514 case 1:
515 case 2:
516 case 3:
517 CPSetFilePosition(fr, startFilePos+binHeaderSize+waveHeaderSize-16, -1); // 16 = size of wData field in WaveHeader2 structure.
518 break;
519 case 5:
520 CPSetFilePosition(fr, startFilePos+binHeaderSize+waveHeaderSize-4, -1); // 4 = size of wData field in WaveHeader2 structure.
521 break;
522 }
523
524 if (type == 0) {
525 // For simplicity, we don't load text wave data in this example program.
526 //printf("This is a text wave.\n");
527 return 0;
528 }
529
530 // Load the data and allocates memory to store it.
531 if (err = LoadNumericWaveData(fr, type, npnts, waveDataSize, needToReorderBytes, waveDataPtrPtr))
532 return err;
533
534 return 0;
535}
536
537
538/*void doMatlabWrite (int npnts, float * data, char * name, MATFILE *mf)
539{
540 int i;
541 double * buffer;
542
543 buffer = (double *) malloc(sizeof(float) * 2 * npnts);
544 for (i = 0; i < npnts; i++) {
545 buffer[i] = (double) data[i];
546 }
547
548 matfile_addmatrix(mf, name, buffer, npnts, 1 , 0);
549}
550
551
552int loadIntoMatfile(const char* filePath, MATFILE *mf);
553int
554loadIntoMatfile(const char* filePath, MATFILE *mf)
555{
556 CP_FILE_REF fr;
557 int type;
558 long npnts;
559 double* dbl_npoints;
560 void* waveDataPtr;
561 int err;
562 int index;
563 float * data;
564 char * name;
565
566 // Open ibw file for reading.
567 if (err = CPOpenFile(filePath, 0, &fr)) {
568 printf("Error %d occurred while opening the file.\n", err);
569 return err;
570 }
571
572 err = ReadWave(fr, &type, &npnts, &waveDataPtr, &name);
573
574 // Here you would do something with the data.
575 data = (float *) waveDataPtr;
576 doMatlabWrite(npnts, data, name, mf);
577
578 // Close file, clean up pointer.
579 CPCloseFile(fr);
580
581 if (waveDataPtr != NULL)
582 free(waveDataPtr);
583 return err;
584}*/
int CPSetFilePosition(CP_FILE_REF fileRef, long filePos, int mode)
int CPGetFilePosition(CP_FILE_REF fileRef, unsigned long *filePosPtr)
int CPReadFile(CP_FILE_REF fileRef, unsigned long count, void *buffer, unsigned long *numBytesReadPtr)
#define CP_FILE_REF
struct BinHeader2 BinHeader2
#define NT_FP32
Definition: IgorBin.h:25
#define NT_FP64
Definition: IgorBin.h:26
struct WaveHeader2 WaveHeader2
Definition: IgorBin.h:119
#define NT_I32
Definition: IgorBin.h:29
#define NT_CMPLX
Definition: IgorBin.h:24
#define NT_UNSIGNED
Definition: IgorBin.h:30
struct BinHeader5 BinHeader5
struct WaveHeader5 WaveHeader5
Definition: IgorBin.h:179
struct BinHeader1 BinHeader1
#define NT_I8
Definition: IgorBin.h:27
struct BinHeader3 BinHeader3
#define NT_I16
Definition: IgorBin.h:28
static int Checksum(short *data, int needToReorderBytes, int oldcksum, int numbytes)
Definition: ReadWave.cpp:160
static int LoadNumericWaveData(CP_FILE_REF fr, int type, long npnts, unsigned long waveDataSize, int needToReorderBytes, void **pp)
Definition: ReadWave.cpp:227
static void ReorderBinHeader2(BinHeader2 *p)
Definition: ReadWave.cpp:50
int ReadWave(CP_FILE_REF fr, int *typePtr, long *npntsPtr, long *ndimptr, double *sfa, double *sfb, void **waveDataPtrPtr, char **name)
Definition: ReadWave.cpp:295
static void ReorderBinHeader5(BinHeader5 *p)
Definition: ReadWave.cpp:71
static void ReorderLong(void *lp)
Definition: ReadWave.cpp:30
static void ReorderBytes(void *p, int bytesPerPoint, long numValues)
Definition: ReadWave.cpp:5
static void ReorderShort(void *sp)
Definition: ReadWave.cpp:24
static int NumBytesPerPoint(int type)
Definition: ReadWave.cpp:179
static void ReorderBinHeader3(BinHeader3 *p)
Definition: ReadWave.cpp:60
static void ReorderBinHeader1(BinHeader1 *p)
Definition: ReadWave.cpp:42
static void ReorderWaveHeader2(WaveHeader2 *p)
Definition: ReadWave.cpp:87
static void ReorderDouble(void *dp)
Definition: ReadWave.cpp:36
static void ReorderWaveHeader5(WaveHeader5 *p)
Definition: ReadWave.cpp:118
const string version
Definition: variables.hpp:66
char name[32]
Definition: resampler.cpp:371
short checksum
Definition: IgorBin.h:42
long wfmSize
Definition: IgorBin.h:41
short version
Definition: IgorBin.h:40
short version
Definition: IgorBin.h:46
long noteSize
Definition: IgorBin.h:48
short checksum
Definition: IgorBin.h:50
long wfmSize
Definition: IgorBin.h:47
long pictSize
Definition: IgorBin.h:49
long pictSize
Definition: IgorBin.h:58
long noteSize
Definition: IgorBin.h:56
long formulaSize
Definition: IgorBin.h:57
short checksum
Definition: IgorBin.h:59
long wfmSize
Definition: IgorBin.h:55
short version
Definition: IgorBin.h:54
long sIndicesSize
Definition: IgorBin.h:71
long noteSize
Definition: IgorBin.h:67
long formulaSize
Definition: IgorBin.h:66
long dimLabelsSize[MAXDIMS]
Definition: IgorBin.h:70
long wfmSize
Definition: IgorBin.h:65
long optionsSize2
Definition: IgorBin.h:73
long optionsSize1
Definition: IgorBin.h:72
short checksum
Definition: IgorBin.h:64
long dimEUnitsSize[MAXDIMS]
Definition: IgorBin.h:69
long dataEUnitsSize
Definition: IgorBin.h:68
short version
Definition: IgorBin.h:63
Handle waveNoteH
Definition: IgorBin.h:115
short srcFldr
Definition: IgorBin.h:91
double topFullScale
Definition: IgorBin.h:105
Handle fileName
Definition: IgorBin.h:92
unsigned long creationDate
Definition: IgorBin.h:111
char bname[MAX_WAVE_NAME2+2]
Definition: IgorBin.h:89
short wModified
Definition: IgorBin.h:102
short fsValid
Definition: IgorBin.h:104
short swModified
Definition: IgorBin.h:103
long depID
Definition: IgorBin.h:110
short aModified
Definition: IgorBin.h:99
unsigned long modDate
Definition: IgorBin.h:114
struct WaveHeader2 ** next
Definition: IgorBin.h:87
double botFullScale
Definition: IgorBin.h:105
short type
Definition: IgorBin.h:86
void ** formula
Definition: IgorBin.h:109
double hsA
Definition: IgorBin.h:100
short whVersion
Definition: IgorBin.h:90
long npnts
Definition: IgorBin.h:97
double hsB
Definition: IgorBin.h:100
long ** sIndices
Definition: IgorBin.h:175
struct DataFolder ** dFolder
Definition: IgorBin.h:138
long whUnused[16]
Definition: IgorBin.h:158
Handle waveNoteH
Definition: IgorBin.h:157
long npnts
Definition: IgorBin.h:130
char bname[MAX_WAVE_NAME5+1]
Definition: IgorBin.h:136
unsigned long creationDate
Definition: IgorBin.h:127
Handle dimEUnits[MAXDIMS]
Definition: IgorBin.h:154
short type
Definition: IgorBin.h:131
long whpad2
Definition: IgorBin.h:137
double sfA[MAXDIMS]
Definition: IgorBin.h:142
Handle dataEUnits
Definition: IgorBin.h:153
void ** formula
Definition: IgorBin.h:168
short whpad4
Definition: IgorBin.h:171
short srcFldr
Definition: IgorBin.h:172
short whVersion
Definition: IgorBin.h:135
short fsValid
Definition: IgorBin.h:149
short swModified
Definition: IgorBin.h:164
double topFullScale
Definition: IgorBin.h:151
long nDim[MAXDIMS]
Definition: IgorBin.h:141
unsigned long modDate
Definition: IgorBin.h:128
double sfB[MAXDIMS]
Definition: IgorBin.h:143
short aModified
Definition: IgorBin.h:162
short dLock
Definition: IgorBin.h:132
double botFullScale
Definition: IgorBin.h:151
short wModified
Definition: IgorBin.h:163
long depID
Definition: IgorBin.h:169
Handle fileName
Definition: IgorBin.h:173
struct WaveHeader5 ** next
Definition: IgorBin.h:125
short whpad3
Definition: IgorBin.h:150
Handle dimLabels[MAXDIMS]
Definition: IgorBin.h:155