Goto: [ Program Documentation ]

//
// Programmer:    Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Sun Apr 12 21:54:05 PDT 1998
// Last Modified: Sun Apr 12 21:54:08 PDT 1998
// Last Modified: Mon Jan 25 23:36:51 PST 2010 (added number option)
// Filename:      ...sig/doc/examples/sig/sigfile/quantize/quantize.cpp
// Syntax:        C++; sig
//
// Description:   quantizes a sound to a given number of amplitude levels.
//                either integer or floating point quantization is
//                possible.
//

#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);


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

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

   SoundHeader header(options.getArg(1));
   if (header.getBitsPerSample() != 16) {
      cout << "Error: this program can only process 16-bit samples." << endl;
      exit(1);
   }
   int numSamples = header.getSamples() * header.getChannels();

   // Elements:
   SoundFileIn  insound(options.getArg(1));
   SoundFileOut outsound(options.getArg(2), header);

   int i;
   double currentSample;
   if (options.getBoolean("float")) {
      int scaleBits = options.getInteger("scale");
      int mantissaBits = options.getInteger("mantissa");
      for (i=0; i<numSamples; i++) {
         currentSample = (double) insound.extractSample16Bit() / 0x8000;
         currentSample = DequantizeFloatMidtread(
           QuantizeFloatMidtread(scaleBits, mantissaBits, currentSample));
         outsound.insertSample16Bit((short)(currentSample * 0x7fff + 0.5));
      }
   } else {  // linear quantization
      int bits = options.getInteger("bits");
      for (i=0; i<numSamples; i++) {
         currentSample = (double)insound.extractSample16Bit() / (long)0x8000;
         currentSample = DequantizeMidtread(
           QuantizeMidtread(bits, currentSample));
         outsound.insertSample16Bit((short)(currentSample * 0x7fff + 0.5));
      }
   }

   return 0;
}


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


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

void checkOptions(Options& opts) {
   opts.define("b|bits|bit=i:8",         "uniform quantizer bits");
   opts.define("s|scale|e|exponent=i:3", "fp quant exponent bits");
   opts.define("m|mantissa|mant=i:5",    "fp quant mantissa bits (incl. sign)");
   opts.define("f|float=b",           "use floating-point quantization");
   opts.define("bf|block-float=b", "floating-point quantization, by block");
   opts.define("d|dec=b",        "display q-codes as decmial values");
   opts.define("max=d:1.0",      "floating-point quantization, by block, max specified");
   opts.define("n|number=d:0.0",    "single number to quantize / dequantize");
   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, April 1998" << 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);
   }

   if (opts.getBoolean("number")) {
      int dec = opts.getBoolean("dec");
      // print single quantization and quit
      if (opts.getBoolean("bits")) {

         int    bits   = opts.getInteger("bits");
         double number = opts.getDouble("number");
         LinearCode linearcode = QuantizeMidtread(bits, number);
         cout << number << "\t";
         printCodeQuartet(linearcode, dec);
	 cout << "\t" << DequantizeMidtread(linearcode) << endl;

      } else if (opts.getBoolean("float")) {
         int    Rs   = opts.getInteger("exponent");
         int    Rm   = opts.getInteger("mantissa");
         double number = opts.getDouble("number");
         FloatCode floatcode = QuantizeFloatMidtread2(Rs, Rm, number);
         cout << number << "\t";
         printFloatCodeQuartet(floatcode, dec);
	 cout << "\t" << DequantizeFloatMidtread2(floatcode, 1) << endl;

      } else if (opts.getBoolean("block-float") && !opts.getBoolean("max")) {
         int    Rs   = opts.getInteger("exponent");
         int    Rm   = opts.getInteger("mantissa");
         double number = opts.getDouble("number");
         FloatCode floatcode = QuantizeBlockFloatMidtread2(Rs, Rm, number);
         cout << number << "\t";
         printFloatCodeQuartet(floatcode, dec);
	 cout << "\t" << DequantizeBlockFloatMidtread2(floatcode, 1) << endl;

      } else if (opts.getBoolean("block-float") && opts.getBoolean("max")) {
         int    Rs   = opts.getInteger("exponent");
         int    Rm   = opts.getInteger("mantissa");
         double number = opts.getDouble("number");
	 double maxx = opts.getDouble("max");
         FloatCode floatcode = QuantizeBlockFloatMidtread2Max(Rs, Rm, 
			           number, maxx);
         cout << number << "\t";
         printFloatCodeQuartet(floatcode, dec);
	 cout << "\t" << DequantizeBlockFloatMidtread2(floatcode, 1) << endl;

      } 

      exit(0);
   }

   if (opts.getBoolean("float")) {
      if (opts.getInt("scale") + opts.getInt("mantissa") > 16) {
         cout << "Error: sum of scale and mantissa must be less than 16." 
              << endl;
         exit(1);
      }
   } else if (opts.getInt("bits") > 16) {
      cout << "Error: number of bits must be less than 16." << endl; 
      exit(1);
   }

   // can only have one input and one output filename
   if (opts.getArgCount() != 2) {
      cout << "Error: need one input and one output file name." << endl;
      usage(opts.getCommand());
      exit(1);
   }



}
  


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

void example(void) {
   cout <<
   "# quantize examples:                                                   \n"
   "       quantize -f -s 3 -m 5 input.snd  output.snd                     \n"
   << endl;
}



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

void usage(const char* command) {
   cout << endl;
   cout << "Quantizes a 16-bit sound using fewer bits, and then converts\n";
   cout << "to 16 bits samples. Will work on mono or stereo soundfiles.\n";
   cout << endl;
   cout << "Usage: " << command << " [-b bits| -f -s sale -m mantissa] "
           "insound outsound\n";
   cout << endl;
   cout << "Options: " << endl;
   cout << "   -b = The number of bits to use to midtread quantize (default 8)\n";
   cout << "        cannot be greater than 16.\n";
   cout << "   -f = use floating point midtread quantization\n";
   cout << "   -s = number of bits for the scale of floating point "
           "quantization\n";
   cout << "   -m = number of bits for the mantissa of floating point "
           "quantization\n";
   cout << "   --options = list of all options, aliases and defaults \n";
   cout << endl;
}



// md5sum: 0c02ff6a78e088623603ca5858a61032 quantize.cpp [20050403]