📄 fileread.cpp
字号:
bool FileRead :: getAifInfo( const char *fileName ){ bool aifc = false; char id[4]; // Determine whether this is AIFF or AIFC. if ( fseek(fd_, 8, SEEK_SET) == -1 ) goto error; if ( fread(&id, 4, 1, fd_) != 1 ) goto error; if ( !strncmp(id, "AIFC", 4) ) aifc = true; // Find "common" chunk SINT32 chunkSize; if ( fread(&id, 4, 1, fd_) != 1) goto error; while ( strncmp(id, "COMM", 4) ) { if ( fread(&chunkSize, 4, 1, fd_) != 1 ) goto error;#ifdef __LITTLE_ENDIAN__ swap32((unsigned char *)&chunkSize);#endif chunkSize += chunkSize % 2; // chunk sizes must be even if ( fseek(fd_, chunkSize, SEEK_CUR) == -1 ) goto error; if ( fread(&id, 4, 1, fd_) != 1 ) goto error; } // Get number of channels from the header. SINT16 temp; if ( fseek(fd_, 4, SEEK_CUR) == -1 ) goto error; // Jump over chunk size if ( fread(&temp, 2, 1, fd_) != 1 ) goto error;#ifdef __LITTLE_ENDIAN__ swap16((unsigned char *)&temp);#endif channels_ = temp; // Get length of data from the header. SINT32 frames; if ( fread(&frames, 4, 1, fd_) != 1 ) goto error;#ifdef __LITTLE_ENDIAN__ swap32((unsigned char *)&frames);#endif fileSize_ = frames; // sample frames // Read the number of bits per sample. if ( fread(&temp, 2, 1, fd_) != 1 ) goto error;#ifdef __LITTLE_ENDIAN__ swap16((unsigned char *)&temp);#endif // Get file sample rate from the header. For AIFF files, this value // is stored in a 10-byte, IEEE Standard 754 floating point number, // so we need to convert it first. unsigned char srate[10]; unsigned char exp; unsigned long mantissa; unsigned long last; if ( fread(&srate, 10, 1, fd_) != 1 ) goto error; mantissa = (unsigned long) *(unsigned long *)(srate+2);#ifdef __LITTLE_ENDIAN__ swap32((unsigned char *)&mantissa);#endif exp = 30 - *(srate+1); last = 0; while (exp--) { last = mantissa; mantissa >>= 1; } if (last & 0x00000001) mantissa++; fileRate_ = (StkFloat) mantissa; // Determine the data format. dataType_ = 0; if ( aifc == false ) { if ( temp <= 8 ) dataType_ = STK_SINT8; else if ( temp <= 16 ) dataType_ = STK_SINT16; else if ( temp <= 24 ) dataType_ = STK_SINT24; else if ( temp <= 32 ) dataType_ = STK_SINT32; } else { if ( fread(&id, 4, 1, fd_) != 1 ) goto error; if ( !strncmp(id, "NONE", 4) ) { if ( temp <= 8 ) dataType_ = STK_SINT8; else if ( temp <= 16 ) dataType_ = STK_SINT16; else if ( temp <= 24 ) dataType_ = STK_SINT24; else if ( temp <= 32 ) dataType_ = STK_SINT32; } else if ( (!strncmp(id, "fl32", 4) || !strncmp(id, "FL32", 4)) && temp == 32 ) dataType_ = STK_FLOAT32; else if ( (!strncmp(id, "fl64", 4) || !strncmp(id, "FL64", 4)) && temp == 64 ) dataType_ = STK_FLOAT64; } if ( dataType_ == 0 ) {#if !defined(SYMBIAN) errorString_ << "FileRead: AIFF/AIFC file (" << fileName << ") has unsupported data type (" << id << ").";#endif return false; } // Start at top to find data (SSND) chunk ... chunk order is undefined. if ( fseek(fd_, 12, SEEK_SET) == -1 ) goto error; // Find data (SSND) chunk if ( fread(&id, 4, 1, fd_) != 1 ) goto error; while ( strncmp(id, "SSND", 4) ) { if ( fread(&chunkSize, 4, 1, fd_) != 1 ) goto error;#ifdef __LITTLE_ENDIAN__ swap32((unsigned char *)&chunkSize);#endif chunkSize += chunkSize % 2; // chunk sizes must be even if ( fseek(fd_, chunkSize, SEEK_CUR) == -1 ) goto error; if ( fread(&id, 4, 1, fd_) != 1 ) goto error; } // Skip over chunk size, offset, and blocksize fields if ( fseek(fd_, 12, SEEK_CUR) == -1 ) goto error; dataOffset_ = ftell(fd_); byteswap_ = false;#ifdef __LITTLE_ENDIAN__ byteswap_ = true;#endif return true; error:#if !defined(SYMBIAN) errorString_ << "FileRead: Error reading AIFF file (" << fileName << ").";#endif return false;}bool FileRead :: getMatInfo( const char *fileName ){ // MAT-file formatting information is available at: // http://www.mathworks.com/access/helpdesk/help/pdf_doc/matlab/matfile_format.pdf // Verify this is a version 5 MAT-file format. char head[4]; if ( fseek(fd_, 0, SEEK_SET) == -1 ) goto error; if ( fread(&head, 4, 1, fd_) != 1 ) goto error; // If any of the first 4 characters of the header = 0, then this is // a Version 4 MAT-file. if ( strstr(head, "0") ) {#if !defined(SYMBIAN) errorString_ << "FileRead: " << fileName << " appears to be a Version 4 MAT-file, which is not currently supported.";#endif return false; } // Determine the endian-ness of the file. char mi[2]; byteswap_ = false; // Locate "M" and "I" characters in header. if ( fseek(fd_, 126, SEEK_SET) == -1 ) goto error; if ( fread(&mi, 2, 1, fd_) != 1) goto error;#ifdef __LITTLE_ENDIAN__ if ( !strncmp(mi, "MI", 2) ) byteswap_ = true; else if ( strncmp(mi, "IM", 2) ) goto error;#else if ( !strncmp(mi, "IM", 2)) byteswap_ = true; else if ( strncmp(mi, "MI", 2) ) goto error;#endif // Check the data element type SINT32 datatype; if ( fread(&datatype, 4, 1, fd_) != 1 ) goto error; if ( byteswap_ ) swap32((unsigned char *)&datatype); if (datatype != 14) {#if !defined(SYMBIAN) errorString_ << "FileRead: The file does not contain a single Matlab array (or matrix) data element.";#endif return false; } // Determine the array data type. SINT32 tmp; SINT32 size; if ( fseek(fd_, 168, SEEK_SET) == -1 ) goto error; if ( fread(&tmp, 4, 1, fd_) != 1 ) goto error; if (byteswap_) swap32((unsigned char *)&tmp); if (tmp == 1) { // array name > 4 characters if ( fread(&tmp, 4, 1, fd_) != 1 ) goto error; // get array name length if (byteswap_) swap32((unsigned char *)&tmp); size = (SINT32) ceil((float)tmp / 8); if ( fseek(fd_, size*8, SEEK_CUR) == -1 ) goto error; // jump over array name } else { // array name <= 4 characters, compressed data element if ( fseek(fd_, 4, SEEK_CUR) == -1 ) goto error; } if ( fread(&tmp, 4, 1, fd_) != 1 ) goto error; if (byteswap_) swap32((unsigned char *)&tmp); if ( tmp == 1 ) dataType_ = STK_SINT8; else if ( tmp == 3 ) dataType_ = STK_SINT16; else if ( tmp == 5 ) dataType_ = STK_SINT32; else if ( tmp == 7 ) dataType_ = STK_FLOAT32; else if ( tmp == 9 ) dataType_ = STK_FLOAT64; else {#if !defined(SYMBIAN) errorString_ << "FileRead: The MAT-file array data format (" << tmp << ") is not supported.";#endif return false; } // Get number of rows from the header. SINT32 rows; if ( fseek(fd_, 160, SEEK_SET) == -1 ) goto error; if ( fread(&rows, 4, 1, fd_) != 1 ) goto error; if (byteswap_) swap32((unsigned char *)&rows); // Get number of columns from the header. SINT32 columns; if ( fread(&columns, 4, 1, fd_) != 1 ) goto error; if (byteswap_) swap32((unsigned char *)&columns); // Assume channels = smaller of rows or columns. if (rows < columns) { channels_ = rows; fileSize_ = columns; } else {#if !defined(SYMBIAN) errorString_ << "FileRead: Transpose the MAT-file array so that audio channels fill matrix rows (not columns).";#endif return false; } // Move read pointer to the data in the file. SINT32 headsize; if ( fseek(fd_, 132, SEEK_SET) == -1 ) goto error; if ( fread(&headsize, 4, 1, fd_) != 1 ) goto error; // file size from 132nd byte if (byteswap_) swap32((unsigned char *)&headsize); headsize -= fileSize_ * 8 * channels_; if ( fseek(fd_, headsize, SEEK_CUR) == -1 ) goto error; dataOffset_ = ftell(fd_); // Assume MAT-files have 44100 Hz sample rate. fileRate_ = 44100.0; return true; error:#if !defined(SYMBIAN) errorString_ << "FileRead: Error reading MAT-file (" << fileName << ").";#endif return false;}void FileRead :: read( StkFrames& buffer, unsigned long startFrame, bool doNormalize ){ // Make sure we have an open file. if ( fd_ == 0 ) {#if !defined(SYMBIAN) errorString_ << "FileRead::read: a file is not open!"; Stk::handleError( StkError::WARNING );#endif return; } // Check the buffer size. unsigned int nFrames = buffer.frames(); if ( nFrames == 0 ) {#if !defined(SYMBIAN) errorString_ << "FileRead::read: StkFrames buffer size is zero ... no data read!"; Stk::handleError( StkError::WARNING );#endif return; } if ( buffer.channels() != channels_ ) {#if !defined(SYMBIAN) errorString_ << "FileRead::read: StkFrames argument has incompatible number of channels!"; Stk::handleError( StkError::FUNCTION_ARGUMENT );#endif } // Check for file end. if ( startFrame + nFrames >= fileSize_ ) nFrames = fileSize_ - startFrame; long i, nSamples = (long) ( nFrames * channels_ ); unsigned long offset = startFrame * channels_; // Read samples into StkFrames data buffer. if ( dataType_ == STK_SINT16 ) { SINT16 *buf = (SINT16 *) &buffer[0]; if ( fseek( fd_, dataOffset_+(offset*2), SEEK_SET ) == -1 ) goto error; if ( fread( buf, nSamples * 2, 1, fd_ ) != 1 ) goto error; if ( byteswap_ ) { SINT16 *ptr = buf; for ( i=nSamples-1; i>=0; i-- ) swap16( (unsigned char *) ptr++ ); } if ( doNormalize ) { StkFloat gain = 1.0 / 32768.0; for ( i=nSamples-1; i>=0; i-- ) buffer[i] = buf[i] * gain; } else { for ( i=nSamples-1; i>=0; i-- ) buffer[i] = buf[i]; } } else if ( dataType_ == STK_SINT32 ) { SINT32 *buf = (SINT32 *) &buffer[0]; if ( fseek( fd_, dataOffset_+(offset*4 ), SEEK_SET ) == -1 ) goto error; if ( fread( buf, nSamples * 4, 1, fd_ ) != 1 ) goto error; if ( byteswap_ ) { SINT32 *ptr = buf; for ( i=nSamples-1; i>=0; i-- ) swap32( (unsigned char *) ptr++ ); } if ( doNormalize ) { StkFloat gain = 1.0 / 2147483648.0; for ( i=nSamples-1; i>=0; i-- ) buffer[i] = buf[i] * gain; } else { for ( i=nSamples-1; i>=0; i-- ) buffer[i] = buf[i]; } } else if ( dataType_ == STK_FLOAT32 ) { FLOAT32 *buf = (FLOAT32 *) &buffer[0]; if ( fseek( fd_, dataOffset_+(offset*4), SEEK_SET ) == -1 ) goto error; if ( fread( buf, nSamples * 4, 1, fd_ ) != 1 ) goto error; if ( byteswap_ ) { FLOAT32 *ptr = buf; for ( i=nSamples-1; i>=0; i-- ) swap32( (unsigned char *) ptr++ ); } for ( i=nSamples-1; i>=0; i-- ) buffer[i] = buf[i]; } else if ( dataType_ == STK_FLOAT64 ) { FLOAT64 *buf = (FLOAT64 *) &buffer[0]; if ( fseek( fd_, dataOffset_+(offset*8), SEEK_SET ) == -1 ) goto error; if ( fread( buf, nSamples * 8, 1, fd_ ) != 1 ) goto error; if ( byteswap_ ) { FLOAT64 *ptr = buf; for ( i=nSamples-1; i>=0; i-- ) swap64( (unsigned char *) ptr++ ); } for ( i=nSamples-1; i>=0; i-- ) buffer[i] = buf[i]; } else if ( dataType_ == STK_SINT8 && wavFile_ ) { // 8-bit WAV data is unsigned! unsigned char *buf = (unsigned char *) &buffer[0]; if ( fseek( fd_, dataOffset_+offset, SEEK_SET ) == -1 ) goto error; if ( fread( buf, nSamples, 1, fd_) != 1 ) goto error; if ( doNormalize ) { StkFloat gain = 1.0 / 128.0; for ( i=nSamples-1; i>=0; i-- ) buffer[i] = ( buf[i] - 128 ) * gain; } else { for ( i=nSamples-1; i>=0; i-- ) buffer[i] = buf[i] - 128.0; } } else if ( dataType_ == STK_SINT8 ) { // signed 8-bit data char *buf = (char *) &buffer[0]; if ( fseek( fd_, dataOffset_+offset, SEEK_SET ) == -1 ) goto error; if ( fread( buf, nSamples, 1, fd_ ) != 1 ) goto error; if ( doNormalize ) { StkFloat gain = 1.0 / 128.0; for ( i=nSamples-1; i>=0; i-- ) buffer[i] = buf[i] * gain; } else { for ( i=nSamples-1; i>=0; i-- ) buffer[i] = buf[i]; } } else if ( dataType_ == STK_SINT24 ) { // 24-bit values are harder to import efficiently since there is // no native 24-bit type. The following routine works but is much // less efficient that that used for the other data types. SINT32 buf; StkFloat gain = 1.0 / 8388608.0; if ( fseek(fd_, dataOffset_+(offset*3), SEEK_SET ) == -1 ) goto error; for ( i=0; i<nSamples; i++ ) { if ( fread( &buf, 3, 1, fd_ ) != 1 ) goto error; buf >>= 8; if ( byteswap_ ) swap32( (unsigned char *) &buf ); if ( doNormalize ) buffer[i] = buf * gain; else buffer[i] = buf; } } buffer.setDataRate( fileRate_ ); return; error:#if !defined(SYMBIAN) errorString_ << "FileRead: Error reading file data."; handleError( StkError::FILE_ERROR);#else {}#endif}// #endif // SYMBIAN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -