// // Programmer: Craig Stuart Sapp // Copyright: Copyright 2002 Craig Stuart Sapp // Creation Date: Fri Jan 18 22:25:27 PST 2002 // Last Modified: Wed Jan 23 20:24:34 PST 2002 // Last Modified: Sat Feb 2 12:22:17 PST 2002 (fixed looping and goto) // Filename: SoundFileRead.cpp // Based On: http://sig.sapp.org/src/sigSignal/SoundFileIn.cpp // Syntax: C++ // #include "SoundFileRead.h" #include #include #ifndef OLDCPP #include using namespace std; #else #include #endif ////////////////////////////// // // SoundFileRead::SoundFileRead -- // defaults: aFileName = "", start = -1, dur = -1 // SoundFileRead::SoundFileRead(const char* aFileName, double start, double dur) { filename = NULL; curIndex = 0; begIndex = 0; endIndex = 0; loopingQ = 0; endianType = 0; if (strlen(aFileName) > 0) { setFile(aFileName, start, dur); // set the size of the current array to the number of channels } else { current.setSize(4); current.allowGrowth(1); current.zero(); } } ////////////////////////////// // // SoundFileRead::~SoundFileRead -- What to do when destroying a // SoundFileRead object. // SoundFileRead::~SoundFileRead() { if (filename != NULL) { delete [] filename; filename = NULL; } } ///////////////////////////// // // SoundFileRead::getCurrentSample16Bit -- return a 16 bit // version of the current channel sample. // default value: channel = 0 // int SoundFileRead::getCurrentSample16Bit(int channel) { return (int)((long)0x8000 * getCurrentSampleDouble(channel)); // rounding necessary? } ////////////////////////////// // // SoundFileRead::getNextSample16Bit -- increment the current sample array // and return the requested channel value. Returns // default value: channel = 0 // int SoundFileRead::getNextSample16Bit(int channel) { incrementSample(); return getCurrentSample16Bit(channel); } ///////////////////////////// // // SoundFileRead::getCurrentSample24Bit -- return a 24 bit // version of the current channel sample. // default value: channel = 0 // int SoundFileRead::getCurrentSample24Bit(int channel) { return (int)((long)0x800000 * getCurrentSampleDouble(channel)); } ////////////////////////////// // // SoundFileRead::getNextSample24Bit -- increment the current sample array // and return the requested channel value. Returns // default value: channel = 0 // int SoundFileRead::getNextSample24Bit(int channel) { incrementSample(); return getCurrentSample24Bit(channel); } ///////////////////////////// // // SoundFileRead::getCurrentSampleDouble -- return a 16 bit // version of the current channel sample. // default value: channel = 0 // double SoundFileRead::getCurrentSampleDouble(int channel) { return current[channel]; } ////////////////////////////// // // SoundFileRead::getNextSampleDouble -- increment the current sample // array and return the requested channel value. Returns // default value: channel = 0 // double SoundFileRead::getNextSampleDouble(int channel) { incrementSample(); return getCurrentSampleDouble(channel); } ////////////////////////////// // // SoundFileRead::getCurrentSampleIndex -- return the sample index of // the current sample data. // int SoundFileRead::getCurrentSampleIndex(void) { return curIndex; } ////////////////////////////// // // SoundFileRead::incrementSample -- read the next sample set and // store in current array. // void SoundFileRead::incrementSample(void) { curIndex++; if (curIndex > endIndex && loopingQ) { gotoSample(begIndex); return; } else if (curIndex < 0 || curIndex > endIndex) { for (int i=0; i= 0) { begIndex = (long)(start * getSrate()); } else { begIndex = 0; } if (begIndex > maxIndex) begIndex = 0; if (dur >= 0) { endIndex = begIndex + (long)(dur * getSrate()); } else { endIndex = maxIndex; } if (endIndex > maxIndex) { endIndex = maxIndex; } } ////////////////////////////// // // SoundFileRead::reset -- Go to the starting point in the file, // either the start of the file, or the start specified in // the setFile() function. // default: sampleIndex = -1 // void SoundFileRead::reset(int sampleIndex) { if (sampleIndex < 0) { gotoSample(begIndex); } else { gotoSample(sampleIndex); } } ////////////////////////////// // // SoundFileRead::gotoSample -- Move to the current sample position // in the soundfile and start reading from that point. // void SoundFileRead::gotoSample(int sampleIndex) { int offset = 0; if (sampleIndex < 0) { offset = getDataByteOffset(); sndfile.seekg(offset); // used to be: sndfile.seekp(offset); sampleIndex = 0; } else { offset = (int)(getDataByteOffset() + (sampleIndex + begIndex) * getChannels() * getBitsPerSample() / 8.0); sndfile.seekg(offset); // used to be: sndfile.seekp(offset); } curIndex = sampleIndex; fillCurrentArray(); } ////////////////////////////// // // SoundFileRead::setFile -- start reading a soundfile at the current // start time and for the given duration. // void SoundFileRead::setFile(const char* aFileName, double start, double dur) { if (filename != NULL) delete [] filename; filename = new char[strlen(aFileName)+1]; strcpy(filename, aFileName); setHeader(filename); if (sndfile.is_open()) sndfile.close(); #ifdef VISUAL /* for stupid LF-CR prevention in Windows */ 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); } setStartAndDuration(start, dur); determineReadingFunction(); // set the file to the current sample gotoSample(begIndex); } ////////////////////////////// // // SoundFileRead::setLoopOption -- turn looping on or off // SoundFileRead::setLoopOn -- turn looping on // SoundFileRead::setLoopOff -- turn looping off // void SoundFileRead::setLoopOption(int mode) { if (mode == 0) { loopingQ = 0; } else { loopingQ = 1; } } void SoundFileRead::setLoopOn(void) { setLoopOption(1); } void SoundFileRead::setLoopOff(void) { setLoopOption(0); } /////////////////////////////////////////////////////////////////////////// // // private functions // // The following functions are used by the readSample function. // These functions have to be outside of the SoundFileRead class // because Microsoft's Visual C++ 5.0 compiler cannot handle pointers // to class member functions. // big endian samples double soundReadSample8M_B (FileIO& soundFile); double soundReadSample8L_B (FileIO& soundFile); double soundReadSample16L_B (FileIO& soundFile); double soundReadSample24L_B (FileIO& soundFile); double soundReadSample32L_B (FileIO& soundFile); double soundReadSample32F_B (FileIO& soundFile); double soundReadSample64F_B (FileIO& soundFile); // little endian samples double soundReadSample8M_L (FileIO& soundFile); double soundReadSample8L_L (FileIO& soundFile); double soundReadSample16L_L (FileIO& soundFile); double soundReadSample24L_L (FileIO& soundFile); double soundReadSample32L_L (FileIO& soundFile); double soundReadSample32F_L (FileIO& soundFile); double soundReadSample64F_L (FileIO& soundFile); ////////////////////////////// // // SoundFileRead::determineSampleReadingFunction -- // void SoundFileRead::determineReadingFunction(void) { switch (getInputType()) { case TYPE_SND: // big endian samples endianType = SIG_BIG_ENDIAN; switch (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: " << getNextFormat() << endl; exit(1); } break; case TYPE_WAV_PCM: // little endian samples endianType = SIG_LITTLE_ENDIAN; switch (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: " << getNextFormat() << endl; exit(1); } break; default: ; // the soundfile name is probably a dummy, and will not be used // cerr << "Error: unknown soundfile type: " // << getInputType() << endl; // exit(1); } } ////////////////////////////// // // SoundFileRead::fillCurrentArray -- read the next set of samples // from the soundfile and store in the current array. // void SoundFileRead::fillCurrentArray(void) { for (int i=0; i