📄 fileread.cpp
字号:
/***************************************************//*! \class FileRead \brief STK audio file input class. This class provides input support for various audio file formats. Multi-channel (>2) soundfiles are supported. The file data is returned via an external StkFrames object passed to the read() function. This class does not store its own copy of the file data, rather the data is read directly from disk. FileRead currently supports uncompressed WAV, AIFF/AIFC, SND (AU), MAT-file (Matlab), and STK RAW file formats. Signed integer (8-, 16-, and 32-bit) and floating-point (32- and 64-bit) data types are supported. Compressed data types are not supported. STK RAW files have no header and are assumed to contain a monophonic stream of 16-bit signed integers in big-endian byte order at a sample rate of 22050 Hz. MAT-file data should be saved in an array with each data channel filling a matrix row. The sample rate for MAT-files is assumed to be 44100 Hz. by Perry R. Cook and Gary P. Scavone, 1995 - 2005.*//***************************************************/#include "FileRead.h"#if !defined(SYMBIAN)#include <sys/stat.h>#include <sys/types.h>#include <cmath>#else#include "symbmath.h"#endifFileRead :: FileRead() : fd_(0){}#if !defined(SYMBIAN)FileRead :: FileRead( std::string fileName, bool typeRaw )#elseFileRead :: FileRead( const char* fileName, bool typeRaw )#endif : fd_(0){ open( fileName, typeRaw );}FileRead :: ~FileRead(){ if ( fd_ ) fclose( fd_ );}void FileRead :: close( void ){ if ( fd_ ) fclose( fd_ ); fd_ = 0; wavFile_ = false;}bool FileRead :: isOpen( void ){ if ( fd_ ) return true; else return false;}#if !defined(SYMBIAN)void FileRead :: open( std::string fileName, bool typeRaw ) {#elsevoid FileRead :: open( const char *fileName, TBool typeRaw ){#endif // If another file is open, close it. close(); // Try to open the file.#if !defined(SYMBIAN) fd_ = fopen( fileName.c_str(), "rb" );#else fd_ = fopen( fileName, "rb" );#endif if ( !fd_ ) { /* errorString_ << "FileRead::open: could not open or find file (" << fileName << ")!"; handleError( StkError::FILE_NOT_FOUND ); */ } // Attempt to determine file type from header (unless RAW). bool result = false; if ( typeRaw )#if !defined(SYMBIAN) result = getRawInfo( fileName.c_str() );#else result = getRawInfo( fileName );#endif else { char header[12]; if ( fread( &header, 4, 3, fd_ ) != 3 ) goto error; if ( !strncmp( header, "RIFF", 4 ) && !strncmp( &header[8], "WAVE", 4 ) )#if !defined(SYMBIAN) result = getWavInfo( fileName.c_str() );#else result = getWavInfo( fileName );#endif else if ( !strncmp( header, ".snd", 4 ) )#if !defined(SYMBIAN) result = getSndInfo( fileName.c_str() );#else result = getSndInfo( fileName );#endif else if ( !strncmp( header, "FORM", 4 ) && ( !strncmp( &header[8], "AIFF", 4 ) || !strncmp(&header[8], "AIFC", 4) ) )#if !defined(SYMBIAN) result = getAifInfo( fileName.c_str() );#else result = getAifInfo( fileName );#endif else { if ( fseek( fd_, 126, SEEK_SET ) == -1 ) goto error; if ( fread( &header, 2, 1, fd_ ) != 1 ) goto error; if ( !strncmp( header, "MI", 2 ) || !strncmp( header, "IM", 2 ) )#if !defined(SYMBIAN) result = getMatInfo( fileName.c_str() );#else result = getMatInfo( fileName );#endif else {#if !defined(SYMBIAN) errorString_ << "FileRead::open: file (" << fileName << ") format unknown."; handleError( StkError::FILE_UNKNOWN_FORMAT );#endif } } } // If here, we had a file type candidate but something else went wrong.#if !defined(SYMBIAN) if ( result == false ) handleError( StkError::FILE_ERROR );#endif // Check for empty files. if ( fileSize_ == 0 ) {#if !defined(SYMBIAN) errorString_ << "FileRead::open: file (" << fileName << ") data size is zero!"; handleError( StkError::FILE_ERROR );#endif } return; error:#if !defined(SYMBIAN) errorString_ << "FileRead::open: error reading file (" << fileName << ")!"; handleError( StkError::FILE_ERROR );#else {}#endif}bool FileRead :: getRawInfo( const char *fileName ){ // Use the system call "stat" to determine the file length. struct stat filestat; if ( stat(fileName, &filestat) == -1 ) {#if !defined(SYMBIAN) errorString_ << "FileRead: Could not stat RAW file (" << fileName << ").";#endif return false; } // STK rawwave files have no header and are assumed to contain a // monophonic stream of 16-bit signed integers in big-endian byte // order at a sample rate of 22050 Hz. channels_ = 1; fileSize_ = (long) filestat.st_size / 2; // length in 2-byte samples dataOffset_ = 0; fileRate_ = 22050.0; dataType_ = STK_SINT16; byteswap_ = false;#ifdef __LITTLE_ENDIAN__ byteswap_ = true;#endif return true;}bool FileRead :: getWavInfo( const char *fileName ){ // Find "format" chunk ... it must come before the "data" chunk. char id[4]; SINT32 chunkSize; if ( fread(&id, 4, 1, fd_) != 1 ) goto error; while ( strncmp(id, "fmt ", 4) ) { if ( fread(&chunkSize, 4, 1, fd_) != 1 ) goto error;#ifndef __LITTLE_ENDIAN__ swap32((unsigned char *)&chunkSize);#endif if ( fseek(fd_, chunkSize, SEEK_CUR) == -1 ) goto error; if ( fread(&id, 4, 1, fd_) != 1 ) goto error; } // Check that the data is not compressed. unsigned short format_tag; if ( fread(&chunkSize, 4, 1, fd_) != 1 ) goto error; // Read fmt chunk size. if ( fread(&format_tag, 2, 1, fd_) != 1 ) goto error;#ifndef __LITTLE_ENDIAN__ swap16((unsigned char *)&format_tag); swap32((unsigned char *)&chunkSize);#endif if ( format_tag == 0xFFFE ) { // WAVE_FORMAT_EXTENSIBLE dataOffset_ = ftell(fd_); if ( fseek(fd_, 14, SEEK_CUR) == -1 ) goto error; unsigned short extSize; if ( fread(&extSize, 2, 1, fd_) != 1 ) goto error;#ifndef __LITTLE_ENDIAN__ swap16((unsigned char *)&extSize);#endif if ( extSize == 0 ) goto error; if ( fseek(fd_, 6, SEEK_CUR) == -1 ) goto error; if ( fread(&format_tag, 2, 1, fd_) != 1 ) goto error;#ifndef __LITTLE_ENDIAN__ swap16((unsigned char *)&format_tag);#endif if ( fseek(fd_, dataOffset_, SEEK_SET) == -1 ) goto error; } if (format_tag != 1 && format_tag != 3 ) { // PCM = 1, FLOAT = 3#if !defined(SYMBIAN) errorString_ << "FileRead: "<< fileName << " contains an unsupported data format type (" << format_tag << ").";#endif return false; } // Get number of channels from the header. SINT16 temp; if ( fread(&temp, 2, 1, fd_) != 1 ) goto error;#ifndef __LITTLE_ENDIAN__ swap16((unsigned char *)&temp);#endif channels_ = (unsigned int ) temp; // Get file sample rate from the header. SINT32 srate; if ( fread(&srate, 4, 1, fd_) != 1 ) goto error;#ifndef __LITTLE_ENDIAN__ swap32((unsigned char *)&srate);#endif fileRate_ = (StkFloat) srate; // Determine the data type. dataType_ = 0; if ( fseek(fd_, 6, SEEK_CUR) == -1 ) goto error; // Locate bits_per_sample info. if ( fread(&temp, 2, 1, fd_) != 1 ) goto error;#ifndef __LITTLE_ENDIAN__ swap16((unsigned char *)&temp);#endif if ( format_tag == 1 ) { if (temp == 8) dataType_ = STK_SINT8; else if (temp == 16) dataType_ = STK_SINT16; else if (temp == 32) dataType_ = STK_SINT32; } else if ( format_tag == 3 ) { if (temp == 32) dataType_ = STK_FLOAT32; else if (temp == 64) dataType_ = STK_FLOAT64; } if ( dataType_ == 0 ) {#if !defined(SYMBIAN) errorString_ << "FileRead: " << temp << " bits per sample with data format " << format_tag << " are not supported (" << fileName << ").";#endif return false; } // Jump over any remaining part of the "fmt" chunk. if ( fseek(fd_, chunkSize-16, SEEK_CUR) == -1 ) goto error; // Find "data" chunk ... it must come after the "fmt" chunk. if ( fread(&id, 4, 1, fd_) != 1 ) goto error; while ( strncmp(id, "data", 4) ) { if ( fread(&chunkSize, 4, 1, fd_) != 1 ) goto error;#ifndef __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 length of data from the header. SINT32 bytes; if ( fread(&bytes, 4, 1, fd_) != 1 ) goto error;#ifndef __LITTLE_ENDIAN__ swap32((unsigned char *)&bytes);#endif fileSize_ = 8 * bytes / temp / channels_; // sample frames dataOffset_ = ftell(fd_); byteswap_ = false;#ifndef __LITTLE_ENDIAN__ byteswap_ = true;#endif wavFile_ = true; return true; error:#if !defined(SYMBIAN) errorString_ << "FileRead: error reading WAV file (" << fileName << ").";#endif return false;}bool FileRead :: getSndInfo( const char *fileName ){ // Determine the data type. UINT32 format; if ( fseek(fd_, 12, SEEK_SET) == -1 ) goto error; // Locate format if ( fread(&format, 4, 1, fd_) != 1 ) goto error;#ifdef __LITTLE_ENDIAN__ swap32((unsigned char *)&format);#endif if (format == 2) dataType_ = STK_SINT8; else if (format == 3) dataType_ = STK_SINT16; else if (format == 4) dataType_ = STK_SINT24; else if (format == 5) dataType_ = STK_SINT32; else if (format == 6) dataType_ = STK_FLOAT32; else if (format == 7) dataType_ = STK_FLOAT64; else {#if !defined(SYMBIAN) errorString_ << "FileRead: data format in file " << fileName << " is not supported.";#endif return false; } // Get file sample rate from the header. UINT32 srate; if ( fread(&srate, 4, 1, fd_) != 1 ) goto error;#ifdef __LITTLE_ENDIAN__ swap32((unsigned char *)&srate);#endif fileRate_ = (StkFloat) srate; // Get number of channels from the header. UINT32 chans; if ( fread(&chans, 4, 1, fd_) != 1 ) goto error;#ifdef __LITTLE_ENDIAN__ swap32((unsigned char *)&chans);#endif channels_ = chans; if ( fseek(fd_, 4, SEEK_SET) == -1 ) goto error; if ( fread(&dataOffset_, 4, 1, fd_) != 1 ) goto error;#ifdef __LITTLE_ENDIAN__ swap32((unsigned char *)&dataOffset_);#endif // Get length of data from the header. if ( fread(&fileSize_, 4, 1, fd_) != 1 ) goto error;#ifdef __LITTLE_ENDIAN__ swap32((unsigned char *)&fileSize_);#endif // Convert to sample frames. if ( dataType_ == STK_SINT8 ) fileSize_ /= channels_; if ( dataType_ == STK_SINT16 ) fileSize_ /= 2 * channels_; else if ( dataType_ == STK_SINT24 ) fileSize_ /= 3 * channels_; else if ( dataType_ == STK_SINT32 || dataType_ == STK_FLOAT32 ) fileSize_ /= 4 * channels_; else if ( dataType_ == STK_FLOAT64 ) fileSize_ /= 8 * channels_; byteswap_ = false;#ifdef __LITTLE_ENDIAN__ byteswap_ = true;#endif return true; error:#if !defined(SYMBIAN) errorString_ << "FileRead: Error reading SND file (" << fileName << ").";#endif return false;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -