Any Data_readFromBinaryFile (MelderFile file) { try { autofile f = Melder_fopen (file, "rb"); char line [200]; int n = fread (line, 1, 199, f); line [n] = '\0'; char *end = strstr (line, "ooBinaryFile"); autoData me = NULL; if (end) { fseek (f, strlen ("ooBinaryFile"), 0); autostring8 klas = bingets1 (f); me.reset ((Data) Thing_newFromClassNameA (klas.peek())); } else { end = strstr (line, "BinaryFile"); if (! end) { Melder_throw ("File ", file, " is not a Data binary file."); } *end = '\0'; me.reset ((Data) Thing_newFromClassNameA (line)); Thing_version = -1; // old version: override version number, which was set to 0 by newFromClassName rewind (f); fread (line, 1, end - line + strlen ("BinaryFile"), f); } MelderFile_getParentDir (file, & Data_directoryBeingRead); Data_readBinary (me.peek(), f); f.close (file); return me.transfer(); } catch (MelderError) { Melder_throw ("Data not read from binary file ", file, "."); } }
autoMatrix Matrix_readAP (MelderFile file) { try { autofile f = Melder_fopen (file, "rb"); int16_t header [256]; for (long i = 0; i < 256; i ++) header [i] = bingeti2LE (f); double samplingFrequency = header [100]; // converting up (from 16 to 54 bytes) Melder_casual (U"Sampling frequency ", samplingFrequency); autoMatrix me = Matrix_create (0.0, (double) header [34], header [34] /* Number of frames. */, 1.0, 0.5, 0.0, (double) header [35], header [35] /* Number of words per frame. */, 1.0, 0.5); /*Mat := MATRIX_create (Buffer.I2 [36], (* Number of words per frame. *) Buffer.I2 [35], (* Number of frames. *) 1.0, Buffer.I2 [111] / (* Samples per frame. *) Buffer.I2 [101]); (* Sampling frequency. *)*/ Melder_casual (U"... Loading ", header [34], U" frames", U" of ", header [35], U" words ..."); for (long i = 1; i <= my nx; i ++) for (long j = 1; j <= my ny; j ++) my z [j] [i] = bingeti2LE (f); // converting up (from 16 to 54 bytes) /* * Get pitch frequencies. */ for (long i = 1; i <= my nx; i ++) if (my z [1] [i] != 0.0) my z [1] [i] = - samplingFrequency / my z [1] [i]; f.close (file); return me; } catch (MelderError) { Melder_throw (U"Matrix object not read from AP file ", file); } }
Daata Data_readFromBinaryFile (MelderFile file) { try { autofile f = Melder_fopen (file, "rb"); char line [200]; int n = fread (line, 1, 199, f); line [n] = '\0'; char *end = strstr (line, "ooBinaryFile"); autoDaata me; int formatVersion; if (end) { fseek (f, strlen ("ooBinaryFile"), 0); autostring8 klas = bingets1 (f); me.reset (static_cast <Daata> (Thing_newFromClassName (Melder_peek8to32 (klas.peek()), & formatVersion))); } else { end = strstr (line, "BinaryFile"); if (! end) { Melder_throw (U"File ", file, U" is not a Data binary file."); } *end = '\0'; me.reset (static_cast <Daata> (Thing_newFromClassName (Melder_peek8to32 (line), nullptr))); formatVersion = -1; // old version: override version number, which was set to 0 by newFromClassName rewind (f); fread (line, 1, end - line + strlen ("BinaryFile"), f); } MelderFile_getParentDir (file, & Data_directoryBeingRead); Data_readBinary (me.peek(), f, formatVersion); file -> format = structMelderFile :: Format :: binary; f.close (file); return me.transfer(); } catch (MelderError) { Melder_throw (U"Data not read from binary file ", file, U"."); } }
autoMatrix Matrix_readFromRawTextFile (MelderFile file) { // BUG: not Unicode-compatible try { autofile f = Melder_fopen (file, "rb"); /* * Count number of columns. */ long ncol = 0; for (;;) { int kar = fgetc (f); if (kar == '\n' || kar == '\r' || kar == EOF) break; if (kar == ' ' || kar == '\t') continue; ncol ++; do { kar = fgetc (f); } while (kar != ' ' && kar != '\t' && kar != '\n' && kar != '\r' && kar != EOF); if (kar == '\n' || kar == '\r' || kar == EOF) break; } if (ncol == 0) Melder_throw (U"File empty"); /* * Count number of elements. */ rewind (f); long nelements = 0; for (;;) { double element; if (fscanf (f, "%lf", & element) < 1) break; // zero or end-of-file nelements ++; } /* * Check if all columns are complete. */ if (nelements == 0 || nelements % ncol != 0) Melder_throw (U"The number of elements (", nelements, U") is not a multiple of the number of columns (", ncol, U")."); /* * Create simple matrix. */ long nrow = nelements / ncol; autoMatrix me = Matrix_createSimple (nrow, ncol); /* * Read elements. */ rewind (f); for (long irow = 1; irow <= nrow; irow ++) for (long icol = 1; icol <= ncol; icol ++) fscanf (f, "%lf", & my z [irow] [icol]); f.close (file); return me; } catch (MelderError) { Melder_throw (U"Matrix object not read from raw text file ", file, U"."); } }
static void PitchTier_writeToSpreadsheetFile (PitchTier me, MelderFile file, int hasHeader) { autofile f = Melder_fopen (file, "w"); if (hasHeader) fprintf (f, "\"ooTextFile\"\n\"PitchTier\"\n%.17g %.17g %ld\n", my xmin, my xmax, my points -> size); for (long i = 1; i <= my points -> size; i ++) { RealPoint point = (RealPoint) my points -> item [i]; fprintf (f, "%.17g\t%.17g\n", point -> number, point -> value); } f.close (file); }
void Picture_writeToPraatPictureFile (Picture me, MelderFile file) { try { autofile f = Melder_fopen (file, "wb"); if (fprintf (f, "PraatPictureFile") < 0) Melder_throw (U"Write error."); Graphics_writeRecordings (my graphics.get(), f); f.close (file); } catch (MelderError) { Melder_throw (U"Cannot write Praat picture file ", file, U"."); } }
autoDaata Data_readFromFile (MelderFile file) { int nread, i; char header [513]; autofile f = Melder_fopen (file, "rb"); nread = fread (& header [0], 1, 512, f); f.close (file); header [nread] = 0; /***** 1. Is this file a text file as defined in Data.cpp? *****/ if (nread > 11) { char *p = strstr (header, "TextFile"); if (p && p - header < nread - 8 && p - header < 40) return Data_readFromTextFile (file); } if (nread > 22) { char headerCopy [101]; memcpy (headerCopy, header, 100); headerCopy [100] = '\0'; for (i = 0; i < 100; i ++) if (headerCopy [i] == '\0') headerCopy [i] = '\001'; char *p = strstr (headerCopy, "T\001e\001x\001t\001F\001i\001l\001e"); if (p && p - headerCopy < nread - 15 && p - headerCopy < 80) return Data_readFromTextFile (file); } /***** 2. Is this file a binary file as defined in Data.cpp? *****/ if (nread > 13) { char *p = strstr (header, "BinaryFile"); if (p && p - header < nread - 10 && p - header < 40) return Data_readFromBinaryFile (file); } /***** 3. Is this file of a type for which a recognizer has been installed? *****/ MelderFile_getParentDir (file, & Data_directoryBeingRead); for (i = 1; i <= numFileTypeRecognizers; i ++) { autoDaata object = fileTypeRecognizers [i] (nread, header, file); if (object) { if (object -> classInfo == classDaata) // dummy object? the recognizer could have had a side effect, such as drawing a picture return autoDaata (); return object; } } /***** 4. Is this a common text file? *****/ for (i = 0; i < nread; i ++) if (header [i] < 32 || header [i] > 126) // not ASCII? break; if (i >= nread) return Data_readFromTextFile (file); Melder_throw (U"File ", file, U" not recognized."); }
Graphics Graphics_create_epsfile (MelderFile file, int resolution, enum kGraphicsPostscript_spots spots, double x1inches, double x2inches, double y1inches, double y2inches, bool includeFonts, bool useSilipaPS) { autoGraphicsPostscript me = Thing_new (GraphicsPostscript); time_t today; int left, right, top, bottom; my postScript = true, my languageLevel = 2; my job = false, my eps = true, my printer = false; #if defined (macintosh) /* Replace newlines with carriage returns to be compatible with MS Word 5.1. */ my d_printf = Eps_postScript_printf; #else my d_printf = (int (*)(void *, const char*, ...)) fprintf; #endif Graphics_init (me.peek(), resolution); // virtual resolution; may differ from that of the printer; OK if always 600 dpi my photocopyable = spots == kGraphicsPostscript_spots_PHOTOCOPYABLE; if (my photocopyable) { my spotsDensity = 85; my spotsAngle = 35; } else { my spotsDensity = 106; my spotsAngle = 46; } my paperWidth = 7.5, my paperHeight = 11.0; my landscape = false; my magnification = 1.0; my includeFonts = includeFonts; my useSilipaPS = useSilipaPS; my d_file = Melder_fopen (file, "w"); my d_x1DC = my d_x1DCmin = 0; my d_x2DC = my d_x2DCmax = my paperWidth * resolution; // 600 dpi -> 4500 virtual dots my d_y1DC = my d_y1DCmin = 0; my d_y2DC = my d_y2DCmax = my paperHeight * resolution; // 600 dpi -> 6600 virtual dots Graphics_setWsWindow ((Graphics) me.peek(), 0, my paperWidth, 12.0 - my paperHeight, 12.0); // force scaling /* * We will honour version 3.0 of the DSC for Encapsulated PostScript files, * which includes supplying the bounding box information. */ left = (int) floor (x1inches * 72); right = (int) ceil (x2inches * 72); top = (int) ceil ((y2inches - my d_y1wNDC) * 72); bottom = (int) floor ((y1inches - my d_y1wNDC) * 72); my d_printf (my d_file, "%%!PS-Adobe-3.0 EPSF-3.0\n"); my d_printf (my d_file, "%%%%BoundingBox: %d %d %d %d\n", left, bottom, right, top); my d_printf (my d_file, "%%%%Creator: Praat Shell 5.1\n"); /* * In an EPS file without screen preview, the file name will be visible anyway. * This leaves us room to show a warning that should keep users from thinking anything is wrong. */ my d_printf (my d_file, "%%%%Title: NO SCREEN PREVIEW, BUT WILL PRINT CORRECTLY\n"); today = time (nullptr); my d_printf (my d_file, "%%%%CreationDate: %s", ctime (& today)); /* Contains newline symbol. */ my d_printf (my d_file, "%%%%EndComments\n"); downloadPrologAndSetUp (me.peek()); initPage (me.peek()); return (Graphics) me.transfer(); }
Any Data_readFromFile (MelderFile file) { int nread, i; char header [513]; autofile f = Melder_fopen (file, "rb"); nread = fread (& header [0], 1, 512, f); f.close (file); header [nread] = 0; /***** 1. Is this file a text file as defined in Data.cpp? *****/ if (nread > 11) { char *p = strstr (header, "TextFile"); if (p != NULL && p - header < nread - 8 && p - header < 40) return Data_readFromTextFile (file); } if (nread > 22) { char headerCopy [101]; memcpy (headerCopy, header, 100); headerCopy [100] = '\0'; for (i = 0; i < 100; i ++) if (headerCopy [i] == '\0') headerCopy [i] = '\001'; char *p = strstr (headerCopy, "T\001e\001x\001t\001F\001i\001l\001e"); if (p != NULL && p - headerCopy < nread - 15 && p - headerCopy < 80) return Data_readFromTextFile (file); } /***** 2. Is this file a binary file as defined in Data.cpp? *****/ if (nread > 13) { char *p = strstr (header, "BinaryFile"); if (p != NULL && p - header < nread - 10 && p - header < 40) return Data_readFromBinaryFile (file); } /***** 3. Is this file of a type for which a recognizer has been installed? *****/ MelderFile_getParentDir (file, & Data_directoryBeingRead); for (i = 1; i <= numFileTypeRecognizers; i ++) { Data object = (Data) fileTypeRecognizers [i] (nread, header, file); if (object == (Data) 1) return NULL; if (object) return object; } /***** 4. Is this a common text file? *****/ for (i = 0; i < nread; i ++) if (header [i] < 32 || header [i] > 126) /* Not ASCII? */ break; if (i >= nread) return Data_readFromTextFile (file); Melder_throw ("File ", file, " not recognized."); }
void Matrix_writeToHeaderlessSpreadsheetFile (Matrix me, MelderFile file) { try { autofile f = Melder_fopen (file, "w"); for (long i = 1; i <= my ny; i ++) { for (long j = 1; j <= my nx; j ++) { if (j > 1) fprintf (f, "\t"); fprintf (f, "%s", Melder8_single (my z [i] [j])); } fprintf (f, "\n"); } f.close (file); } catch (MelderError) { Melder_throw (me, U": not saved as tab-separated file ", file); } }
Graphics Graphics_create_postscriptjob (MelderFile file, int resolution, enum kGraphicsPostscript_spots spots, enum kGraphicsPostscript_paperSize paperSize, enum kGraphicsPostscript_orientation rotation, double magnification) { autoGraphicsPostscript me = Thing_new (GraphicsPostscript); time_t today; my postScript = true, my yIsZeroAtTheTop = false, my languageLevel = 2; my job = true, my eps = false, my printer = false; my d_printf = (int (*)(void *, const char*, ...)) fprintf; Graphics_init (me.peek(), resolution); // virtual resolution; may differ from that of the printer; OK if always 600 dpi my photocopyable = spots == kGraphicsPostscript_spots_PHOTOCOPYABLE; if (my photocopyable) { my spotsDensity = 85; my spotsAngle = 35; } else { my spotsDensity = 106; my spotsAngle = 46; } if (paperSize == kGraphicsPostscript_paperSize_A3) my paperWidth = 842 / 72.0, my paperHeight = 1191 / 72.0; else if (paperSize == kGraphicsPostscript_paperSize_US_LETTER) my paperWidth = 612 / 72.0, my paperHeight = 792 / 72.0; else my paperWidth = 595 / 72.0, my paperHeight = 842 / 72.0; my landscape = rotation == kGraphicsPostscript_orientation_LANDSCAPE; my magnification = magnification; my includeFonts = true; my d_file = Melder_fopen (file, "w"); /* * The Device Coordinates are the PostScript user coordinates. * They are chosen in such a way that a distance of 1 in device coordinates * equals one dot if the printer's resolution is 'resolution' dots per inch. * Take a sensible default margin: half an inch on all sides. */ my d_x1DC = my d_x1DCmin = resolution / 2; my d_x2DC = my d_x2DCmax = (my paperWidth - 0.5) * resolution; my d_y1DC = my d_y1DCmin = resolution / 2; my d_y2DC = my d_y2DCmax = (my paperHeight - 0.5) * resolution; /* * Now don't just set x1wNDC etc, but force computation of the scaling as well. */ Graphics_setWsWindow ((Graphics) me.peek(), 0, my paperWidth - 1.0, 13.0 - my paperHeight, 12.0); /* * We will adhere to version 3.0 of the Document Structuring Conventions for print jobs. */ my d_printf (my d_file, "%%!PS-Adobe-3.0\n"); my d_printf (my d_file, "%%%%Creator: Praat Shell 4.2\n"); my d_printf (my d_file, "%%%%Title: %s\n", Melder_peek32to8 (MelderFile_name (file))); today = time (nullptr); my d_printf (my d_file, "%%%%CreationDate: %s", ctime (& today)); // contains newline symbol my d_printf (my d_file, "%%%%PageOrder: Special\n"); my d_printf (my d_file, "%%%%Pages: (atend)\n"); my d_printf (my d_file, "%%%%EndComments\n"); downloadPrologAndSetUp (me.peek()); initPage (me.peek()); return (Graphics) me.transfer(); }
void Matrix_writeToMatrixTextFile (Matrix me, MelderFile file) { try { autofile f = Melder_fopen (file, "w"); fprintf (f, "\"ooTextFile\"\n\"Matrix\"\n%.17g %.17g %ld %.17g %.17g\n%.17g %.17g %ld %.17g %.17g\n", my xmin, my xmax, (long) my nx, my dx, my x1, my ymin, my ymax, my ny, my dy, my y1); for (long i = 1; i <= my ny; i ++) { for (long j = 1; j <= my nx; j ++) { if (j > 1) fprintf (f, " "); fprintf (f, "%.17g", my z [i] [j]); } fprintf (f, "\n"); } f.close (file); } catch (MelderError) { Melder_throw (me, U": not written to Matrix text file."); } }
void Picture_readFromPraatPictureFile (Picture me, MelderFile file) { try { autofile f = Melder_fopen (file, "rb"); char line [200]; int n = fread (line, 1, 199, f); line [n] = '\0'; const char *tag = "PraatPictureFile"; char *end = strstr (line, tag); if (! end) Melder_throw (U"This is not a Praat picture file."); *end = '\0'; rewind (f); fread (line, 1, end - line + strlen (tag), f); Graphics_readRecordings (my graphics.get(), f); Graphics_updateWs (my graphics.get()); f.close (file); } catch (MelderError) { Melder_throw (U"Praat picture not read from file ", file); } }
autoEEG EEG_readFromBdfFile (MelderFile file) { try { autofile f = Melder_fopen (file, "rb"); char buffer [81]; fread (buffer, 1, 8, f); buffer [8] = '\0'; bool is24bit = buffer [0] == (char) 255; fread (buffer, 1, 80, f); buffer [80] = '\0'; trace (U"Local subject identification: \"", Melder_peek8to32 (buffer), U"\""); fread (buffer, 1, 80, f); buffer [80] = '\0'; trace (U"Local recording identification: \"", Melder_peek8to32 (buffer), U"\""); fread (buffer, 1, 8, f); buffer [8] = '\0'; trace (U"Start date of recording: \"", Melder_peek8to32 (buffer), U"\""); fread (buffer, 1, 8, f); buffer [8] = '\0'; trace (U"Start time of recording: \"", Melder_peek8to32 (buffer), U"\""); fread (buffer, 1, 8, f); buffer [8] = '\0'; long numberOfBytesInHeaderRecord = atol (buffer); trace (U"Number of bytes in header record: ", numberOfBytesInHeaderRecord); fread (buffer, 1, 44, f); buffer [44] = '\0'; trace (U"Version of data format: \"", Melder_peek8to32 (buffer), U"\""); fread (buffer, 1, 8, f); buffer [8] = '\0'; long numberOfDataRecords = strtol (buffer, nullptr, 10); trace (U"Number of data records: ", numberOfDataRecords); fread (buffer, 1, 8, f); buffer [8] = '\0'; double durationOfDataRecord = atof (buffer); trace (U"Duration of a data record: ", durationOfDataRecord); fread (buffer, 1, 4, f); buffer [4] = '\0'; long numberOfChannels = atol (buffer); trace (U"Number of channels in data record: ", numberOfChannels); if (numberOfBytesInHeaderRecord != (numberOfChannels + 1) * 256) Melder_throw (U"Number of bytes in header record (", numberOfBytesInHeaderRecord, U") doesn't match number of channels (", numberOfChannels, U")."); autostring32vector channelNames (1, numberOfChannels); for (long ichannel = 1; ichannel <= numberOfChannels; ichannel ++) { fread (buffer, 1, 16, f); buffer [16] = '\0'; // labels of the channels /* * Strip all final spaces. */ for (int i = 15; i >= 0; i --) { if (buffer [i] == ' ') { buffer [i] = '\0'; } else { break; } } channelNames [ichannel] = Melder_8to32 (buffer); trace (U"Channel <<", channelNames [ichannel], U">>"); } bool hasLetters = str32equ (channelNames [numberOfChannels], U"EDF Annotations"); double samplingFrequency = NUMundefined; for (long channel = 1; channel <= numberOfChannels; channel ++) { fread (buffer, 1, 80, f); buffer [80] = '\0'; // transducer type } for (long channel = 1; channel <= numberOfChannels; channel ++) { fread (buffer, 1, 8, f); buffer [8] = '\0'; // physical dimension of channels } autoNUMvector <double> physicalMinimum (1, numberOfChannels); for (long ichannel = 1; ichannel <= numberOfChannels; ichannel ++) { fread (buffer, 1, 8, f); buffer [8] = '\0'; physicalMinimum [ichannel] = atof (buffer); } autoNUMvector <double> physicalMaximum (1, numberOfChannels); for (long ichannel = 1; ichannel <= numberOfChannels; ichannel ++) { fread (buffer, 1, 8, f); buffer [8] = '\0'; physicalMaximum [ichannel] = atof (buffer); } autoNUMvector <double> digitalMinimum (1, numberOfChannels); for (long ichannel = 1; ichannel <= numberOfChannels; ichannel ++) { fread (buffer, 1, 8, f); buffer [8] = '\0'; digitalMinimum [ichannel] = atof (buffer); } autoNUMvector <double> digitalMaximum (1, numberOfChannels); for (long ichannel = 1; ichannel <= numberOfChannels; ichannel ++) { fread (buffer, 1, 8, f); buffer [8] = '\0'; digitalMaximum [ichannel] = atof (buffer); } for (long channel = 1; channel <= numberOfChannels; channel ++) { fread (buffer, 1, 80, f); buffer [80] = '\0'; // prefiltering } long numberOfSamplesPerDataRecord = 0; for (long channel = 1; channel <= numberOfChannels; channel ++) { fread (buffer, 1, 8, f); buffer [8] = '\0'; // number of samples in each data record long numberOfSamplesInThisDataRecord = atol (buffer); if (samplingFrequency == NUMundefined) { numberOfSamplesPerDataRecord = numberOfSamplesInThisDataRecord; samplingFrequency = numberOfSamplesInThisDataRecord / durationOfDataRecord; } if (numberOfSamplesInThisDataRecord / durationOfDataRecord != samplingFrequency) Melder_throw (U"Number of samples per data record in channel ", channel, U" (", numberOfSamplesInThisDataRecord, U") doesn't match sampling frequency of channel 1 (", samplingFrequency, U")."); } for (long channel = 1; channel <= numberOfChannels; channel ++) { fread (buffer, 1, 32, f); buffer [32] = '\0'; // reserved } double duration = numberOfDataRecords * durationOfDataRecord; autoEEG him = EEG_create (0, duration); his numberOfChannels = numberOfChannels; autoSound me = Sound_createSimple (numberOfChannels, duration, samplingFrequency); Melder_assert (my nx == numberOfSamplesPerDataRecord * numberOfDataRecords); autoNUMvector <unsigned char> dataBuffer (0L, 3 * numberOfSamplesPerDataRecord - 1); for (long record = 1; record <= numberOfDataRecords; record ++) { for (long channel = 1; channel <= numberOfChannels; channel ++) { double factor = channel == numberOfChannels ? 1.0 : physicalMinimum [channel] / digitalMinimum [channel]; if (channel < numberOfChannels - EEG_getNumberOfExtraSensors (him.peek())) factor /= 1000000.0; if (is24bit) { fread (& dataBuffer [0], 3, numberOfSamplesPerDataRecord, f); unsigned char *p = & dataBuffer [0]; for (long i = 1; i <= numberOfSamplesPerDataRecord; i ++) { long sample = i + (record - 1) * numberOfSamplesPerDataRecord; Melder_assert (sample <= my nx); uint8_t lowByte = *p ++, midByte = *p ++, highByte = *p ++; uint32_t externalValue = ((uint32_t) highByte << 16) | ((uint32_t) midByte << 8) | (uint32_t) lowByte; if ((highByte & 128) != 0) // is the 24-bit sign bit on? externalValue |= 0xFF000000; // extend negative sign to 32 bits my z [channel] [sample] = (int32_t) externalValue * factor; } } else { fread (& dataBuffer [0], 2, numberOfSamplesPerDataRecord, f); unsigned char *p = & dataBuffer [0]; for (long i = 1; i <= numberOfSamplesPerDataRecord; i ++) { long sample = i + (record - 1) * numberOfSamplesPerDataRecord; Melder_assert (sample <= my nx); uint8 lowByte = *p ++, highByte = *p ++; uint16 externalValue = (uint16) ((uint16) highByte << 8) | (uint16) lowByte; my z [channel] [sample] = (int16) externalValue * factor; } } } } int numberOfStatusBits = 8; for (long i = 1; i <= my nx; i ++) { unsigned long value = (long) my z [numberOfChannels] [i]; if (value & 0x0000FF00) { numberOfStatusBits = 16; } } autoTextGrid thee; if (hasLetters) { thee = TextGrid_create (0, duration, U"Mark Trigger", U"Mark Trigger"); autoMelderString letters; double time = NUMundefined; for (long i = 1; i <= my nx; i ++) { unsigned long value = (long) my z [numberOfChannels] [i]; for (int byte = 1; byte <= numberOfStatusBits / 8; byte ++) { unsigned long mask = byte == 1 ? 0x000000ff : 0x0000ff00; char32 kar = byte == 1 ? (value & mask) : (value & mask) >> 8; if (kar != U'\0' && kar != 20) { MelderString_appendCharacter (& letters, kar); } else if (letters. string [0] != U'\0') { if (letters. string [0] == U'+') { if (NUMdefined (time)) { try { TextGrid_insertPoint (thee.peek(), 1, time, U""); } catch (MelderError) { Melder_throw (U"Did not insert empty mark (", letters. string, U") on Mark tier."); } time = NUMundefined; // defensive } time = Melder_atof (& letters. string [1]); MelderString_empty (& letters); } else { if (! NUMdefined (time)) { Melder_throw (U"Undefined time for label at sample ", i, U"."); } try { if (Melder_nequ (letters. string, U"Trigger-", 8)) { try { TextGrid_insertPoint (thee.peek(), 2, time, & letters. string [8]); } catch (MelderError) { Melder_clearError (); trace (U"Duplicate trigger at ", time, U" seconds: ", & letters. string [8]); } } else { TextGrid_insertPoint (thee.peek(), 1, time, & letters. string [0]); } } catch (MelderError) { Melder_throw (U"Did not insert mark (", letters. string, U") on Trigger tier."); } time = NUMundefined; // crucial MelderString_empty (& letters); } } } } if (NUMdefined (time)) { TextGrid_insertPoint (thee.peek(), 1, time, U""); time = NUMundefined; // defensive } } else { thee = TextGrid_create (0, duration, numberOfStatusBits == 8 ? U"S1 S2 S3 S4 S5 S6 S7 S8" : U"S1 S2 S3 S4 S5 S6 S7 S8 S9 S10 S11 S12 S13 S14 S15 S16", U""); for (int bit = 1; bit <= numberOfStatusBits; bit ++) { unsigned long bitValue = 1 << (bit - 1); IntervalTier tier = (IntervalTier) thy tiers -> item [bit]; for (long i = 1; i <= my nx; i ++) { unsigned long previousValue = i == 1 ? 0 : (long) my z [numberOfChannels] [i - 1]; unsigned long thisValue = (long) my z [numberOfChannels] [i]; if ((thisValue & bitValue) != (previousValue & bitValue)) { double time = i == 1 ? 0.0 : my x1 + (i - 1.5) * my dx; if (time != 0.0) TextGrid_insertBoundary (thee.peek(), bit, time); if ((thisValue & bitValue) != 0) TextGrid_setIntervalText (thee.peek(), bit, tier -> intervals -> size, U"1"); } } } } f.close (file); his channelNames = channelNames.transfer(); his sound = me.move(); his textgrid = thee.move(); if (EEG_getNumberOfCapElectrodes (him.peek()) == 32) { EEG_setChannelName (him.peek(), 1, U"Fp1"); EEG_setChannelName (him.peek(), 2, U"AF3"); EEG_setChannelName (him.peek(), 3, U"F7"); EEG_setChannelName (him.peek(), 4, U"F3"); EEG_setChannelName (him.peek(), 5, U"FC1"); EEG_setChannelName (him.peek(), 6, U"FC5"); EEG_setChannelName (him.peek(), 7, U"T7"); EEG_setChannelName (him.peek(), 8, U"C3"); EEG_setChannelName (him.peek(), 9, U"CP1"); EEG_setChannelName (him.peek(), 10, U"CP5"); EEG_setChannelName (him.peek(), 11, U"P7"); EEG_setChannelName (him.peek(), 12, U"P3"); EEG_setChannelName (him.peek(), 13, U"Pz"); EEG_setChannelName (him.peek(), 14, U"PO3"); EEG_setChannelName (him.peek(), 15, U"O1"); EEG_setChannelName (him.peek(), 16, U"Oz"); EEG_setChannelName (him.peek(), 17, U"O2"); EEG_setChannelName (him.peek(), 18, U"PO4"); EEG_setChannelName (him.peek(), 19, U"P4"); EEG_setChannelName (him.peek(), 20, U"P8"); EEG_setChannelName (him.peek(), 21, U"CP6"); EEG_setChannelName (him.peek(), 22, U"CP2"); EEG_setChannelName (him.peek(), 23, U"C4"); EEG_setChannelName (him.peek(), 24, U"T8"); EEG_setChannelName (him.peek(), 25, U"FC6"); EEG_setChannelName (him.peek(), 26, U"FC2"); EEG_setChannelName (him.peek(), 27, U"F4"); EEG_setChannelName (him.peek(), 28, U"F8"); EEG_setChannelName (him.peek(), 29, U"AF4"); EEG_setChannelName (him.peek(), 30, U"Fp2"); EEG_setChannelName (him.peek(), 31, U"Fz"); EEG_setChannelName (him.peek(), 32, U"Cz"); } else if (EEG_getNumberOfCapElectrodes (him.peek()) == 64) { EEG_setChannelName (him.peek(), 1, U"Fp1"); EEG_setChannelName (him.peek(), 2, U"AF7"); EEG_setChannelName (him.peek(), 3, U"AF3"); EEG_setChannelName (him.peek(), 4, U"F1"); EEG_setChannelName (him.peek(), 5, U"F3"); EEG_setChannelName (him.peek(), 6, U"F5"); EEG_setChannelName (him.peek(), 7, U"F7"); EEG_setChannelName (him.peek(), 8, U"FT7"); EEG_setChannelName (him.peek(), 9, U"FC5"); EEG_setChannelName (him.peek(), 10, U"FC3"); EEG_setChannelName (him.peek(), 11, U"FC1"); EEG_setChannelName (him.peek(), 12, U"C1"); EEG_setChannelName (him.peek(), 13, U"C3"); EEG_setChannelName (him.peek(), 14, U"C5"); EEG_setChannelName (him.peek(), 15, U"T7"); EEG_setChannelName (him.peek(), 16, U"TP7"); EEG_setChannelName (him.peek(), 17, U"CP5"); EEG_setChannelName (him.peek(), 18, U"CP3"); EEG_setChannelName (him.peek(), 19, U"CP1"); EEG_setChannelName (him.peek(), 20, U"P1"); EEG_setChannelName (him.peek(), 21, U"P3"); EEG_setChannelName (him.peek(), 22, U"P5"); EEG_setChannelName (him.peek(), 23, U"P7"); EEG_setChannelName (him.peek(), 24, U"P9"); EEG_setChannelName (him.peek(), 25, U"PO7"); EEG_setChannelName (him.peek(), 26, U"PO3"); EEG_setChannelName (him.peek(), 27, U"O1"); EEG_setChannelName (him.peek(), 28, U"Iz"); EEG_setChannelName (him.peek(), 29, U"Oz"); EEG_setChannelName (him.peek(), 30, U"POz"); EEG_setChannelName (him.peek(), 31, U"Pz"); EEG_setChannelName (him.peek(), 32, U"CPz"); EEG_setChannelName (him.peek(), 33, U"Fpz"); EEG_setChannelName (him.peek(), 34, U"Fp2"); EEG_setChannelName (him.peek(), 35, U"AF8"); EEG_setChannelName (him.peek(), 36, U"AF4"); EEG_setChannelName (him.peek(), 37, U"AFz"); EEG_setChannelName (him.peek(), 38, U"Fz"); EEG_setChannelName (him.peek(), 39, U"F2"); EEG_setChannelName (him.peek(), 40, U"F4"); EEG_setChannelName (him.peek(), 41, U"F6"); EEG_setChannelName (him.peek(), 42, U"F8"); EEG_setChannelName (him.peek(), 43, U"FT8"); EEG_setChannelName (him.peek(), 44, U"FC6"); EEG_setChannelName (him.peek(), 45, U"FC4"); EEG_setChannelName (him.peek(), 46, U"FC2"); EEG_setChannelName (him.peek(), 47, U"FCz"); EEG_setChannelName (him.peek(), 48, U"Cz"); EEG_setChannelName (him.peek(), 49, U"C2"); EEG_setChannelName (him.peek(), 50, U"C4"); EEG_setChannelName (him.peek(), 51, U"C6"); EEG_setChannelName (him.peek(), 52, U"T8"); EEG_setChannelName (him.peek(), 53, U"TP8"); EEG_setChannelName (him.peek(), 54, U"CP6"); EEG_setChannelName (him.peek(), 55, U"CP4"); EEG_setChannelName (him.peek(), 56, U"CP2"); EEG_setChannelName (him.peek(), 57, U"P2"); EEG_setChannelName (him.peek(), 58, U"P4"); EEG_setChannelName (him.peek(), 59, U"P6"); EEG_setChannelName (him.peek(), 60, U"P8"); EEG_setChannelName (him.peek(), 61, U"P10"); EEG_setChannelName (him.peek(), 62, U"PO8"); EEG_setChannelName (him.peek(), 63, U"PO4"); EEG_setChannelName (him.peek(), 64, U"O2"); } return him; } catch (MelderError) {
TextGrid TextGrid_readFromTIMITLabelFile (MelderFile file, int phnFile) { try { double dt = 1.0 / 16000; /* 1 / (TIMIT samplingFrequency) */ double xmax = dt; autofile f = Melder_fopen (file, "r"); // Ending time will only be known after all labels have been read. // We start with a sufficiently long duration (one hour) and correct this later. autoTextGrid me = TextGrid_create (0, 3600, U"wrd", 0); IntervalTier timit = (IntervalTier) my tiers -> item[1]; long linesRead = 0; char line[200], label[200]; while (fgets (line, 199, f)) { long it1, it2; linesRead++; if (sscanf (line, "%ld%ld%s", &it1, &it2, label) != 3) { Melder_throw (U"Incorrect number of items."); } if (it1 < 0 || it2 <= it1) { Melder_throw (U"Incorrect time at line ", linesRead); } xmax = it2 * dt; double xmin = it1 * dt; long ni = timit -> intervals -> size - 1; if (ni < 1) { ni = 1; // Some files do not start with a first line "0 <number2> h#". // Instead they start with "<number1> <number2> h#", where number1 > 0. // We override number1 with 0. */ if (xmin > 0 && phnFile) { xmin = 0; } } TextInterval interval = (TextInterval) timit -> intervals -> item[ni]; if (xmin < interval -> xmax && linesRead > 1) { xmin = interval -> xmax; Melder_warning (U"File \"", MelderFile_messageName (file), U"\": Start time set to previous end " U"time for label at line ", linesRead, U"."); } // standard: new TextInterval const char *labelstring = (strncmp (label, "h#", 2) ? label : TIMIT_DELIMITER); IntervalTier_add (timit, xmin, xmax, Melder_peek8to32 (labelstring)); } // Now correct the end times, based on last read interval. // (end time was set to large value!) if (timit -> intervals -> size < 2) { Melder_throw (U"Empty TextGrid"); } Collection_removeItem (timit -> intervals, timit -> intervals -> size); TextInterval interval = (TextInterval) timit -> intervals -> item[timit -> intervals -> size]; timit -> xmax = interval -> xmax; my xmax = xmax; if (phnFile) { // Create tier 2 with IPA symbols autoIntervalTier ipa = Data_copy (timit); Thing_setName (ipa.peek(), U"ipa"); // First change the data in ipa for (long i = 1; i <= ipa -> intervals -> size; i++) { interval = (TextInterval) timit -> intervals -> item[i]; TextInterval_setText ( (TextInterval) ipa -> intervals -> item[i], Melder_peek8to32 (timitLabelToIpaLabel (Melder_peek32to8 (interval -> text)))); } Collection_addItem (my tiers, ipa.transfer()); // Then: add to collection Thing_setName (timit, U"phn"); // rename wrd } f.close (file); return me.transfer(); } catch (MelderError) { Melder_throw (U"TextGrid not read from file ", file, U"."); } }
void LongSounds_appendToExistingSoundFile (Collection me, MelderFile file) { long pre_append_endpos = 0, numberOfBitsPerSamplePoint = 16; try { if (my size < 1) { Melder_throw ("No Sound or LongSound objects to append."); } /* We have to open with "r+" mode because this will position the stream at the beginning of the file. The "a" mode does not allow us to seek before the end-of-file. For Linux: If the file is already opened (e.g. by a LongSound) object we should deny access! Under Windows deny access is default?! */ autofile f = Melder_fopen (file, "r+b"); file -> filePointer = f; // essential !! double sampleRate_d; long startOfData, numberOfSamples; int numberOfChannels, encoding; int audioFileType = MelderFile_checkSoundFile (file, &numberOfChannels, &encoding, &sampleRate_d, &startOfData, &numberOfSamples); if (audioFileType == 0) { Melder_throw ("Not a sound file."); } // Check whether all the sample rates and channels match. long sampleRate = sampleRate_d; for (long i = 1; i <= my size; i++) { int sampleRatesMatch, numbersOfChannelsMatch; Sampled data = (Sampled) my item [i]; if (data -> classInfo == classSound) { Sound sound = (Sound) data; sampleRatesMatch = floor (1.0 / sound -> dx + 0.5) == sampleRate; numbersOfChannelsMatch = sound -> ny == numberOfChannels; numberOfSamples += sound -> nx; } else { LongSound longSound = (LongSound) data; sampleRatesMatch = longSound -> sampleRate == sampleRate; numbersOfChannelsMatch = longSound -> numberOfChannels == numberOfChannels; numberOfSamples += longSound -> nx; } if (! sampleRatesMatch) { Melder_throw ("Sample rates do not match."); } if (! numbersOfChannelsMatch) { Melder_throw ("Cannot mix stereo and mono."); } } // Search the end of the file, count the number of bytes and append. MelderFile_seek (file, 0, SEEK_END); pre_append_endpos = MelderFile_tell (file); errno = 0; for (long i = 1; i <= my size; i++) { Sampled data = (Sampled) my item [i]; if (data -> classInfo == classSound) { Sound sound = (Sound) data; MelderFile_writeFloatToAudio (file, sound -> ny, Melder_defaultAudioFileEncoding (audioFileType, numberOfBitsPerSamplePoint), sound -> z, sound -> nx, true); } else { LongSound longSound = (LongSound) data; writePartToOpenFile16 (longSound, audioFileType, 1, longSound -> nx, file); } if (errno != 0) { Melder_throw ("Error during writing."); } } // Update header MelderFile_rewind (file); MelderFile_writeAudioFileHeader (file, audioFileType, sampleRate, numberOfSamples, numberOfChannels, numberOfBitsPerSamplePoint); MelderFile_writeAudioFileTrailer (file, audioFileType, sampleRate, numberOfSamples, numberOfChannels, numberOfBitsPerSamplePoint); f.close (file); return; } catch (MelderError) { if (errno != 0 && pre_append_endpos > 0) { // Restore file at original size int error = errno; MelderFile_truncate (file, pre_append_endpos); Melder_throw ("File ", MelderFile_messageName (file), L" restored to original size (", strerror (error), ")."); } throw; } }
autoMatrix Matrix_readFromIDXFormatFile (MelderFile file) { /* From: http://yann.lecun.com/exdb/mnist/ The IDX file format is a simple format for vectors and multidimensional matrices of various numerical types. The basic format is magic number size in dimension 0 size in dimension 1 size in dimension 2 .... size in dimension N data The magic number is an integer (MSB first). The first 2 bytes are always 0. The third byte codes the type of the data: 0x08: unsigned byte 0x09: signed byte 0x0B: short (2 bytes) 0x0C: int (4 bytes) 0x0D: float (4 bytes) 0x0E: double (8 bytes) The 4-th byte codes the number of dimensions of the vector/matrix: 1 for vectors, 2 for matrices.... The sizes in each dimension are 4-byte integers (MSB first, big endian, like in most non-Intel processors). The data is stored like in a C array, i.e. the index in the last dimension changes the fastest. */ try { autofile f = Melder_fopen (file, "r"); unsigned int b1 = bingetu1 (f); // 0 unsigned int b2 = bingetu1 (f); // 0 if (b1 != 0 || b2 != 0) { Melder_throw (U"Starting two bytes should be zero."); } unsigned int b3 = bingetu1 (f); // data type unsigned int b4 = bingetu1 (f); // number of dimensions long ncols = bingeti32 (f), nrows = 1; // ok if vector if (b4 > 1) { nrows = ncols; ncols = bingeti32 (f); } while (b4 > 2) { // accumulate all other dimensions in the columns long n2 = bingeti32 (f); ncols *= n2; // put the matrix in one row -- b4; } autoMatrix me = Matrix_create (0.0, ncols, ncols, 1, 0.5, 0, nrows, nrows, 1.0, 0.5); if (b3 == 0x08) { // unsigned byte for (long irow = 1; irow <= nrows; irow ++) { for (long icol = 1; icol <= ncols; icol ++) { my z [irow] [icol] = bingetu1 (f); } } } else if (b3 == 0x09) { // signed byte for (long irow = 1; irow <= nrows; irow ++) { for (long icol = 1; icol <= ncols; icol ++) { my z [irow] [icol] = bingeti1 (f); } } } else if (b3 == 0x0B) { // short (2 bytes) for (long irow = 1; irow <= nrows; irow ++) { for (long icol = 1; icol <= ncols; icol ++) { my z [irow] [icol] = bingeti2 (f); } } } else if (b3 == 0x0C) { // int (4 bytes) for (long irow = 1; irow <= nrows; irow ++) { for (long icol = 1; icol <= ncols; icol ++) { my z [irow] [icol] = bingeti32 (f); } } } else if (b3 == 0x0D) { // float (4 bytes) for (long irow = 1; irow <= nrows; irow ++) { for (long icol = 1; icol <= ncols; icol ++) { my z [irow] [icol] = bingetr4 (f); } } } else if (b3 == 0x0E) { // double (8 bytes) for (long irow = 1; irow <= nrows; irow ++) { for (long icol = 1; icol <= ncols; icol ++) { my z [irow] [icol] = bingetr8 (f); } } } else { Melder_throw (U"Not a valid data type."); } f.close (file); return me; } catch (MelderError) { Melder_throw (U"Cannot read from IDX format file ", MelderFile_messageName (file), U"."); } }