// file: $isip/class/algo/Cepstrum/cep_05.cc
// version: $Id: cep_05.cc 8417 2002-07-17 21:59:48Z parihar $
//

// isip include files
//
#include "Cepstrum.h"
#include <FourierTransform.h>

// method: apply
//
// arguments:
//  Vector<AlgorithmData>& output: (output) output data
//  const Vector< CircularBuffer<AlgorithmData> >& input: (input) input data
//
// return: a boolean value indicating status
//
// this method computes the cepstral coefficients for the given
// input. this method selects the appropriate input and output data
// types and calls compute method accordingly.
//
boolean Cepstrum::apply(Vector<AlgorithmData>& output_a,
			const Vector< CircularBuffer<AlgorithmData> >&
			input_a) {

  // check for an unsupported mode
  //
  if (cmode_d == ACCUMULATE) {
    Error::handle(name(), L"apply", ERR_UNSUPM, __FILE__, __LINE__);
  }

  // set the length to the number of input channels
  //
  long len = input_a.length();
  output_a.setLength(len);

  // accumulate a result status -- if compute method returns false
  // this apply method should return false
  //    
  boolean res = true;
  
  // start the debugging output
  //
  displayStart(this);

  // loop over the channels and call the compute method
  //
  for (long c = 0; c < len; c++) {

    // display the channel number
    //
    displayChannel(c);

    // branch on compute method type based on the input type and
    // algorithm type
    //
    if ((input_a(c)(0).getDataType() == AlgorithmData::VECTOR_FLOAT) &&
	(algorithm_d == IDCT)) {
      
      // call AlgorithmData::makeVectorFloat to force the output vector for
      // this channel to be a VectorFloat, call AlgorithmData::getVectorFloat
      // on the input for this channel to check that the input is
      // already a VectorFloat and return that vector.
      //
      res &= compute(output_a(c).makeVectorFloat(),
		     input_a(c)(0).getVectorFloat(),
		     input_a(c)(0).getCoefType());
    }
    
    else if ((input_a(c)(0).getDataType()
	      == AlgorithmData::VECTOR_COMPLEX_FLOAT)
	     && (algorithm_d == IDCT)) {
      
      // call AlgorithmData::makeVectorFloat to force the output
      // vector for this channel to be a VectorFloat, call
      // AlgorithmData::getVectorComplexFloat on the input for this
      // channel to check that the input is already a
      // VectorComplexFloat and return that vector.
      //
      res &= compute(output_a(c).makeVectorFloat(),
		     input_a(c)(0).getVectorComplexFloat(),
		     input_a(c)(0).getCoefType());
    }
    
    else if ((input_a(c)(0).getDataType() == AlgorithmData::VECTOR_FLOAT)
	     && (algorithm_d == IDFT)) {
      
      // call AlgorithmData::makeVectorComplexFloat to force the
      // output vector for this channel to be a VectorComplexFloat,
      // call AlgorithmData::getVectorFloat on the input for this
      // channel to check that the input is already a VectorFloat and
      // return that vector.
      //
      res &= compute(output_a(c).makeVectorComplexFloat(),
		     input_a(c)(0).getVectorFloat(),
		     input_a(c)(0).getCoefType());
    }

    else if ((input_a(c)(0).getDataType()
	      == AlgorithmData::VECTOR_COMPLEX_FLOAT)
	     && (algorithm_d == IDFT)) {
      
      // call AlgorithmData::makeVectorComplexFloat to force the
      // output vector for this channel to be a VectorComplexFloat,
      // call AlgorithmData::getVectorComplexFloat on the input for
      // this channel to check that the input is already a
      // VectorComplexFloat and return that vector.
      //
      res &= compute(output_a(c).makeVectorComplexFloat(),
		     input_a(c)(0).getVectorComplexFloat(),
		     input_a(c)(0).getCoefType());
    }
    
    // error condition
    //
    else {
      return Error::handle(name(), L"apply", ERR_ORDER, __FILE__, __LINE__);
    }
    
    // set the coefficient type for the output
    //
    output_a(c).setCoefType(AlgorithmData::SIGNAL);
  }

  // finish the debugging output
  //
  displayFinish(this);

  // exit gracefully
  //
  return res;
}

// method: compute
//
// arguments:
//  VectorFloat& output: (output) cepstral coefficients
//  const VectorFloat& input: (input) input vector
//  AlgorithmData::COEF_TYPE input_coef_type: (input) type of input
//  long channel_index: (input) channel index
//
// return: a boolean value indicating status
//
// this method computes the cepstral coefficients for a given input vector
//
boolean Cepstrum::compute(VectorFloat& output_a,
			  const VectorFloat& input_a,
			  AlgorithmData::COEF_TYPE input_coef_type_a,
			  long channel_index_a) {

  // declare local variables
  //
  boolean status = false;
  VectorFloat input(input_a);

  // check the input arguments
  //
  if (order_d < (long)0) {
    Error::handle(name(), L"compute", ERR_ORDER, __FILE__, __LINE__);
  }

  // compute the log spectrum from spectrum
  //
  VectorFloat logspectrum;

  // make sure that input amplitude doesn't fall below the minimum
  // amplitude if it is defined
  //
  if (flag_min_amp_d) {
    input.limitMin((float)min_amp_d);
  }
  
  // take log of the input vector
  //
  logspectrum.log(input);

  // branch on algorithm
  //  Algorithm: IDCT
  //
  if (algorithm_d == IDCT) {

    // branch on implementation
    //  Implementation: TYPE_I
    //
    if (implementation_d == TYPE_I) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	status = computeIdctT1Float(output_a, logspectrum);
      }
      
      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }

    //  Implementation: TYPE_II
    //
    else if (implementation_d == TYPE_II) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	status = computeIdctT2Float(output_a, logspectrum);
      }
      
      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }


    //  Implementation: TYPE_III
    //
    else if (implementation_d == TYPE_III) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	status = computeIdctT3Float(output_a, logspectrum);
      }
      
      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }

    //  Implementation: TYPE_IV
    //
    else if (implementation_d == TYPE_IV) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	status = computeIdctT4Float(output_a, logspectrum);
      }
      
      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }

    // else: error unknown implementation type
    //
    else {
      return Error::handle(name(), L"compute",
			   ERR_UNKIMP, __FILE__, __LINE__);
    }
  }
  
  // Algorithm: IDFT
  //
  else {

    // branch on implementation:
    //  Implementation: CONVENTIONAL
    //    
    if (implementation_d == CONVENTIONAL) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	return Error::handle(name(), L"compute",
			     ERR, __FILE__, __LINE__);
      }

      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }

    // else: error unknown implementation type
    //
    else {
      return Error::handle(name(), L"compute",
			   ERR_UNKIMP, __FILE__, __LINE__);
    }    
  }
  
  // possibly display the data
  //
  display(output_a, input_a, name());
  
  // exit gracefully
  //
  return status;
}

// method: compute
//
// arguments:
//  VectorFloat& output: (output) cepstral coefficients
//  const VectorComplexFloat& input: (input) input vector
//  AlgorithmData::COEF_TYPE input_coef_type: (input) type of input
//  long channel_index: (input) channel index
//
// return: a boolean value indicating status
//
// this method computes the cepstral coefficients for a given input vector
//
boolean Cepstrum::compute(VectorFloat& output_a,
			  const VectorComplexFloat& input_a,
			  AlgorithmData::COEF_TYPE input_coef_type_a,
			  long channel_index_a) {

  // declare local variables
  //
  boolean status = false;

  // check the input arguments
  //
  if (order_d < (long)0) {
    Error::handle(name(), L"compute", ERR, __FILE__, __LINE__);
  }
  
  // extract magnitude from the complex spectrum
  //
  VectorFloat magspectrum;
  input_a.mag(magspectrum);
  
  // compute the log spectrum from spectrum
  //
  VectorFloat logspectrum;
  
  // make sure that input amplitude doesn't fall below the minimum
  // amplitude, if it is defined
  //
  if (flag_min_amp_d) {
    magspectrum.limitMin((float)min_amp_d);
  }
  
  // take log of the input vector
  //
  logspectrum.log(magspectrum);  

  // branch on algorithm
  //  Algorithm: IDCT
  //
  if (algorithm_d == IDCT) {
    
    // branch on implementation
    //  Implementation: TYPE_I
    //
    if (implementation_d == TYPE_I) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	status = computeIdctT1Float(output_a, logspectrum);
      }

      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }

    //  Implementation: TYPE_II
    //
    else if (implementation_d == TYPE_II) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	status = computeIdctT2Float(output_a, logspectrum);
      }
      
      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }


    //  Implementation: TYPE_III
    //
    else if (implementation_d == TYPE_III) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	status = computeIdctT3Float(output_a, logspectrum);
      }
      
      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }

    //  Implementation: TYPE_IV
    //
    else if (implementation_d == TYPE_IV) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	status = computeIdctT4Float(output_a, logspectrum);
      }
      
      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }

    // else: error unknown implementation type
    //
    else {
      return Error::handle(name(), L"compute",
			   ERR_UNKIMP, __FILE__, __LINE__);
    }
  }
    
  // Algorithm: IDFT
  //
  else {
    
    // declare a local variable
    //
    VectorComplexFloat complex_output;
    
    // branch on implementation:
    //  Implementation: CONVENTIONAL
    //    
    if (implementation_d == CONVENTIONAL) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	status = computeIdftConvRealFloat(complex_output, logspectrum);
      }
      
      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }
    
    // else: error unknown implementation type
    //
    else {
      return Error::handle(name(), L"compute",
			   ERR_UNKIMP, __FILE__, __LINE__);
    }
    
    // convert back to the output to the real type
    //
    complex_output.real(output_a);
  }
  
  // possibly display the data
  //
  display(output_a, input_a, name());
  
  // exit gracefully
  //
  return status;
}

// method: compute
//
// arguments:
//  VectorComplexFloat& output: (output) cepstral coefficients
//  const VectorFloat& input: (input) input vector
//  AlgorithmData::COEF_TYPE input_coef_type: (input) type of input
//  long channel_index: (input) channel index
//
// return: a boolean value indicating status
//
// this method computes the cepstral coefficients for a given input vector
//
boolean Cepstrum::compute(VectorComplexFloat& output_a,
			  const VectorFloat& input_a,
			  AlgorithmData::COEF_TYPE input_coef_type_a,
			  long channel_index_a) {

  // declare local variables
  //
  boolean status = false;
  VectorFloat input(input_a);
    
  // check the input arguments
  //
  if (order_d < (long)0) {
    Error::handle(name(), L"compute", ERR, __FILE__, __LINE__);
  }

  // compute the log spectrum from spectrum
  //
  VectorFloat logspectrum;

  // make sure that input amplitude doesn't fall below the minimum
  // amplitude if it is defined
  //
  if (flag_min_amp_d) {
    input.limitMin((float)min_amp_d);
  }
  
  // take log of the input vector
  //
  logspectrum.log(input);
  
  // branch on algorithm
  //  Algorithm: IDCT
  //
  if (algorithm_d == IDCT) {

    // branch on implementation
    //  Implementation: TYPE_I
    //
    if (implementation_d == TYPE_I) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	return Error::handle(name(), L"compute",
			     ERR_UNKALG, __FILE__, __LINE__);	
      }

      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }

    // branch on implementation
    //  Implementation: TYPE_II
    //
    else if (implementation_d == TYPE_II) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	return Error::handle(name(), L"compute",
			     ERR_UNKALG, __FILE__, __LINE__);	
      }

      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }

    // branch on implementation
    //  Implementation: TYPE_III
    //
    else if (implementation_d == TYPE_III) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	return Error::handle(name(), L"compute",
			     ERR_UNKALG, __FILE__, __LINE__);	
      }
      
      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }

    // branch on implementation
    //  Implementation: TYPE_IV
    //
    if (implementation_d == TYPE_IV) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	return Error::handle(name(), L"compute",
			     ERR_UNKIMP, __FILE__, __LINE__);	
      }

      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }
    
    // else: error unknown implementation type
    //
    else {
      return Error::handle(name(), L"compute",
			   ERR_UNKIMP, __FILE__, __LINE__);
    }    
  } 
  
  // Algorithm: IDFT
  //
  else {
    
    // branch on implementation:
    //  Implementation: CONVENTIONAL
    //    
    if (implementation_d == CONVENTIONAL) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	status = computeIdftConvRealFloat(output_a, logspectrum);
      }
      
      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }

    // else: error unknown implementation type
    //
    else {
      return Error::handle(name(), L"compute",
			   ERR_UNKIMP, __FILE__, __LINE__);
    }    
  }
  
  // possibly display the data
  //
  display(output_a, input_a, name());
  
  // exit gracefully
  //
  return status;
}

// method: compute
//
// arguments:
//  VectorComplexFloat& output: (output) cepstral coefficients
//  const VectorComplexFloat& input: (input) input vector
//  AlgorithmData::COEF_TYPE input_coef_type: (input) type of input
//  long channel_index: (input) channel index
//
// return: a boolean value indicating status
//
// this method computes the cepstral coefficients for a given input vector
//
boolean Cepstrum::compute(VectorComplexFloat& output_a,
			  const VectorComplexFloat& input_a,
			  AlgorithmData::COEF_TYPE input_coef_type_a,
			  long channel_index_a) {
  
  // declare local variables
  //
  boolean status = false;
  VectorComplexFloat input(input_a);
  
  // check the input arguments
  //
  if (order_d < (long)0) {
    Error::handle(name(), L"compute", ERR, __FILE__, __LINE__);
  }

  // compute the log spectrum from spectrum
  //
  VectorComplexFloat logspectrum;

  // make sure that input amplitude doesn't fall below the minimum
  // amplitude if it is defined
  //
  if (flag_min_amp_d) {
    input.limitMin((float)min_amp_d);
  }
  
  // take log of the input vector
  //
  logspectrum.log(input);

  // branch on algorithm
  //  Algorithm: IDCT
  //
  if (algorithm_d == IDCT) {

    // branch on implementation
    //  Implementation: TYPE_I
    //
    if (implementation_d == TYPE_I) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	return Error::handle(name(), L"compute",
			     ERR_UNKALG, __FILE__, __LINE__);	
      }

      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }

    // branch on implementation
    //  Implementation: TYPE_II
    //
    else if (implementation_d == TYPE_II) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	return Error::handle(name(), L"compute",
			     ERR_UNKALG, __FILE__, __LINE__);	
      }

      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }

    // branch on implementation
    //  Implementation: TYPE_III
    //
    else if (implementation_d == TYPE_III) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	return Error::handle(name(), L"compute",
			     ERR_UNKALG, __FILE__, __LINE__);	
      }
      
      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }

    // branch on implementation
    //  Implementation: TYPE_IV
    //
    if (implementation_d == TYPE_IV) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	return Error::handle(name(), L"compute",
			     ERR_UNKIMP, __FILE__, __LINE__);	
      }

      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }
    
    // else: error unknown implementation type
    //
    else {
      return Error::handle(name(), L"compute",
			   ERR_UNKIMP, __FILE__, __LINE__);
    }    
  } 
  
  // Algorithm: IDFT
  //
  else {
    
    // branch on implementation:
    //  Implementation: CONVENTIONAL
    //    
    if (implementation_d == CONVENTIONAL) {
      if (input_coef_type_a == AlgorithmData::SPECTRUM) {
	status = computeIdftConvComplexFloat(output_a, logspectrum);
      }
      
      // else: error unknown input type
      //
      else {
	return Error::handle(name(), L"compute",
			     ERR_UNCTYP, __FILE__, __LINE__);
      }
    }

    // else: error unknown implementation type
    //
    else {
      return Error::handle(name(), L"compute",
			   ERR_UNKIMP, __FILE__, __LINE__);
    }    
  }
  
  // possibly display the data
  //
  display(output_a, input_a, name());
  
  // exit gracefully
  //
  return status;
}

// method: computeIdctT1Float
//
// arguments:
//  VectorFloat& cepstrum: (output) cepstral coefficients
//  const VectorFloat& logspectrum: (input) input log magnitude spectrum
//
// return: a boolean value indicating status
//
// this method gives the cepstral coefficients for given input log
// magnitude spectrum using IDCT algorithm and TYPE_I implementation
//
boolean Cepstrum::computeIdctT1Float(VectorFloat& cepstrum_a,
				     const VectorFloat& logspectrum_a) {
  
  // check the algorithm and implementation
  //
  if ((algorithm_d != IDCT) && (implementation_d != TYPE_I)) {
    return Error::handle(name(), L"computeIdctT1Float",
			 ERR, __FILE__, __LINE__);
  }

  // declare local variable
  //
  long comp_num_coeffs = order_d + (long)1;

  // compute the order
  //
  Long order;
  order.max(comp_num_coeffs, logspectrum_a.length());
  
  // setup the algorithm
  //
  if (!ft_d.setAlgorithm(FourierTransform::DCT)) {
    return Error::handle(name(), L"computeIdctT1Float",
			 ERR, __FILE__, __LINE__);
  }
  
  // setup the implementation
  //
  if (!ft_d.setImplementation(FourierTransform::TYPE_I)) {
    return Error::handle(name(), L"computeIdctT1Float",
			 ERR, __FILE__, __LINE__);
  }

  // setup the direction
  //
  if (!ft_d.setDirection(FourierTransform::INVERSE)) {
    return Error::handle(name(), L"computeIdctT1Float",
			 ERR, __FILE__, __LINE__);
  }

  // setup the resolution
  //
  if (!ft_d.setResolution(FourierTransform::FIXED)) {
    return Error::handle(name(), L"computeIdctT1Float",
			 ERR, __FILE__, __LINE__);
  }

  // setup the input length (order of IDCT)
  //
  if (!ft_d.setInputLength(order)) {
    return Error::handle(name(), L"computeIdctT1Float",
			 ERR, __FILE__, __LINE__);
  }

  // setup the output length
  //
  if (!ft_d.setOutputLength(comp_num_coeffs)) {
    return Error::handle(name(), L"computeIdctT1Float",
			 ERR, __FILE__, __LINE__);
  }
  
  // call compute method of fourier transform
  //
  if (!ft_d.compute(cepstrum_a, logspectrum_a)) {
    return Error::handle(name(), L"computeIdctT1Float",
			 ERR, __FILE__, __LINE__);
  }
  
  // output debugging information
  //
  if (debug_level_d >= Integral::ALL) {
    cepstrum_a.debug(L"cepstrum");
  }
  
  // exit gracefully
  //
  return true;
}

// method: computeIdctT2Float
//
// arguments:
//  VectorFloat& cepstrum: (output) cepstral coefficients
//  const VectorFloat& logspectrum: (input) input log magnitude spectrum
//
// return: a boolean value indicating status
//
// this method gives the cepstral coefficients for given input log
// magnitude spectrum using IDCT algorithm and TYPE_II implementation
//
boolean Cepstrum::computeIdctT2Float(VectorFloat& cepstrum_a,
				     const VectorFloat& logspectrum_a) {
  
  // check the algorithm and implementation
  //
  if ((algorithm_d = IDCT) && (implementation_d != TYPE_II)) {
    return Error::handle(name(), L"computeIdctT2Float",
			 ERR, __FILE__, __LINE__);
  }

  // declare local variable
  //
  long comp_num_coeffs = order_d + (long)1;
  
  // compute the order
  //
  Long order;
  order.max(comp_num_coeffs, logspectrum_a.length());
  
  // setup the algorithm
  //
  if (!ft_d.setAlgorithm(FourierTransform::DCT)) {
    return Error::handle(name(), L"computeIdctT2Float",
			 ERR, __FILE__, __LINE__);
  }
  
  // setup the implementation
  //
  if (!ft_d.setImplementation(FourierTransform::TYPE_II)) {
    return Error::handle(name(), L"computeIdctT2Float",
			 ERR, __FILE__, __LINE__);
  }

  // setup the direction
  //
  if (!ft_d.setDirection(FourierTransform::INVERSE)) {
    return Error::handle(name(), L"computeIdctT2Float",
			 ERR, __FILE__, __LINE__);
  }

  // setup the resolution
  //
  if (!ft_d.setResolution(FourierTransform::FIXED)) {
    return Error::handle(name(), L"computeIdctT2Float",
			 ERR, __FILE__, __LINE__);
  }

  // setup the input length (order of IDCT)
  //
  if (!ft_d.setInputLength(order)) {
    return Error::handle(name(), L"computeIdctT2Float",
			 ERR, __FILE__, __LINE__);
  }

  // setup the output length
  //
  if (!ft_d.setOutputLength(comp_num_coeffs)) {
    return Error::handle(name(), L"computeIdctT2Float",
			 ERR, __FILE__, __LINE__);
  }
  
  // call compute method of fourier transform
  //
  if (!ft_d.compute(cepstrum_a, logspectrum_a)) {
    return Error::handle(name(), L"computeIdctT2Float",
			 ERR, __FILE__, __LINE__);
  }
  
  // output debugging information
  //
  if (debug_level_d >= Integral::ALL) {
    cepstrum_a.debug(L"cepstrum");
  }
  
  // exit gracefully
  //
  return true;
}

// method: computeIdctT3Float
//
// arguments:
//  VectorFloat& cepstrum: (output) cepstral coefficients
//  const VectorFloat& logspectrum: (input) input log magnitude spectrum
//
// return: a boolean value indicating status
//
// this method gives the cepstral coefficients for given input log
// magnitude spectrum using IDCT algorithm and TYPE_III implementation
//
boolean Cepstrum::computeIdctT3Float(VectorFloat& cepstrum_a,
				      const VectorFloat& logspectrum_a) {
  
  // check the algorithm and implementation
  //
  if ((algorithm_d = IDCT) && (implementation_d != TYPE_III)) {
    return Error::handle(name(), L"computeIdctT3Float",
			 ERR, __FILE__, __LINE__);
  }

  // declare local variable
  //
  long comp_num_coeffs = order_d + (long)1;

  // compute the order
  //
  Long order;
  order.max(comp_num_coeffs, logspectrum_a.length());
  
  // setup the algorithm
  //
  if (!ft_d.setAlgorithm(FourierTransform::DCT)) {
    return Error::handle(name(), L"computeIdctT3Float",
			 ERR, __FILE__, __LINE__);
  }
  
  // setup the implementation
  //
  if (!ft_d.setImplementation(FourierTransform::TYPE_III)) {
    return Error::handle(name(), L"computeIdctT3Float",
			 ERR, __FILE__, __LINE__);
  }

  // setup the direction
  //
  if (!ft_d.setDirection(FourierTransform::INVERSE)) {
    return Error::handle(name(), L"computeIdctT3Float",
			 ERR, __FILE__, __LINE__);
  }

  // setup the resolution
  //
  if (!ft_d.setResolution(FourierTransform::FIXED)) {
    return Error::handle(name(), L"computeIdctT3Float",
			 ERR, __FILE__, __LINE__);
  }

  // setup the input length (order of computeIdct)
  //
  if (!ft_d.setInputLength(order)) {
    return Error::handle(name(), L"computeIdctT3Float",
			 ERR, __FILE__, __LINE__);
  }

  // setup the output length
  //
  if (!ft_d.setOutputLength(comp_num_coeffs)) {
    return Error::handle(name(), L"computeIdctT3Float",
			 ERR, __FILE__, __LINE__);
  }
  
  // call compute method of fourier transform
  //
  if (!ft_d.compute(cepstrum_a, logspectrum_a)) {
    return Error::handle(name(), L"computeIdctT3Float",
			 ERR, __FILE__, __LINE__);
  }
  
  // output debugging information
  //
  if (debug_level_d >= Integral::ALL) {
    cepstrum_a.debug(L"cepstrum");
  }
  
  // exit gracefully
  //
  return true;
}

// method: computeIdctT4Float
//
// arguments:
//  VectorFloat& cepstrum: (output) cepstral coefficients
//  const VectorFloat& logspectrum: (input) input log magnitude spectrum
//
// return: a boolean value indicating status
//
// this method gives the cepstral coefficients for given input log
// magnitude spectrum using computeIdct algorithm and TYPE_IV implementation
//
boolean Cepstrum::computeIdctT4Float(VectorFloat& cepstrum_a,
			     const VectorFloat& logspectrum_a) {
  
  // check the algorithm and implementation
  //
  if ((algorithm_d = IDCT) && (implementation_d != TYPE_IV)) {
    return Error::handle(name(), L"computeIdctT4Float",
			 ERR, __FILE__, __LINE__);
  }
  
  // declare local variable
  //
  long comp_num_coeffs = order_d + (long)1;

  // compute the order
  //
  Long order;
  order.max(comp_num_coeffs, logspectrum_a.length());
  
  // setup the algorithm
  //
  if (!ft_d.setAlgorithm(FourierTransform::DCT)) {
    return Error::handle(name(), L"computeIdctT4Float",
			 ERR, __FILE__, __LINE__);
  }
  
  // setup the implementation
  //
  if (!ft_d.setImplementation(FourierTransform::TYPE_IV)) {
    return Error::handle(name(), L"computeIdctT4Float",
			 ERR, __FILE__, __LINE__);
  }

  // setup the direction
  //
  if (!ft_d.setDirection(FourierTransform::INVERSE)) {
    return Error::handle(name(), L"computeIdctT4Float",
			 ERR, __FILE__, __LINE__);
  }

  // setup the resolution
  //
  if (!ft_d.setResolution(FourierTransform::FIXED)) {
    return Error::handle(name(), L"computeIdctT4Float",
			 ERR, __FILE__, __LINE__);
  }

  // setup the input length (order of computeIdct)
  //
  if (!ft_d.setInputLength(order)) {
    return Error::handle(name(), L"computeIdctT4Float",
			 ERR, __FILE__, __LINE__);
  }

  // setup the output length
  //
  if (!ft_d.setOutputLength(comp_num_coeffs)) {
    return Error::handle(name(), L"computeIdctT4Float",
			 ERR, __FILE__, __LINE__);
  }
  
  // call compute method of fourier transform
  //
  if (!ft_d.compute(cepstrum_a, logspectrum_a)) {
    return Error::handle(name(), L"computeIdctT4Float",
			 ERR, __FILE__, __LINE__);
  }
  
  // output debugging information
  //
  if (debug_level_d >= Integral::ALL) {
    cepstrum_a.debug(L"cepstrum");
  }
  
  // exit gracefully
  //
  return true;
}

// method: computeIdftConvRealFloat
//
// arguments:
//  VectorComplexFloat& cepstrum: (output) cepstral coefficients
//  const VectorFloat& logspectrum: (input) input log magnitude spectrum
//
// return: a boolean value indicating status
//
// this method implements a DFT-based computation on floats.
//
boolean Cepstrum::computeIdftConvRealFloat(VectorComplexFloat& cepstrum_a,
					   const VectorFloat& logspectrum_a) {
  
  // check the algorithm and implementation
  //
  if ((algorithm_d != IDFT) && (implementation_d != CONVENTIONAL)) {
    return Error::handle(name(), L"computeIdftConvRealFloat",
			 ERR, __FILE__, __LINE__);
  }

  // declare local variable
  //
  long comp_num_coeffs = order_d + (long)1;

  // compute the order
  //
  Long order;
  order.max(comp_num_coeffs, logspectrum_a.length());
  
  // setup the algorithm
  //
  if (!ft_d.setAlgorithm(FourierTransform::DFT)) {
    return Error::handle(name(), L"computeIdftConvRealFloat",
			 ERR, __FILE__, __LINE__);
  }
  
  // setup the implementation
  //
  if (!ft_d.setImplementation(FourierTransform::CONVENTIONAL)) {
    return Error::handle(name(), L"computeIdftConvRealFloat",
			 ERR, __FILE__, __LINE__);
  }

  // setup the direction
  //
  if (!ft_d.setDirection(FourierTransform::INVERSE)) {
    return Error::handle(name(), L"computeIdftConvRealFloat",
			 ERR, __FILE__, __LINE__);
  }

  // setup the resolution
  //
  if (!ft_d.setResolution(FourierTransform::AUTO)) {
    return Error::handle(name(), L"computeIdftConvRealFloat",
			 ERR, __FILE__, __LINE__);
  }

  // setup the input length (order of computeIdft)
  //
  if (!ft_d.setInputLength(order)) {
    return Error::handle(name(), L"computeIdftConvRealFloat",
			 ERR, __FILE__, __LINE__);
  }

  // setup the output length
  //
  if (!ft_d.setOutputLength(comp_num_coeffs)) {
    return Error::handle(name(), L"computeIdftConvRealFloat",
			 ERR, __FILE__, __LINE__);
  }
  
  // call compute method of fourier transform
  //
  if (!ft_d.compute(cepstrum_a, logspectrum_a)) {
    return Error::handle(name(), L"computeIdftConvRealFloat",
			 ERR, __FILE__, __LINE__);
  }

  // output debugging information
  //
  if (debug_level_d >= Integral::ALL) {
    cepstrum_a.debug(L"cepstrum");
  }
  
  // exit gracefully
  //
  return true;
}

// method: computeIdftConvComplexFloat
//
// arguments:
//  VectorComplexFloat& cepstrum: (output) cepstral coefficients
//  const VectorComplexFloat& logspectrum: (input) input log spectrum
//
// return: a boolean value indicating status
//
// this method implements a DFT-based computation on complex floats.
//
boolean Cepstrum::computeIdftConvComplexFloat(VectorComplexFloat& cepstrum_a,
						 const VectorComplexFloat&
						 logspectrum_a) {
  
  // check the algorithm and implementation
  //
  if ((algorithm_d != IDFT) && (implementation_d != CONVENTIONAL)) {
    return Error::handle(name(), L"computeIdftConvComplexFloat",
			 ERR, __FILE__, __LINE__);
  }

  // declare local variable
  //
  long comp_num_coeffs = order_d + (long)1;

  // compute the order
  //
  Long order;
  order.max(comp_num_coeffs, logspectrum_a.length());
  
  // setup the algorithm
  //
  if (!ft_d.setAlgorithm(FourierTransform::DFT)) {
    return Error::handle(name(), L"computeIdftConvComplexFloat",
			 ERR, __FILE__, __LINE__);
  }
  
  // setup the implementation
  //
  if (!ft_d.setImplementation(FourierTransform::CONVENTIONAL)) {
    return Error::handle(name(), L"computeIdftConvComplexFloat",
			 ERR, __FILE__, __LINE__);
  }

  // setup the direction
  //
  if (!ft_d.setDirection(FourierTransform::INVERSE)) {
    return Error::handle(name(), L"computeIdftConvComplexFloat",
			 ERR, __FILE__, __LINE__);
  }

  // setup the resolution
  //
  if (!ft_d.setResolution(FourierTransform::AUTO)) {
    return Error::handle(name(), L"computeIdftConvComplexFloat",
			 ERR, __FILE__, __LINE__);
  }

  // setup the input length (order of computeIdft)
  //
  if (!ft_d.setInputLength(order)) {
    return Error::handle(name(), L"computeIdftConvComplexFloat",
			 ERR, __FILE__, __LINE__);
  }
  
  // setup the output length
  //
  if (!ft_d.setOutputLength(comp_num_coeffs)) {
    return Error::handle(name(), L"computeIdftConvComplexFloat",
			 ERR, __FILE__, __LINE__);
  }
  
  // call compute method of fourier transform
  //
  if (!ft_d.compute(cepstrum_a, logspectrum_a)) {
    return Error::handle(name(), L"computeIdftConvComplexFloat",
			 ERR, __FILE__, __LINE__);
  }
  
  // output debugging information
  //
  if (debug_level_d >= Integral::ALL) {
    cepstrum_a.debug(L"cepstrum");
  }
  
  // exit gracefully
  //
  return true;
}
