?? filewrite.cpp
字號:
/***************************************************//*! \class FileWrite \brief STK audio file output class. This class provides output support for various audio file formats. FileWrite writes samples to an audio file. It supports multi-channel data. FileWrite 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. STK RAW files use 16-bit integers by definition. MAT-files will always be written as 64-bit floats. If a data type specification does not match the specified file type, the data type will automatically be modified. Compressed data types are not supported. by Perry R. Cook and Gary P. Scavone, 1995 - 2005.*//***************************************************/#include "FileWrite.h"#if !defined(SYMBIAN)#include <cmath>#else#include "symbmath.h"#endifconst FileWrite::FILE_TYPE FileWrite :: FILE_RAW = 1;const FileWrite::FILE_TYPE FileWrite :: FILE_WAV = 2;const FileWrite::FILE_TYPE FileWrite :: FILE_SND = 3;const FileWrite::FILE_TYPE FileWrite :: FILE_AIF = 4;const FileWrite::FILE_TYPE FileWrite :: FILE_MAT = 5;// WAV header structure. See ftp://ftp.isi.edu/in-notes/rfc2361.txt// for information regarding format codes.struct wavhdr { char riff[4]; // "RIFF" SINT32 file_size; // in bytes char wave[4]; // "WAVE" char fmt[4]; // "fmt " SINT32 chunk_size; // in bytes (16 for PCM) SINT16 format_tag; // 1=PCM, 2=ADPCM, 3=IEEE float, 6=A-Law, 7=Mu-Law SINT16 num_chans; // 1=mono, 2=stereo SINT32 sample_rate; SINT32 bytes_per_sec; SINT16 bytes_per_samp; // 2=16-bit mono, 4=16-bit stereo SINT16 bits_per_samp; char data[4]; // "data" SINT32 data_length; // in bytes};// SND (AU) header structure (NeXT and Sun).struct sndhdr { char pref[4]; SINT32 hdr_length; SINT32 data_length; SINT32 format; SINT32 sample_rate; SINT32 num_channels; char comment[16];};// AIFF/AIFC header structure ... only the part common to both// formats.struct aifhdr { char form[4]; // "FORM" SINT32 form_size; // in bytes char aiff[4]; // "AIFF" or "AIFC" char comm[4]; // "COMM" SINT32 comm_size; // "COMM" chunk size (18 for AIFF, 24 for AIFC) SINT16 num_chans; // number of channels unsigned long sample_frames; // sample frames of audio data SINT16 sample_size; // in bits unsigned char srate[10]; // IEEE 754 floating point format};struct aifssnd { char ssnd[4]; // "SSND" SINT32 ssnd_size; // "SSND" chunk size unsigned long offset; // data offset in data block (should be 0) unsigned long block_size; // not used by STK (should be 0)};// MAT-file 5 header structure.struct mathdr { char heading[124]; // Header text field SINT16 hff[2]; // Header flag fields SINT32 adf[11]; // Array data format fields // There's more, but it's of variable length};FileWrite :: FileWrite() : fd_( 0 ){}#if !defined(SYMBIAN)FileWrite::FileWrite( std::string fileName, unsigned int nChannels, FILE_TYPE type, Stk::StkFormat format )#elseFileWrite::FileWrite( const char *fileName, unsigned int nChannels, FILE_TYPE type, Stk::StkFormat format )#endif : fd_( 0 ){ this->open( fileName, nChannels, type, format );}FileWrite :: ~FileWrite(){ this->close();}void FileWrite :: close( void ){ if ( fd_ == 0 ) return; if ( fileType_ == FILE_RAW ) fclose( fd_ ); else if ( fileType_ == FILE_WAV ) this->closeWavFile(); else if ( fileType_ == FILE_SND ) this->closeSndFile(); else if ( fileType_ == FILE_AIF ) this->closeAifFile(); else if ( fileType_ == FILE_MAT ) this->closeMatFile(); fd_ = 0;}bool FileWrite :: isOpen( void ){ if ( fd_ ) return true; else return false;}#if !defined(SYMBIAN)void FileWrite :: open( std::string fileName, unsigned int nChannels, FileWrite::FILE_TYPE type, Stk::StkFormat format )#elsevoid FileWrite :: open( const char *fileName, unsigned int nChannels, FileWrite::FILE_TYPE type, Stk::StkFormat format )#endif{ // Call close() in case another file is already open. this->close(); if ( nChannels < 1 ) {#if !defined(SYMBIAN) errorString_ << "FileWrite::open: then channels argument must be greater than zero!"; handleError( StkError::FUNCTION_ARGUMENT );#endif } channels_ = nChannels; fileType_ = type; if ( format != STK_SINT8 && format != STK_SINT16 && format != STK_SINT32 && format != STK_FLOAT32 && format != STK_FLOAT64 ) {#if !defined(SYMBIAN) errorString_ << "FileWrite::open: unknown data type (" << format << ") specified!"; handleError( StkError::FUNCTION_ARGUMENT );#endif } dataType_ = format; bool result = false; if ( fileType_ == FILE_RAW ) { if ( channels_ != 1 ) {#if !defined(SYMBIAN) errorString_ << "FileWrite::open: STK RAW files are, by definition, always monaural (channels = " << nChannels << " not supported)!"; handleError( StkError::FUNCTION_ARGUMENT );#endif }#if !defined(SYMBIAN) result = setRawFile( fileName.c_str() );#else result = setRawFile( fileName );#endif } else if ( fileType_ == FILE_WAV )#if !defined(SYMBIAN) result = setWavFile( fileName.c_str() );#else result = setWavFile( fileName );#endif else if ( fileType_ == FILE_SND )#if !defined(SYMBIAN) result = setSndFile( fileName.c_str() );#else result = setSndFile( fileName );#endif else if ( fileType_ == FILE_AIF )#if !defined(SYMBIAN) result = setAifFile( fileName.c_str() );#else result = setAifFile( fileName );#endif else if ( fileType_ == FILE_MAT )#if !defined(SYMBIAN) result = setMatFile( fileName.c_str() );#else result = setMatFile( fileName );#endif else {#if !defined(SYMBIAN) errorString_ << "FileWrite::open: unknown file type (" << fileType_ << ") specified!"; handleError( StkError::FUNCTION_ARGUMENT );#endif }#if !defined(SYMBIAN) if ( result == false ) handleError( StkError::FILE_ERROR );#endif frameCounter_ = 0;}bool FileWrite :: setRawFile( const char *fileName ){ char name[8192]; strncpy(name, fileName, 8192); if ( strstr(name, ".raw") == NULL) strcat(name, ".raw"); fd_ = fopen(name, "wb"); if ( !fd_ ) {#if !defined(SYMBIAN) errorString_ << "FileWrite: could not create RAW file: " << name << '.';#endif return false; } if ( dataType_ != STK_SINT16 ) { dataType_ = STK_SINT16;#if !defined(SYMBIAN) errorString_ << "FileWrite: using 16-bit signed integer data format for file " << name << '.'; handleError( StkError::DEBUG_WARNING );#endif } byteswap_ = false;#ifdef __LITTLE_ENDIAN__ byteswap_ = true;#endif#if !defined(SYMBIAN) errorString_ << "FileWrite: creating RAW file: " << name; handleError( StkError::STATUS );#endif return true;}bool FileWrite :: setWavFile( const char *fileName ){ char name[8192]; strncpy(name, fileName, 8192); if ( strstr(name, ".wav") == NULL) strcat(name, ".wav"); fd_ = fopen(name, "wb"); if ( !fd_ ) {#if !defined(SYMBIAN) errorString_ << "FileWrite: could not create WAV file: " << name;#endif return false; } struct wavhdr hdr = {"RIF", 44, "WAV", "fmt", 16, 1, 1, (SINT32) Stk::sampleRate(), 0, 2, 16, "dat", 0}; hdr.riff[3] = 'F'; hdr.wave[3] = 'E'; hdr.fmt[3] = ' '; hdr.data[3] = 'a'; hdr.num_chans = (SINT16) channels_; if ( dataType_ == STK_SINT8 ) hdr.bits_per_samp = 8; else if ( dataType_ == STK_SINT16 ) hdr.bits_per_samp = 16; else if ( dataType_ == STK_SINT32 ) hdr.bits_per_samp = 32; else if ( dataType_ == STK_FLOAT32 ) { hdr.format_tag = 3; hdr.bits_per_samp = 32; } else if ( dataType_ == STK_FLOAT64 ) { hdr.format_tag = 3; hdr.bits_per_samp = 64; } hdr.bytes_per_samp = (SINT16) (channels_ * hdr.bits_per_samp / 8); hdr.bytes_per_sec = (SINT32) (hdr.sample_rate * hdr.bytes_per_samp); byteswap_ = false;#ifndef __LITTLE_ENDIAN__ byteswap_ = true; swap32((unsigned char *)&hdr.file_size); swap32((unsigned char *)&hdr.chunk_size); swap16((unsigned char *)&hdr.format_tag); swap16((unsigned char *)&hdr.num_chans); swap32((unsigned char *)&hdr.sample_rate); swap32((unsigned char *)&hdr.bytes_per_sec); swap16((unsigned char *)&hdr.bytes_per_samp); swap16((unsigned char *)&hdr.bits_per_samp);#endif if ( fwrite(&hdr, 4, 11, fd_) != 11 ) {#if !defined(SYMBIAN) errorString_ << "FileWrite: could not write WAV header for file " << name << '.';#endif return false; }#if !defined(SYMBIAN) errorString_ << "FileWrite: creating WAV file: " << name; handleError( StkError::STATUS );#endif return true;}void FileWrite :: closeWavFile( void ){ int bytes_per_sample = 1; if ( dataType_ == STK_SINT16 ) bytes_per_sample = 2; else if ( dataType_ == STK_SINT32 || dataType_ == STK_FLOAT32 ) bytes_per_sample = 4; else if ( dataType_ == STK_FLOAT64 ) bytes_per_sample = 8; SINT32 bytes = frameCounter_ * channels_ * bytes_per_sample;#ifndef __LITTLE_ENDIAN__ swap32((unsigned char *)&bytes);#endif fseek(fd_, 40, SEEK_SET); // jump to data length fwrite(&bytes, 4, 1, fd_); bytes = frameCounter_ * channels_ * bytes_per_sample + 44;#ifndef __LITTLE_ENDIAN__ swap32((unsigned char *)&bytes);#endif fseek(fd_, 4, SEEK_SET); // jump to file size fwrite(&bytes, 4, 1, fd_); fclose( fd_ );}bool FileWrite :: setSndFile( const char *fileName ){ char name[8192]; strncpy(name, fileName, 8192); if ( strstr(name, ".snd") == NULL) strcat(name, ".snd"); fd_ = fopen(name, "wb"); if ( !fd_ ) {#if !defined(SYMBIAN) errorString_ << "FileWrite: could not create SND file: " << name;#endif return false; } struct sndhdr hdr = {".sn", 40, 0, 3, (SINT32) Stk::sampleRate(), 1, "Created by STK"}; hdr.pref[3] = 'd'; hdr.num_channels = channels_; if ( dataType_ == STK_SINT8 ) hdr.format = 2; else if ( dataType_ == STK_SINT16 ) hdr.format = 3; else if ( dataType_ == STK_SINT32 ) hdr.format = 5; else if ( dataType_ == STK_FLOAT32 ) hdr.format = 6; else if ( dataType_ == STK_FLOAT64 ) hdr.format = 7; byteswap_ = false;#ifdef __LITTLE_ENDIAN__ byteswap_ = true; swap32 ((unsigned char *)&hdr.hdr_length); swap32 ((unsigned char *)&hdr.format); swap32 ((unsigned char *)&hdr.sample_rate); swap32 ((unsigned char *)&hdr.num_channels);#endif if ( fwrite(&hdr, 4, 10, fd_) != 10 ) {#if !defined(SYMBIAN) errorString_ << "FileWrite: Could not write SND header for file " << name << '.';#endif return false; }#if !defined(SYMBIAN) errorString_ << "FileWrite: creating SND file: " << name; handleError( StkError::STATUS );#endif return true;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -