// // Programmer: Craig Stuart Sapp // Creation Date: Fri Nov 1 23:35:02 PST 1996 // Last Modified: Sat Apr 4 22:47:36 GMT-0800 1998 // Last Modified: Wed Mar 17 16:52:53 PST 1999 // Filename: ...sig/maint/code/Generator/SoundFileIn/SoundFileIn.cpp // Web Address: http://sig.sapp.org/src/sigSignal/SoundFileIn.cpp // Documentation: http://sig.sapp.org/doc/classes/SoundFileIn // Syntax: C++ // #include "SoundFileIn.h" #include #include #ifndef OLDCPP #include using namespace std; #else #include #endif ////////////////////////////// // // SoundFileIn::SoundFileIn -- // defaults: aFileName = "", start = NONE, dur = NONE // SoundFileIn::SoundFileIn(const char* aFileName, float start, float dur) { setName("SoundFileIn"); 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; } ////////////////////////////// // // SoundFileIn::~SoundFileIn -- // SoundFileIn::~SoundFileIn() { delete [] filename; } ////////////////////////////// // // SoundFileIn::action -- // void SoundFileIn::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; } } ////////////////////////////// // // SoundFileIn::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 SoundFileIn::extractSample16Bit(void) { short sample; switch (endianType) { case SIG_BIG_ENDIAN: sndfile.readBigEndian(sample); break; case SIG_LITTLE_ENDIAN: sndfile.readLittleEndian(sample); break; } return sample; } ////////////////////////////// // // SoundFileIn::getBitsPerSample -- // int SoundFileIn::getBitsPerSample(void) { return sndHeader.getBitsPerSample(); } ////////////////////////////// // // SoundFileIn::getChannels -- // int SoundFileIn::getChannels(void) { return sndHeader.getChannels(); } ////////////////////////////// // // SoundFileIn::getFilename -- // const char* SoundFileIn::getFilename(void) const { if (filename == NULL) { return ""; } else { return filename; } } ////////////////////////////// // // SoundFileIn::getHeader -- // SoundHeader& SoundFileIn::getHeader(void) { return sndHeader; } ////////////////////////////// // // SoundFileIn::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 SoundFileIn::getSamples(void) { return maxSampleIndex + 1; } ////////////////////////////// // // SoundFileIn::output -- // default: channel = 0 // sampleType SoundFileIn::output(int channel) { return Output[channel]; } ////////////////////////////// // // SoundFileIn::printState -- // void SoundFileIn::printState(void) { int oldFlag = sndHeader.setOutputType(TYPE_TEXT); cerr << "Filename: " << filename << endl; cerr << sndHeader; sndHeader.setOutputType(oldFlag); } ////////////////////////////// // // SoundFileIn::reset -- // default: sampleIndex = 0 // void SoundFileIn::reset(int sampleIndex) { if (sampleIndex < 0) { sndfile.seekp(sndHeader.getDataByteOffset()-1); } else { sndfile.seekp((int)(sndHeader.getDataByteOffset() - 1 + (sampleIndex + begSampleIndex) * sndHeader.getChannels() * sndHeader.getBitsPerSample() / 8.0)); } } ////////////////////////////// // // SoundFileIn::setFile -- // void SoundFileIn::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)); determineSampleReadingFunction(); } /////////////////////////////////////////////////////////////////////////// // // private functions // // The following functions are used by the readSample function. // These functions have to be outside of the SoundFileIn class // because Microsoft's Visual C++ 5.0 compiler cannot handle pointers // to class member functions. // big endian samples sampleType soundReadSample8M_B (FileIO& soundFile); sampleType soundReadSample8L_B (FileIO& soundFile); sampleType soundReadSample16L_B (FileIO& soundFile); sampleType soundReadSample24L_B (FileIO& soundFile); sampleType soundReadSample32L_B (FileIO& soundFile); sampleType soundReadSample32F_B (FileIO& soundFile); sampleType soundReadSample64F_B (FileIO& soundFile); // little endian samples sampleType soundReadSample8M_L (FileIO& soundFile); sampleType soundReadSample8L_L (FileIO& soundFile); sampleType soundReadSample16L_L (FileIO& soundFile); sampleType soundReadSample24L_L (FileIO& soundFile); sampleType soundReadSample32L_L (FileIO& soundFile); sampleType soundReadSample32F_L (FileIO& soundFile); sampleType soundReadSample64F_L (FileIO& soundFile); ////////////////////////////// // // SoundFileIn::determineSampleReadingFunction -- // void SoundFileIn::determineSampleReadingFunction(void) { switch (sndHeader.getInputType()) { case TYPE_SND: // big endian samples endianType = SIG_BIG_ENDIAN; switch (sndHeader.getNextFormat()) { case SND_FORMAT_MULAW_8: readSample = soundReadSample8M_B; break; case SND_FORMAT_LINEAR_8: readSample = soundReadSample8L_B; break; case SND_FORMAT_LINEAR_16: readSample = soundReadSample16L_B; break; case SND_FORMAT_LINEAR_24: readSample = soundReadSample24L_B; break; case SND_FORMAT_LINEAR_32: readSample = soundReadSample32L_B; break; case SND_FORMAT_FLOAT: readSample = soundReadSample32F_B; break; case SND_FORMAT_DOUBLE: readSample = 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 = soundReadSample8M_L; break; case SND_FORMAT_LINEAR_8: readSample = soundReadSample8L_L; break; case SND_FORMAT_LINEAR_16: readSample = soundReadSample16L_L; break; case SND_FORMAT_LINEAR_24: readSample = soundReadSample24L_L; break; case SND_FORMAT_LINEAR_32: readSample = soundReadSample32L_L; break; case SND_FORMAT_FLOAT: readSample = soundReadSample32F_L; break; case SND_FORMAT_DOUBLE: readSample = 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); } } ////////////////////////////// // // SoundFileIn::fillOutputArray -- // void SoundFileIn::fillOutputArray(void) { for (int i=0; i