//
// Programmer:    Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Sun Jan 19 07:51:14 PST 2003
// Last Modified: Sun Jan 19 07:51:17 PST 2003
// Filename:      ...sig/doc/examples/sig/sigfile/addsnd/addsnd.cpp
// Syntax:        C++; sig
//
// Description:   Adds multiple sound files into one file.  The 
//                channel count of the output file is equal to
//                the maximum channel count of the input files.
//                All input soundfiles must contain the same 
//                sampling rete.  If they do not, then the sample
//                rate of the first soundfile in the input list
//                will be used.
//
//  Usage: addsnd [-a ampscale] insound(s) outsound  
//                                                                           
//  Options:                                                                 
//     -a = scale the amplitude of all input soundfiles by this value.
//     --options = list of all options, aliases and defaults                 
//

#include "sigAudio.h"

#include <stdlib.h>

#ifndef OLDCPP
   #include <iostream>
   using namespace std;
#else
   #include <iostream.h>
#endif

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

double amplitude = 1.0;      // used with -a option

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

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

   int incount = options.getArgCount() - 1;
   SoundHeader* headers;
   headers = new SoundHeader[incount];
   int maxchannel = 0;
   int maxsamples = 0;

   int i, j;
   for (i=0; i<incount; i++) {
      headers[i].setHeader(options.getArg(i+1));
      if (maxchannel < headers[i].getChannels()) {
         maxchannel = headers[i].getChannels();
      }
      if (maxsamples < headers[i].getSamples()) {
         maxsamples = headers[i].getSamples();
      }
   }

   SoundHeader outheader;
   outheader.setChannels(maxchannel);
   outheader.setSrate(headers[0].getSrate());

   // Elements
   SoundFileOut outsound(options.getArg(incount + 1), outheader);
   SoundFileIn  insounds[incount];
   Scale* scales;
   scales = new Scale[maxchannel];
   Add* summation;
   summation = new Add[maxchannel];

   for (i=0; i<maxchannel; i++) {
      scales[i].setScale(amplitude);
   }

   for (i=0; i<incount; i++) {
      insounds[i].setFile(options.getArg(i+1));
      for (j=0; j<headers[i].getChannels(); j++) {
         summation[j].connect(insounds[i], NONE, j);
      }
   }

   for (i=0; i<maxchannel; i++) {
      scales[i].connect(summation[i]);
      outsound.connect(scales[i], i, i);
   }

   Action action;
   action.tick(outsound, maxsamples);

   return 0;
}



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


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

void checkOptions(Options& opts) {
   opts.define("a|amp|amplitude=d:1.0", "amplitude scaling for all channels");

   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, January 2003" << 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);
   }

   // must have at least two sound filenames
   if (opts.getArgCount() < 2) {
      cout << "Error: need at least one input soundfile." << endl;
      usage(opts.getCommand());
      exit(1);
   }

   amplitude = opts.getDouble("amplitude");
}



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

void example(void) {
   cout <<
   "                                                                         \n"
   "# addsnd examples:                                                       \n"
   << endl;
}



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

void usage(const char* command) {
   cout << 
   "                                                                         \n"
   "Usage: " << command << " [-a amp] insound(s) outsound                    \n"
   "                                                                         \n"
   << endl;
}



// md5sum: fc5e56969319ff1a24f64241e8d9c78a addsnd.cpp [20050403]