// // Programmer: Craig Stuart Sapp // Creation Date: Sat Sep 7 16:10:45 2002 // Last Modified: Sat Sep 7 22:30:41 2002 // Filename: ...sig/doc/examples/sig/sigfile/addsyn/addsyn.cpp // Syntax: C++; sig // // Description: make a soundfile with the specified moveable // frequency/amplitude sinewaves // #include "sigAudio.h" #include #include #ifndef OLDCPP #include #include using namespace std; #else #include #include #endif class OscInfo { public: int startSample; int stopSample; double phase; double freq; double amp; void setFreqEnv (const char* string) { int len = strlen(string); if (freqEnv != NULL) { delete [] freqEnv; } freqEnv = new char[len+1]; strcpy(freqEnv, string); } void setAmpEnv (const char* string) { int len = strlen(string); if (ampEnv != NULL) { delete [] ampEnv; } ampEnv = new char[len+1]; strcpy(ampEnv, string); } void print(void) { cout << "Start sample: " << startSample << endl; cout << "Stop sample: " << stopSample << endl; cout << "Phase: " << phase << endl; cout << "Frequency: " << freq << endl; cout << "Amplitude: " << amp << endl; cout << "FreqEnv: " << getFreqEnv() << endl; cout << "AmpEnv: " << getAmpEnv() << endl; cout << "======================" << endl; } const char* getFreqEnv(void) { if (freqEnv == NULL) return ""; else return freqEnv; } const char* getAmpEnv(void) { if (ampEnv == NULL) return ""; else return ampEnv; } OscInfo(void) { freqEnv = ampEnv = NULL; clear(); } OscInfo(OscInfo& a) { startSample = a.startSample; stopSample = a.stopSample; phase = a.phase; freq = a.freq; amp = a.amp; setFreqEnv(a.getFreqEnv()); setAmpEnv(a.getAmpEnv()); } OscInfo& operator=(OscInfo& a) { if (&a == this) return *this; startSample = a.startSample; stopSample = a.stopSample; phase = a.phase; freq = a.freq; amp = a.amp; setFreqEnv(a.getFreqEnv()); setAmpEnv(a.getAmpEnv()); return *this; } void clear(void) { startSample = stopSample = 0; freq = amp = -1000.0; phase = 0.0; if (freqEnv != NULL) { delete [] freqEnv; freqEnv = NULL; } if (ampEnv != NULL) { delete [] ampEnv; ampEnv = NULL; } } private: char* freqEnv; char* ampEnv; }; class ActionTime { public: int time; int number; ActionTime(void) { time = number = 0; } }; // function declarations: void checkOptions (Options& opts); void example (void); void usage (const char* command); int timesort (const void* a, const void* b); void buildOscInfo (Array& oscinfo, const char* filename); void setOnTimes (Array& ontimes, Array& oscinfo); void setOffTimes (Array& offtimes, Array& oscinfo); void checkOnConnections(int currtime, Add& add, Array& osc, Array& ontimes, int& onindex); void checkOffConnections(int currtime, Add& add, Array& osc, Array& offtimes, int& offindex); void prepareOscillators(Array& oscinfo, Array& osc, Array& freqEnv, Array& ampEnv); // global variables: Array oscinfo; int srate = 44100; // sampling rate of output soundfile int verboseQ = 0; // used with the -v option /////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { Options options(argc, argv); checkOptions(options); // determine how many samples in the output based on the input data int numSamples = 0; int i; for (i=0; i= numSamples) { numSamples = oscinfo[i].stopSample + 1; } } Array ontimes; Array offtimes; int onindex = 0; int offindex = 0; setOnTimes(ontimes, oscinfo); setOffTimes(offtimes, oscinfo); // prepare for a monophonic output file SoundHeader header; header.setHighMono(); Array freqEnv(oscinfo.getSize()); Array ampEnv(oscinfo.getSize()); Array osc(oscinfo.getSize()); prepareOscillators(oscinfo, osc, freqEnv, ampEnv); Add add; SoundFileOut outsound(options.getArg(2), header); // connections outsound.connect(add); for (i=0; i& oscinfo, Array& osc, Array& freqEnv, Array& ampEnv) { int i; for (i=0; i& osc, Array& ontimes, int& onindex) { int i; for (i=onindex; i& osc, Array& offtimes, int& offindex) { int i; for (i=offindex; i& ontimes, Array& oscinfo) { ontimes.setSize(oscinfo.getSize()); int i; for (i=0; i& offtimes, Array& oscinfo) { offtimes.setSize(oscinfo.getSize()); int i; for (i=0; i B.time) { return +1; } else { return 0; } } ////////////////////////////// // // checkOptions -- handle command-line options. // void checkOptions(Options& opts) { opts.define("v|verbose=b", "display input osc data"); opts.define("author=b"); opts.define("version=b"); opts.define("example=b"); opts.define("help=b"); opts.process(); if (opts.getBoolean("author")) { cout << "Written by Craig Stuart Sapp, " << "craig@ccrma.stanford.edu, September 2002" << endl; exit(0); } if (opts.getBoolean("version")) { cout << "compiled: " << __DATE__ << endl; cout << SIG_VERSION << endl; exit(0); } if (opts.getBoolean("help")) { usage(opts.getCommand()); exit(0); } if (opts.getBoolean("example")) { example(); exit(0); } // can only have one output filename if (opts.getArgCount() != 2) { cout << "Error: need two arguments." << endl; usage(opts.getCommand()); exit(1); } verboseQ = opts.getBoolean("verbose"); oscinfo.setSize(0); buildOscInfo(oscinfo, opts.getArg(1)); } ////////////////////////////// // // buildOscInfo -- // void buildOscInfo(Array& oscinfo, const char* filename) { #ifndef OLDCPP fstream infile(filename, ios::in); #else fstream infile(filename, ios::in | ios::nocreate); #endif if (!infile.is_open()) { cout << "Error: cannot open file: " << filename << endl; exit(1); } oscinfo.setSize(10000); oscinfo.setGrowth(10000); oscinfo.setSize(0); OscInfo tempinfo; char buffer[100001] = {0}; infile.getline(buffer, 100000, '\n'); double starttime = 0.0; double duration = 0.0; double phase = 0.0; double frequency = -1000; double amplitude = -1000; char* ptr = NULL; int line = 1; while (!infile.eof()) { tempinfo.clear(); frequency = -1000.0; amplitude = -1000.0; phase = 0; if (buffer[0] == ';' || buffer[0] == '/' || buffer[0] == '#') { infile.getline(buffer, 100000, '\n'); line++; continue; } if (strncmp(buffer, "osc", 3) == 0 || strncmp(buffer, "OSC", 3) == 0 || strncmp(buffer, "Osc", 3) == 0 ) { ptr = strtok(buffer, " \t\n:,;"); // OSC identifier ptr = strtok(NULL, " \t\n:,;"); // start time (required) if (ptr == NULL) { cout << "Error on line " << line << ": expecting start time." << endl; exit(1); } starttime = strtod(ptr, NULL); ptr = strtok(NULL, " \t\n:,;"); // duration (required) if (ptr == NULL) { cout << "Error on line " << line << ": expecting duration." << endl; exit(1); } duration = strtod(ptr, NULL); if (duration < 0.0) { duration = 0.0; } ptr = strtok(NULL, " \t\n:,;"); // frequency (optional) if (ptr != NULL) { frequency = strtod(ptr, NULL); } ptr = strtok(NULL, " \t\n:,;"); // amplitude (optional) if (ptr != NULL) { amplitude = strtod(ptr, NULL); } ptr = strtok(NULL, " \t\n:,;"); // phase (optional) if (ptr != NULL) { phase = strtod(ptr, NULL); } infile.getline(buffer, 100000, '\n'); line++; // cout << "Start = " << starttime << endl; // cout << "Duration = " << duration << endl; if (duration == 0.0) { continue; } tempinfo.startSample = (int)(starttime * srate + 0.5); tempinfo.stopSample = (int)((starttime + duration) * srate + 0.5); if (frequency != -1000.0) { tempinfo.freq = frequency; } if (amplitude != -1000.0) { tempinfo.amp = amplitude; } tempinfo.phase = phase; while (isspace(buffer[0])) { int n = 0; while ((buffer[n] != '\0') && isspace(buffer[n])) { n++; } if (strncmp(&buffer[n], "freq", 4) == 0) { n = n+4; while ((buffer[n] != '\0') && isspace(buffer[n])) { n++; } tempinfo.setFreqEnv(&buffer[n]); // cout << "Found freq env: " << &buffer[n]<< endl; } else if (strncmp(&buffer[n], "amp", 3) == 0) { n = n+3; while ((buffer[n] != '\0') && isspace(buffer[n])) { n++; } tempinfo.setAmpEnv(&buffer[n]); // cout << "Found amp env: " << &buffer[n] << endl; } else if (strncmp(&buffer[n], "phase", 5) == 0) { n = n+5; while ((buffer[n] != '\0') && isspace(buffer[n])) { n++; } // cout << "Found phase: " << &buffer[n] << endl; tempinfo.phase = strtod(&buffer[n], NULL); } infile.getline(buffer, 100000, '\n'); line++; } if (verboseQ) { tempinfo.print(); } oscinfo.append(tempinfo); continue; } infile.getline(buffer, 100000, '\n'); line++; // cout << buffer << endl; } } ////////////////////////////// // // example -- gives example calls to the addsyn program. // void example(void) { cout << " addsyn script output.wav \n" " where the file script contains: \n" " \n" "osc 0.0 1.0 440 0.5 0 \n" "osc 0.3 0.5 880 0.1 \n" " \n" "osc 1.0 1.0 \n" " freq 0 0 1 1000 2 500 \n" " amp 0 0 5 0.5 95 0.5 100 0 \n" " phase 90 \n" "; script comment \n" " \n" << endl; } ////////////////////////////// // // usage -- how to run the osc program on the command line. // void usage(const char* command) { cout << " \n" "Creates a frequency and amplitude varying sinusoids from a script file. \n" " \n" "Usage: " << command << " script outsound \n" " \n" "Options: \n" " -v = display a list of the parsed oscillator inputs. \n" " --options = list of all options, aliases and default values. \n" " \n" " \n" << endl; } // md5sum: abd9ba92e401a40ae6fd7474da7d40f8 addsyn.cpp [20050403]