// // Programmer: Craig Stuart Sapp // Creation Date: Tue Mar 9 08:05:31 PST 1999 // Last Modified: Tue Mar 9 08:05:34 PST 1999 // Filename: ...sig/code/Generator/SoundFileInMemory/SoundFileInMemory.cpp // Syntax: C++ // $Smake: cc -Wall -g -c %b.cpp -I../../../include && rm -f %b.o // #include "SoundFileInMemory.h" #include #include #ifndef OLDCPP #include using namespace std; #else #include #endif int SoundFileInMemory::memoryUsage = 0; ////////////////////////////// // // SoundFileInMemory::SoundFileInMemory -- // defaults: aFileName = "", start = NONE, dur = NONE // SoundFileInMemory::SoundFileInMemory(const char* aFileName, float start, float dur) { setName("SoundFileInMemory"); soundData = NULL; dataPointer = -1; soundDataSize = 0; borrowedQ = 0; filename = NULL; maxSampleIndex = -1; curSampleIndex = 0; begSampleIndex = 0; if (strlen(aFileName) > 0) { setFile(aFileName, start, dur); // set the size of the output array to the number of channels Output.setSize(sndHeader.getChannels()); Output.allowGrowth(0); } else { Output.setSize(4); Output.allowGrowth(1); } Output.zero(); runningQ = 1; loopingQ = 0; brandname = GENERATOR; } ////////////////////////////// // // SoundFileInMemory::~SoundFileInMemory -- // SoundFileInMemory::~SoundFileInMemory() { if (filename != NULL) { delete [] filename; filename = NULL; } if (borrowedQ != 1 && soundData != NULL) { memoryUsage -= soundDataSize; delete [] soundData; soundDataSize = 0; } } ////////////////////////////// // // SoundFileInMemory::action -- // void SoundFileInMemory::action(void) { if (!runningQ) return; // read the soundfile samples into the output array if (curSampleIndex < 0 || curSampleIndex > maxSampleIndex) { for (int i=0; i endSampleIndex && loopingQ) { curSampleIndex = begSampleIndex; } } ////////////////////////////// // // SoundFileInMemory::borrow -- Borrow data from another // similar object // void SoundFileInMemory::borrow(const SoundFileInMemory& aFile) { if (borrowedQ == 0 && soundData != NULL) { memoryUsage -= soundDataSize; delete [] soundData; soundData = NULL; } soundData = aFile.soundData; dataPointer = 0; soundDataSize = aFile.soundDataSize; borrowedQ = 1; sndHeader = aFile.sndHeader; if (filename != NULL) { delete [] filename; filename = NULL; } filename = new char[strlen(aFile.filename) + 1]; strcpy(filename, aFile.filename); endianType = aFile.endianType; readSample = aFile.readSample; } ////////////////////////////// // // SoundFileInMemory::extractSample16Bit -- reads a sample from the // soundfile. The soundfile must be in 16 bit format or else // unreported errors will occur. Also, you cannot use the // action function after calling this function since this // function does not keep track of the number of samples read // from the file. This function is used only to extract the // integer sample values without converting them to floating // point samples. // short SoundFileInMemory::extractSample16Bit(void) { short sample = 0; switch (endianType) { case SIG_BIG_ENDIAN: readBigEndian(sample); break; case SIG_LITTLE_ENDIAN: readLittleEndian(sample); break; } return sample; } ////////////////////////////// // // SoundFileInMemory::getBitsPerSample -- // int SoundFileInMemory::getBitsPerSample(void) { return sndHeader.getBitsPerSample(); } ////////////////////////////// // // SoundFileInMemory::getChannels -- // int SoundFileInMemory::getChannels(void) { return sndHeader.getChannels(); } ////////////////////////////// // // SoundFileInMemory::getFilename -- // const char* SoundFileInMemory::getFilename(void) const { if (filename == NULL) { return ""; } else { return filename; } } ////////////////////////////// // // SoundFileInMemory::getMemoryUsage -- return the number of bytes // being used for all SoundFileInMemory objects. // int SoundFileInMemory::getMemoryUsage(void) { return memoryUsage; } ////////////////////////////// // // SoundFileInMemory::getHeader -- // SoundHeader& SoundFileInMemory::getHeader(void) { return sndHeader; } ////////////////////////////// // // SoundFileInMemory::getSamples -- returns the number of samples // in the soundfile. If a soundfile has more than one // channel, then all of the samples occuring at the // same time are considered to be ONE sample according // to the counting convention of this function. // In other words, if you know the sample rate for // the sound file, then dividing the count returned // by this function by the sampling rate will return the // duration of the soundfile. // long SoundFileInMemory::getSamples(void) { return maxSampleIndex + 1; } ////////////////////////////// // // SoundFileInMemory::output -- // default: channel = 0 // sampleType SoundFileInMemory::output(int channel) { return Output[channel]; } ////////////////////////////// // // SoundFileInMemory::ownership -- returns true if this object // owns the sound memory // int SoundFileInMemory::ownership(void) const { return !borrowedQ; } ////////////////////////////// // // SoundFileInMemory::printState -- // void SoundFileInMemory::printState(void) { int oldFlag = sndHeader.setOutputType(TYPE_TEXT); cerr << "Filename: " << filename << endl; cerr << sndHeader; sndHeader.setOutputType(oldFlag); } ////////////////////////////// // // SoundFileInMemory::reset -- // default: sampleIndex = 0 // void SoundFileInMemory::reset(int sampleIndex) { dataPointer = 0; if (sampleIndex < 0) { sndfile.seekp(sndHeader.getDataByteOffset()-1); } else { sndfile.seekp((int)(sndHeader.getDataByteOffset() - 1 + (sampleIndex + begSampleIndex) * sndHeader.getChannels() * sndHeader.getBitsPerSample() / 8.0)); } } ////////////////////////////// // // SoundFileInMemory::setFile -- // void SoundFileInMemory::setFile(const char* aFileName, float start, float dur) { if (filename != NULL) delete [] filename; filename = new char[strlen(aFileName)+1]; strcpy(filename, aFileName); sndHeader.setHeader(filename); if (sndfile.is_open()) sndfile.close(); #ifdef VISUAL /* for stupid LF-CR prevention in DOS */ sndfile.open(filename, ios::in | ios::binary); #else sndfile.open(filename, ios::in); #endif if(!sndfile.is_open()) { cerr << "Error: sound file " << filename << " could not be opened!" << endl; exit(1); } // determine the beginning and ending samples according to start and dur maxSampleIndex = sndHeader.getSamples() - 1; if (maxSampleIndex < 0) { cerr << "Error: sound file " << filename << " has no data!" << endl; exit(1); } if (start >= 0) { begSampleIndex = (long)(start * sndHeader.getSrate()); } else { begSampleIndex = 0; } if (begSampleIndex > maxSampleIndex) begSampleIndex = 0; if (dur >= 0) { endSampleIndex = begSampleIndex + (long)(dur * sndHeader.getSrate()); } else { endSampleIndex = maxSampleIndex; } if (endSampleIndex > maxSampleIndex) { endSampleIndex = maxSampleIndex; } curSampleIndex = begSampleIndex; // set the file to the current sample sndfile.seekp((long)(sndHeader.getDataByteOffset() + curSampleIndex * sndHeader.getChannels() * sndHeader.getBitsPerSample() / 8.0)); // now load the samples into the soundData storage array in memory if (borrowedQ == 0 && soundData != NULL) { delete [] soundData; memoryUsage -= soundDataSize; if (memoryUsage < 0) { cout << "Warning in SoundFileInMemory: Weird memory management" << endl; } } if (borrowedQ == 1) { borrowedQ = 0; } soundDataSize = getSamples() * getChannels() * (getBitsPerSample()/8); cout << "SoundDataSize = " << soundDataSize << endl; soundData = new char[soundDataSize]; sndfile.read(soundData, soundDataSize); dataPointer = 0; memoryUsage += soundDataSize; determineSampleReadingFunction(); } /////////////////////////////////////////////////////////////////////////// // // private functions // // The following functions are used by the readSample function. // These functions have to be outside of the SoundFileInMemory class // because Microsoft's Visual C++ 5.0 compiler cannot handle pointers // to class member functions. // big endian samples sampleType SMEM_soundReadSample8M_B (SoundFileInMemory& x); sampleType SMEM_soundReadSample8L_B (SoundFileInMemory& x); sampleType SMEM_soundReadSample16L_B (SoundFileInMemory& x); sampleType SMEM_soundReadSample24L_B (SoundFileInMemory& x); sampleType SMEM_soundReadSample32L_B (SoundFileInMemory& x); sampleType SMEM_soundReadSample32F_B (SoundFileInMemory& x); sampleType SMEM_soundReadSample64F_B (SoundFileInMemory& x); // little endian samples sampleType SMEM_soundReadSample8M_L (SoundFileInMemory& x); sampleType SMEM_soundReadSample8L_L (SoundFileInMemory& x); sampleType SMEM_soundReadSample16L_L (SoundFileInMemory& x); sampleType SMEM_soundReadSample24L_L (SoundFileInMemory& x); sampleType SMEM_soundReadSample32L_L (SoundFileInMemory& x); sampleType SMEM_soundReadSample32F_L (SoundFileInMemory& x); sampleType SMEM_soundReadSample64F_L (SoundFileInMemory& x); ////////////////////////////// // // SoundFileInMemory::determineSampleReadingFunction -- // void SoundFileInMemory::determineSampleReadingFunction(void) { switch (sndHeader.getInputType()) { case TYPE_SND: // big endian samples endianType = SIG_BIG_ENDIAN; switch (sndHeader.getNextFormat()) { case SND_FORMAT_MULAW_8: readSample = SMEM_soundReadSample8M_B; break; case SND_FORMAT_LINEAR_8: readSample = SMEM_soundReadSample8L_B; break; case SND_FORMAT_LINEAR_16: readSample = SMEM_soundReadSample16L_B; break; case SND_FORMAT_LINEAR_24: readSample = SMEM_soundReadSample24L_B; break; case SND_FORMAT_LINEAR_32: readSample = SMEM_soundReadSample32L_B; break; case SND_FORMAT_FLOAT: readSample = SMEM_soundReadSample32F_B; break; case SND_FORMAT_DOUBLE: readSample = SMEM_soundReadSample64F_B; break; default: cerr << "Error: unknown input soundfile format: " << sndHeader.getNextFormat() << endl; exit(1); } break; case TYPE_WAV_PCM: // little endian samples endianType = SIG_LITTLE_ENDIAN; switch (sndHeader.getNextFormat()) { case SND_FORMAT_MULAW_8: readSample = SMEM_soundReadSample8M_L; break; case SND_FORMAT_LINEAR_8: readSample = SMEM_soundReadSample8L_L; break; case SND_FORMAT_LINEAR_16: readSample = SMEM_soundReadSample16L_L; break; case SND_FORMAT_LINEAR_24: readSample = SMEM_soundReadSample24L_L; break; case SND_FORMAT_LINEAR_32: readSample = SMEM_soundReadSample32L_L; break; case SND_FORMAT_FLOAT: readSample = SMEM_soundReadSample32F_L; break; case SND_FORMAT_DOUBLE: readSample = SMEM_soundReadSample64F_L; break; default: cerr << "Error: unknown input soundfile format: " << sndHeader.getNextFormat() << endl; exit(1); } break; default: ; // the soundfile name is probably a dummy, and will not be used // cerr << "Error: unknown soundfile type: " // << sndHeader.getInputType() << endl; // exit(1); } } ////////////////////////////// // // SoundFileInMemory::fillOutputArray -- // void SoundFileInMemory::fillOutputArray(void) { for (int i=0; i= soundDataSize) { aNumber = '\0'; } aNumber = soundData[dataPointer]; dataPointer += 1; } void SoundFileInMemory::storageRead(uchar& aNumber) { if (dataPointer >= soundDataSize) { aNumber = '\0'; } aNumber = (uchar)soundData[dataPointer]; dataPointer += 1; } void SoundFileInMemory::storageRead(short& aNumber) { if (dataPointer >= soundDataSize - 1) { aNumber = 0; } aNumber = (uchar)soundData[dataPointer]; dataPointer += 1; aNumber = aNumber << 8; aNumber |= (uchar)soundData[dataPointer]; dataPointer += 1; } void SoundFileInMemory::storageRead(ushort& aNumber) { if (dataPointer >= soundDataSize - 1) { aNumber = 0; } aNumber = (uchar)soundData[dataPointer]; dataPointer += 1; aNumber = aNumber << 8; aNumber |= (uchar)soundData[dataPointer]; dataPointer += 1; } void SoundFileInMemory::storageRead(long& aNumber) { if (dataPointer >= soundDataSize - 3) { aNumber = 0; } aNumber = (uchar)soundData[dataPointer]; dataPointer += 1; aNumber = aNumber << 8; aNumber |= (uchar)soundData[dataPointer]; dataPointer += 1; aNumber = aNumber << 8; aNumber |= (uchar)soundData[dataPointer]; dataPointer += 1; aNumber = aNumber << 8; aNumber |= (uchar)soundData[dataPointer]; dataPointer += 1; } void SoundFileInMemory::storageRead(ulong& aNumber) { if (dataPointer >= soundDataSize - 3) { aNumber = 0; } aNumber = (uchar)soundData[dataPointer]; dataPointer += 1; aNumber = aNumber << 8; aNumber |= (uchar)soundData[dataPointer]; dataPointer += 1; aNumber = aNumber << 8; aNumber |= (uchar)soundData[dataPointer]; dataPointer += 1; aNumber = aNumber << 8; aNumber |= (uchar)soundData[dataPointer]; dataPointer += 1; } void SoundFileInMemory::storageRead(int& aNumber) { if (dataPointer >= soundDataSize - 3) { aNumber = 0; } aNumber = (uchar)soundData[dataPointer]; dataPointer += 1; aNumber = aNumber << 8; aNumber |= (uchar)soundData[dataPointer]; dataPointer += 1; aNumber = aNumber << 8; aNumber |= (uchar)soundData[dataPointer]; dataPointer += 1; aNumber = aNumber << 8; aNumber |= (uchar)soundData[dataPointer]; dataPointer += 1; } void SoundFileInMemory::storageRead(uint& aNumber) { if (dataPointer >= soundDataSize - 3) { aNumber = 0; } aNumber = (uchar)soundData[dataPointer]; dataPointer += 1; aNumber = aNumber << 8; aNumber |= (uchar)soundData[dataPointer]; dataPointer += 1; aNumber = aNumber << 8; aNumber |= (uchar)soundData[dataPointer]; dataPointer += 1; aNumber = aNumber << 8; aNumber |= (uchar)soundData[dataPointer]; dataPointer += 1; } void SoundFileInMemory::storageRead(float& aNumber) { if (dataPointer >= soundDataSize - 7) { aNumber = 0; } char* fpointer = (char*)&aNumber; fpointer[0] = (uchar)soundData[dataPointer]; dataPointer += 1; fpointer[1] = (uchar)soundData[dataPointer]; dataPointer += 1; fpointer[2] = (uchar)soundData[dataPointer]; dataPointer += 1; fpointer[3] = (uchar)soundData[dataPointer]; dataPointer += 1; } void SoundFileInMemory::storageRead(double& aNumber) { if (dataPointer >= soundDataSize - 7) { aNumber = 0; } char* fpointer = (char*)&aNumber; fpointer[0] = (uchar)soundData[dataPointer]; dataPointer += 1; fpointer[1] = (uchar)soundData[dataPointer]; dataPointer += 1; fpointer[2] = (uchar)soundData[dataPointer]; dataPointer += 1; fpointer[3] = (uchar)soundData[dataPointer]; dataPointer += 1; fpointer[4] = (uchar)soundData[dataPointer]; dataPointer += 1; fpointer[5] = (uchar)soundData[dataPointer]; dataPointer += 1; fpointer[6] = (uchar)soundData[dataPointer]; dataPointer += 1; fpointer[7] = (uchar)soundData[dataPointer]; dataPointer += 1; } /////////////////////////////////////////////////////////////////////////// // // private functions // ////////////////////////////// // // SoundFileInMemory::flipBytes -- flip the bytes in a number // char SoundFileInMemory::flipBytes(char aNumber) { return aNumber; } uchar SoundFileInMemory::flipBytes(uchar aNumber) { return aNumber; } short SoundFileInMemory::flipBytes(short aNumber) { static uchar output[2]; static uchar* input; input = (uchar*)(&aNumber); output[0] = input[1]; output[1] = input[0]; return *((short*)(&output)); } ushort SoundFileInMemory::flipBytes(ushort aNumber) { static uchar output[2]; static uchar* input; input = (uchar*)(&aNumber); output[0] = input[1]; output[1] = input[0]; return *((ushort*)(&output)); } long SoundFileInMemory::flipBytes(long aNumber) { static uchar output[4]; static uchar* input; input = (uchar*)(&aNumber); output[0] = input[3]; output[1] = input[2]; output[2] = input[1]; output[3] = input[0]; return *((long*)(&output)); } ulong SoundFileInMemory::flipBytes(ulong aNumber) { static uchar output[4]; static uchar* input; input = (uchar*)(&aNumber); output[0] = input[3]; output[1] = input[2]; output[2] = input[1]; output[3] = input[0]; return *((ulong*)(&output)); } int SoundFileInMemory::flipBytes(int aNumber) { static uchar output[sizeof(uint)]; static uchar* input; input = (uchar*)(&aNumber); for(uint i=0; i