Goto: [ Program Documentation ]

//
// Programmer:    Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Sun Apr 20 19:43:40 GMT-0800 1997
// Last Modified: Mon Apr 20 11:27:58 PDT 1998
// Last Modified: Mon Jul  9 16:56:13 PDT 2001 (fixed bugs and add rev calc)
// Filename:      ...sig/doc/examples/sig/sigfile/comb/comb.cpp
// Syntax:        C++; sig
//
// Description:   a comb filter.  If no input, then use whitenoise.
//		  Can handle mono or stereo files.
//

#include "sigAudio.h"

#include <stdlib.h>

#ifndef OLDCPP
   #include <iostream>
#else
   #include <iostream.h>
#endif
   

void checkOptions(Options& opts);
void example(void);
void usage(const char* command);

///////////////////////////////////////////////////////////////////////////


int main(int argc, char* argv[]) {
   Options options(argc, argv);
   checkOptions(options);

   SoundHeader header;
   char* infilename = "";
   char* outfilename = NULL;
   int numSamples;
 
   if (options.getArgCount() == 1) {   // use whitenoise
      outfilename = options.getArg(1);
      header.setHighMono();
      if (options.getInt("samples") > 0) {
         numSamples = options.getInt("samples");
      } else {
         numSamples = (int)(options.getDouble("duration") * 44100 + 0.5);
      }
   } else {                            // use input soundfile
      infilename = options.getArg(1);
      header.setHeader(infilename);
      numSamples = header.getSamples();
      outfilename = options.getArg(2);
   }


   // Elements:
   SoundFileIn  insound(infilename);
   SoundFileOut outsound(outfilename, header);
   Comb         combLeft;
   Comb         combRight;
   Envelope     gainEnv(options.getString("gain-env"));
   WhiteNoise   noise(1);
   Envelope     ampEnv(options.getString("amp-env"));
   Multiply     mul;

   combLeft.setMinFund(options.getDouble("fundamental"));
   combRight.setMinFund(options.getDouble("fundamental"));
   combLeft.setFund(options.getDouble("fundamental"));
   combRight.setFund(options.getDouble("fundamental"));

   // Connections:
   outsound.connect(combLeft);
   if (header.getChannels() == 2) {
      outsound.connect(combRight, 1, 0);
   }

   mul.connect(noise);
   mul.connect(ampEnv);
   if (strlen(infilename) == 0) {         // use noise
      combLeft.connect(mul, 0);      
      combRight.connect(mul, 0);      
   } else {                               // use input file
      combLeft.connect(insound, 0, 0);
      combRight.connect(insound, 1, 0);
   }
   combLeft.connect(gainEnv, 1);
   combRight.connect(gainEnv, 1);

   Action action;
   if (options.getBoolean("zeros")) {
      action.tick(combLeft, combLeft.getDelaySamples());
      action.tick(combRight, combLeft.getDelaySamples());
   }
cout << "TICKING FOR " << numSamples << endl;
   action.tick(outsound, numSamples);
   
   // disconnect signal and add ending reverb
   double addsamples;
   if (options.getDouble("reverb") == 0.0) {
      addsamples = 0;
   } else {
      addsamples = options.getDouble("reverb")/-20.0 * 
            combLeft.getDelaySamples() / log10(fabs(combLeft.getGain()));
   }
   // cout << "adding " << addsamples << " to the end of the file" << endl;
   
   combLeft.disconnect(0);
   combRight.disconnect(0);
   action.tick(outsound, (int)addsamples);
 
   return 0;
}


///////////////////////////////////////////////////////////////////////////


//////////////////////////////
//
// checkOptions -- handle command-line options.
//

void checkOptions(Options& opts) {
   opts.define("a|amp|amp-env=s:0 .1 1 .1", "Amplitude env of noise");
   opts.define("f|fundamental=d:100.0", "Resonance pitch of comb filter");
   opts.define("g|gain|gain-env=s:0 0.9 1 0.9", "Comb filter feedback gain");
   opts.define("d|dur|duration=d:1.0 second", "Time in sec. for noise");
   opts.define("r|reverb|T=d:60.0", "Reverb time to add to end of file");
   opts.define("s|samples=i", "Number of white noise sample if no soundfile");
   opts.define("z|zeros|remove-zeros=b", "Remove initial delay from soundfile");
   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, March 1998" << endl;
      exit(0);
   }
   if (opts.getBoolean("version")) {
      cout << "Version 9 July 2001" << endl;
      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 input and one output filename
   if (opts.getArgCount() == 0) {
      cout << "Error: need one output file name." << endl;
      usage(opts.getCommand());
      exit(1);
   } else if (opts.getArgCount() > 2) {
      cout << "Error: too many arguments.  Given "
           << opts.getArgCount() << " but need only 2." << endl;
      usage(opts.getCommand());
      exit(1);
   }

}



//////////////////////////////
//
// example -- gives example calls to the comb program.
//

void example(void) {
}



//////////////////////////////
//
// usage -- how to run the osc program on the command line.
//

void usage(const char* command) {
   cout << endl;
   cout << 
      "A comb filter.  Uses whitenoise if no input sound is specified" << endl;
   cout << endl;
   cout << "Usage: " << command << " [insound] outsound" << endl;
   cout << endl;
}


// md5sum: e3639ab5020e1ee5561a79705ad48c40 comb.cpp [20050403]