/* SpiralSynth * Copyleft (C) 2000 David Griffiths * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include "RiffWav.h" //#include "SpiralInfo.h" #include #include #include //#define TRACE_OUT using namespace std; #ifndef USE_LIBSNDFILE const int HEADERLEN = (4+24+8); #if __BYTE_ORDER == BIG_ENDIAN #define SWAPSHORT(a) (a)=(((a)<<8)|(((a)>>8)&0xff)) #define SWAPINT(a) (a)=(((a)&0x000000ff)<<24)|(((a)&0x0000ff00)<<8)|(((a)&0x00ff0000)>>8)|(((a)&0xff000000)>>24) #define SWAPFLOAT(a) swap_be_to_le_float(&a) #else #define SWAPSHORT(a) #define SWAPINT(a) #define SWAPFLOAT(a) #endif static void swap_be_to_le_float(float *a) { float tmp; char *src, *dst; src = (char*)a; dst = (char*)&tmp; dst[0] = src[3]; dst[1] = src[2]; dst[2] = src[1]; dst[3] = src[0]; *a = tmp; } static void write_float_as_16bit_short(float v, FILE *file) { short value=(short)(v*SHRT_MAX); SWAPSHORT(value); fwrite(((char*) &value),2,1,file); } static void write_float_as_24bit_int(float v, FILE *file) { char data[3]; #if __BYTE_ORDER == BIG_ENDIAN data[0] = (int)(v*0x7FFFFF) >> 16; data[1] = ((int)(v*0x7FFFFF) >> 8); data[2] = ((int)(v*0x7FFFFF)); #else data[0] = (int)(v*0x7FFFFF); data[1] = ((int)(v*0x7FFFFF) >> 8); data[2] = ((int)(v*0x7FFFFF) >> 16); #endif fwrite(data,3,1,file); } static void write_float_as_32bit_float(float v, FILE *file) { float value=v; SWAPFLOAT(v); fwrite(((char*) &v),4,1,file); } #endif int WavFile::Open(string FileName, Mode mode, Channels channels) { #ifdef USE_LIBSNDFILE if (m_FileHandle!=NULL) { cerr<<"WavFile: File already open ["<16) { fseek(m_Stream,m_Header.FmtLength-16,SEEK_CUR); } fread(&m_DataHeader,sizeof(DataHeader),1,m_Stream); SWAPINT(m_DataHeader.DataLengthBytes); while (m_DataHeader.DataName[0]!='d' || m_DataHeader.DataName[1]!='a' || m_DataHeader.DataName[2]!='t' || m_DataHeader.DataName[3]!='a') { // crawl through the rest of the propriatory headers // if we need to to try and get to the data header if (feof(m_Stream) || fseek(m_Stream,-(sizeof(DataHeader)-1),SEEK_CUR)==-1) { cerr<<"WavFile: File open error, wrong format ["<1) m=1; switch (WavFile::m_BitsPerSample) { case 16: write_float_as_16bit_short(m, m_Stream); break; case 24: write_float_as_24bit_int(m, m_Stream); break; case 32: write_float_as_32bit_float(m, m_Stream); break; default: return 0; } } m_DataHeader.DataLengthBytes+=data.GetLength()*(WavFile::m_BitsPerSample/8); return 1; #endif } int WavFile::Save(short *data, int Bytes) { #ifdef USE_LIBSNDFILE if (m_FileHandle==NULL || data==NULL) { return 0; } sf_write_short(m_FileHandle, data, Bytes*m_FileInfo.channels/2); return 1; #else if (m_Stream==NULL || data==NULL) { return 0; } m_DataHeader.DataLengthBytes+=Bytes; fwrite(data,sizeof(data),Bytes/4,m_Stream); return 1; #endif } int WavFile::Save(float *left, float *right, int Length) { #ifdef USE_LIBSNDFILE if (m_FileHandle==NULL || left==NULL || right==NULL) { return 0; } if (IsStereo())// Interleave the channels into buffer and write { float *TempBuf = new float[Length*2]; for (int n=0; n1) l=1; if (r<-1) r=-1; if (r>1) r=1; switch (WavFile::m_BitsPerSample) { case 16: write_float_as_16bit_short(l, m_Stream); write_float_as_16bit_short(r, m_Stream); break; case 24: write_float_as_24bit_int(l, m_Stream); write_float_as_24bit_int(r, m_Stream); break; case 32: write_float_as_32bit_float(l, m_Stream); write_float_as_32bit_float(r, m_Stream); break; default: return 0; } } m_DataHeader.DataLengthBytes+=Length*2*(WavFile::m_BitsPerSample/8); return 1; #endif } #ifndef USE_LIBSNDFILE int WavFile::GetSize() { int Bps = m_Header.FmtBitsPerSample/8; if ((Bps<1) || (Bps>4)) { cerr<<"WavFile Warning: FmtBitsPerSample="<1) // mix the channels into a mono buffer { #ifdef TRACE_OUT cerr<<"WavFile::Load - Channels = "<1) // mix the channels into a mono buffer { #ifdef TRACE_OUT cerr<<"WavFile::Load - Channels = "<1) // mix the channels into a mono buffer { #ifdef TRACE_OUT cerr<<"WavFile::Load - Channels = "<1) // mix the channels into a mono buffer { #ifdef TRACE_OUT cerr<<"WavFile::Load - Channels = "<1) rdata.Set(n,TempBuf[n*m_FileInfo.channels+1]); } } delete[] TempBuf; return 1; #else int c = m_Header.FmtChannels; int SizeBytes = NumSamples * 2 * c; // 2 bytes per sample per channel short *TempBuf = new short[NumSamples * c]; if (SizeBytes!=(int)fread(TempBuf,1,SizeBytes,m_Stream)) { cerr<<"WavFile: Read chunk error"<