// // Programmer: Craig Stuart Sapp // Creation Date: Sun Nov 23 18:46:35 GMT-0800 1997 // Last Modified: Mon Apr 13 11:06:15 PDT 1998 // Filename: ...sig/maint/code/base/EnvelopeString/EnvelopeString.cpp // Web Address: http://sig.sapp.org/src/sig/EnvelopeString.cpp // Documentation: http://sig.sapp.org/doc/classes/EnvelopeString // Syntax: C++ // #include "EnvelopeString.h" #include #include #include #include #ifndef OLDCPP #include #include #include #define SSTREAM stringstream #define CSTRING str().c_str() using namespace std; #else #include #include #ifdef VISUAL #include #else #include #endif #define SSTREAM strstream #define CSTRING str() #endif #define MAX_ENVELOPE_POINT_DIMENSION (100) ////////////////////////////// // // EnvelopeString::EnvelopeString -- // EnvelopeString::EnvelopeString(void) { envelope = NULL; normalization = 1.0; dimension = 0; points = NULL; absoluteType = 'm'; pointInterp.allowGrowth(); pointInterp.setSize(0); pointParameter.allowGrowth(); pointInterp.setSize(0); } EnvelopeString::EnvelopeString(const char* aString) { envelope = NULL; normalization = 1.0; dimension = 0; points = NULL; absoluteType = 'm'; pointInterp.allowGrowth(); pointInterp.setSize(0); pointParameter.allowGrowth(); pointInterp.setSize(0); setEnvelope(aString); } ////////////////////////////// // // EnvelopeString::~EnvelopeString -- // EnvelopeString::~EnvelopeString() { if (envelope != NULL) { delete [] envelope; } if (points != NULL) { delete [] points; } } ////////////////////////////// // // EnvelopeString::getDimension -- // int EnvelopeString::getDimension(void) const { return dimension; } ////////////////////////////// // // EnvelopeString::getEnvelope -- // const char* EnvelopeString::getEnvelope(void) { if (!modified) { return envelope; } else { makeEnvelope(); return envelope; } } ////////////////////////////// // // EnvelopeString::getLength -- // double EnvelopeString::getLength(void) const { return normalization; } ////////////////////////////// // // EnvelopeString::getNumPoints -- // int EnvelopeString::getNumPoints(void) const { if (points != NULL) { return points[0].getSize(); } else { return 0; } } ////////////////////////////// // // EnvelopeString::getStickIndex -- return -1 if no stick point // int EnvelopeString::getStickIndex(void) const { return stickIndex; } ////////////////////////////// // // EnvelopeString::getValue -- // double EnvelopeString::getValue(int a, int b) { return points[b][a]; } ////////////////////////////// // // EnvelopeString::print -- // void EnvelopeString::print(void) { int i, j; cout << " Envelope Time Length = " << getLength() << endl; cout << " Default interpolation = " << defaultInterpolation << endl; cout << " Absolute Type = " << absoluteType << endl; cout << " Stick index = " << stickIndex << endl; cout << " Number of points = " << points[0].getSize() << endl; for (i=0; i getNumPoints() - 1) { cerr << "Error: invalid index for stick point: " << anIndex << endl; exit(1); } if (anIndex == stickIndex) return; for (int i=0; i= anIndex) { points[0][i] = points[0][i] - 1.0; } } stickIndex = anIndex; modified = 1; } ////////////////////////////// // // setStickSamples // void EnvelopeString::setStickSamples(void) { absoluteType = 'm'; modified = 1; } ////////////////////////////// // // setStickSeconds // void EnvelopeString::setStickSeconds(void) { absoluteType = 't'; modified = 1; } ////////////////////////////// // // EnvelopeString::setSyntax -- // void EnvelopeString::setSyntax(int syntaxType) { switch (syntaxType) { case CLM_ENV: case LISP_ENV: case MUSICKIT_ENV: case MATHEMATICA_ENV: case PLAIN_ENV: case SIG_ENV: outputType = syntaxType; break; default: cerr << "Error: unknown type of syntax." << endl; } modified = 1; } ////////////////////////////// // // EnvelopeString::setSyntaxCLM -- // void EnvelopeString::setSyntaxCLM(void) { setSyntax(CLM_ENV); } ////////////////////////////// // // EnvelopeString::setSyntaxLISP -- // void EnvelopeString::setSyntaxLISP(void) { setSyntax(LISP_ENV); } ////////////////////////////// // // EnvelopeString::setSyntaxMK -- // void EnvelopeString::setSyntaxMK(void) { setSyntax(MUSICKIT_ENV); } ////////////////////////////// // // EnvelopeString::setSyntaxMMA -- // void EnvelopeString::setSyntaxMMA(void) { setSyntax(MMA_ENV); } ////////////////////////////// // // EnvelopeString::setSyntaxPLAIN -- // void EnvelopeString::setSyntaxPLAIN(void) { setSyntax(PLAIN_ENV); } ////////////////////////////// // // EnvelopeString::setSyntaxSIG -- // void EnvelopeString::setSyntaxSIG(void) { setSyntax(SIG_ENV); } ////////////////////////////// // // operator<< // ostream& operator<<(ostream& out, EnvelopeString& aString) { out << aString.getEnvelope(); return out; } /////////////////////////////////////////////////////////////////////////// // // Private functions // ////////////////////////////// // // EnvelopeString::determineType -- // int EnvelopeString::determineType(const char* aString) { int length = strlen(aString); int index; // if the first non-space character is a '[' then a MusicKit envelope for (index=0; index tempData; tempData.allowGrowth(); tempData.setSize(0); index = 0; skipSpace(aString, index); if (aString[index] != '(') { cerr << "Error at beginning of string: " << aString << endl; exit(1); } index++; i = 0; while (aString[index] != ')' && index < length) { tempData[i++] = extractNumber(aString, index); skipSpace(aString, index); } if (aString[index] != ')') { cerr << "Error at end of envelope at character " << index + 1 << " in: " << aString << endl; exit(1); } if (aDimension == -1) { dimension = 2; } else { dimension = aDimension; } if (getDimension() < 2) { cerr << "Error: not enough dimension to envelope points: " << aString << endl; exit(1); } if (tempData.getSize() % getDimension() != 0) { cerr << "Error: CLM envelope must have right amount of data for " << "dimension : " << aString << endl; exit(1); } int pointCount = tempData.getSize() / getDimension(); setLength(tempData[tempData.getSize()-getDimension()]); if (points != NULL) { delete [] points; } points = new Array[getDimension()]; for (i=0; i= 0) { index--; } setLength(extractNumber(aString, index)); // no interpolation indicators allowed. // no interpolation parameters allowed. index = 0; skipSpace(aString, index); // must be at start of envelope if (aString[index] != '(') { cerr << "Error at start of envelope: " << aString << endl; exit(1); } index++; skipSpace(aString, index); if (aString[index] != '(') { cerr << "Error at beginning of fist data point in envelope: " << aString << endl; exit(1); } index++; // determine the dimension of an envelope point by checking // the number of elements in the first envelope point: dimension = 1; double testNumbers[MAX_ENVELOPE_POINT_DIMENSION]; testNumbers[getDimension()-1] = extractNumber(aString, index); if (testNumbers[getDimension()-1] != 0.0) { cerr << "Error: first element in an envelope must be zero: " << testNumbers[getDimension()-1] << " in " << aString << endl; exit(1); } skipSpace(aString, index); while (aString[index] != ')' && aString[index] != '\0') { dimension++; if (getDimension() >= MAX_ENVELOPE_POINT_DIMENSION) { cerr << "Error: too many elements in first point of envelope: " << aString << endl; exit(1); } testNumbers[getDimension()-1] = extractNumber(aString, index); skipSpace(aString, index, "\n \t,"); } if (getDimension() <= 1) { cerr << "Error: not enough data for first envelope point: " << aString << endl; exit(1); } // process the rest of the envelope points if (points != NULL) { delete [] points; } points = new Array[getDimension()]; for (i=0; i= 0) { index--; } setLength(extractNumber(aString, index)); // no interpolation indicators allowed. // no interpolation parameters allowed. index = 0; skipSpace(aString, index); // must be at start of envelope if (aString[index] != '[') { cerr << "Error at start of envelope: " << aString << endl; exit(1); } index++; skipSpace(aString, index); if (aString[index] != '(') { cerr << "Error at beginning of fist data point in envelope: " << aString << endl; exit(1); } index++; // determine the dimension of an envelope point by checking // the number of elements in the first envelope point: dimension = 1; double testNumbers[MAX_ENVELOPE_POINT_DIMENSION]; testNumbers[getDimension()-1] = extractNumber(aString, index); if (testNumbers[getDimension()-1] != 0.0) { cerr << "Error: first element in an envelope must be zero: " << testNumbers[getDimension()-1] << " in " << aString << endl; exit(1); } skipSpace(aString, index); while (aString[index] != ')' && aString[index] != '\0') { dimension++; if (getDimension() >= MAX_ENVELOPE_POINT_DIMENSION) { cerr << "Error: too many elements in first point of envelope: " << aString << endl; exit(1); } testNumbers[getDimension()-1] = extractNumber(aString, index); skipSpace(aString, index, "\n \t,"); } if (getDimension() <= 1) { cerr << "Error: not enough data for first envelope point: " << aString << endl; exit(1); } // process the rest of the envelope points if (points != NULL) { delete [] points; } points = new Array[getDimension()]; for (i=0; i= 0) { index--; } setLength(extractNumber(aString, index)); // no interpolation indicators allowed. // no interpolation parameters allowed. index = 0; skipSpace(aString, index); // must be at start of envelope if (aString[index] != '{') { cerr << "Error at start of envelope: " << aString << endl; exit(1); } index++; skipSpace(aString, index); if (aString[index] != '{') { cerr << "Error at beginning of fist data point in envelope: " << aString << endl; exit(1); } index++; // determine the dimension of an envelope point by checking // the number of elements in the first envelope point: dimension = 1; double testNumbers[MAX_ENVELOPE_POINT_DIMENSION]; testNumbers[getDimension()-1] = extractNumber(aString, index); if (testNumbers[getDimension()-1] != 0.0) { cerr << "Error: first element in an envelope must be zero: " << testNumbers[getDimension()-1] << " in " << aString << endl; exit(1); } skipSpace(aString, index); while (aString[index] != '}' && aString[index] != '\0') { dimension++; if (getDimension() >= MAX_ENVELOPE_POINT_DIMENSION) { cerr << "Error: too many elements in first point of envelope: " << aString << endl; exit(1); } testNumbers[getDimension()-1] = extractNumber(aString, index); skipSpace(aString, index, "\n \t,"); } if (getDimension() <= 1) { cerr << "Error: not enough data for first envelope point: " << aString << endl; exit(1); } // process the rest of the envelope points if (points != NULL) { delete [] points; } points = new Array[getDimension()]; for (i=0; i tempData; tempData.allowGrowth(); tempData.setSize(0); index = 0; skipSpace(aString, index); if (std::isalpha(aString[index])) { cerr << "Error at beginning of string: " << aString << endl; exit(1); } i = 0; while (aString[index] != '\0' && index < length) { tempData[i++] = extractNumber(aString, index); skipSpace(aString, index); } if (aDimension == -1) { dimension = 2; } else { dimension = aDimension; } if (getDimension() < 2) { cerr << "Error: not enough dimension to envelope points: " << aString << endl; exit(1); } if (tempData.getSize() % getDimension() != 0) { cerr << "Error: PLAIN envelope must have enough points for dimension: " << aString << endl; exit(1); } int pointCount = tempData.getSize() / getDimension(); setLength(tempData[tempData.getSize()-getDimension()]); if (points != NULL) { delete [] points; } points = new Array[getDimension()]; for (i=0; i 1) { cerr << "Error: too many letter \"s\"es found in envleope: " << aString << endl; exit(1); } } } if (pointCount <= 1) { cerr << "Error: not enough points in envelope: " << aString << endl; exit(1); } // find first coordinate of the last point in envelope to use // in normalizing the time element of the envelope: index = length-1; while (aString[index] != ';' && index >= 0) { index--; } setLength(extractNumber(aString, index)); // check for a default interpolation type defaultInterpolation = 'L'; defaultParameter = -9999; index = 0; skipSpace(aString, index); if (std::isalpha(aString[index])) { validateInterpolation(aString[index]); defaultInterpolation = std::toupper(aString[index]); index++; skipSpace(aString, index); if (std::isdigit(aString[index])) { defaultParameter = extractNumber(aString, index); skipSpace(aString, index); } } // must be at start of envelope if (aString[index] != '(') { cerr << "Error at start of envelope: " << aString << endl; exit(1); } // determine the dimension of an envelope point by checking // the number of elements in the first envelope point: dimension = 1; double testNumbers[MAX_ENVELOPE_POINT_DIMENSION]; testNumbers[getDimension()-1] = extractNumber(aString, index); if (testNumbers[getDimension()-1] != 0.0) { cerr << "Error: first element in an envelope must be zero: " << testNumbers[getDimension()-1] << " in " << aString << endl; exit(1); } while (aString[index] != ';' && !std::isalpha(aString[index]) && aString[index] != ')' && aString[index] != '\0' ) { dimension++; if (getDimension() >= MAX_ENVELOPE_POINT_DIMENSION) { cerr << "Error: too many elements in first point of envelope: " << aString << endl; exit(1); } testNumbers[getDimension()-1] = extractNumber(aString, index); skipSpace(aString, index, "\n \t,"); } if (getDimension() <= 1) { cerr << "Error: not enough data for first envelope point: " << getDimension() << " " << aString << endl; exit(1); } // process the rest of the envleope points if (points != NULL) { delete [] points; } points = new Array[getDimension()]; for (i=0; i= 0) { setStickIndex(tempStickIndex-1); } if (aString[index] == '\0') { return; } else { skipSpace(aString, index); } if (aString[index] == '\0') { return; } else if (std::tolower(aString[index]) == 't') { absoluteType = 't'; } else if (std::tolower(aString[index]) == 'm') { absoluteType = 'm'; } else { cerr << "Error: unknown characters after end of envelope: " << aString << endl; exit(1); } } ////////////////////////////// // // EnvelopeString::adjustForStick -- // void EnvelopeString::adjustForStick(void) { if (stickIndex <= 0) { return; } int i = 0; int j; if (pointInterp[i] == pointInterp[pointInterp.getSize()-1]) { i = pointInterp.getSize()-1; while (i>0 && pointInterp[i] <= 0) { pointInterp[i+1] = pointInterp[i]; pointParameter[i+1] = pointInterp[i]; for (j=0; j