// file: $isip/class/mmedia/AudioFile/adf_02.cc
// version: $Id: adf_02.cc 9384 2004-01-16 19:37:53Z parihar $
//

// isip include files
//
#include <Console.h>
#include "AudioFile.h"

// method: diagnose
//
// arguments:
//  Integral::DEBUG level: (input) debug level for diagnostics
//
// return: a boolean value indicating status
//
boolean AudioFile::diagnose(Integral::DEBUG level_a) {

  //---------------------------------------------------------------------------
  //
  // 0. preliminaries
  //
  //---------------------------------------------------------------------------

  // output the class name
  //
  if (level_a > Integral::NONE) {
    Filename output(L"diagnosing class ");
    output.concat(CLASS_NAME);
    output.concat(L": ");
    Console::put(output);
    Console::increaseIndention();
  }
  
  // --------------------------------------------------------------------
  //
  // 1. required public methods
  //
  // --------------------------------------------------------------------

  if (level_a >= Integral::BRIEF) {
    Console::put(L"testing constructors:\n");
  }

  AudioFile adf1(BINARY, RAW, 16000, 2, 1);
  adf1.setCompType(LINEAR);
  adf1.setAmplitudeRange(0.01);
  
  if (adf1.getFileFormat() != RAW ) {
    return Error::handle(name(), L"set/getFileType", Error::TEST,
			 __FILE__, __LINE__);
  }

  if (adf1.getCompType() != LINEAR ) {
    return Error::handle(name(), L"set/getCompType", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (adf1.getAmplitudeRange() != (double)0.01 ) {
    return Error::handle(name(), L"set/getAmplitudeRange", Error::TEST,
			 __FILE__, __LINE__);
  }
  
  if (adf1.getSampleFrequency() != 16000 ) {
    return Error::handle(name(), L"set/getSampleFrequency", Error::TEST,
			 __FILE__, __LINE__);
  }
  
  if (adf1.getSampleNumBytes() != 2 ) {
    return Error::handle(name(), L"set/getSampleNumBytes", Error::TEST,
			 __FILE__, __LINE__);
  }
  
  if (adf1.getSamplePrecision() != NONE ) {
    return Error::handle(name(), L"set/getSamplePrecision", Error::TEST,
			 __FILE__, __LINE__);
  }
  
  if (adf1.getNumChannels() != 1 ) {
    return Error::handle(name(), L"set/getNumChannels", Error::TEST,
			 __FILE__, __LINE__);
  }

  
  // test copy constructor and eq method
  //
  AudioFile adf2(adf1);
  if (!adf2.eq(adf1)) {
    adf2.debug(L"copy adf");
    return Error::handle(name(), L"copy assign/ eq", Error::TEST,
			 __FILE__, __LINE__);
  }
  
  // test new and delete
  //
  AudioFile* adf3 = new AudioFile(adf1);
  delete adf3;
  

  // --------------------------------------------------------------------
  //
  // 2. check Sof i/o methods
  //
  // --------------------------------------------------------------------

  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"testing i/o methods:\n");
    }
    
    Filename file_text;
    Filename file_bin;
    Integral::makeTemp(file_text);
    Integral::makeTemp(file_bin);
    
    Sof sof0;
    sof0.open(file_text, File::WRITE_ONLY, File::TEXT);
    Sof sof1;
    sof1.open(file_bin, File::WRITE_ONLY, File::BINARY);

    // allocate an object and change some parameter to a non default
    // value
    //
    AudioFile src;
    src.setAmplitudeRange(0.01);
    src.setSampleFrequency(16000);
    src.sampled_data_d.setLength(1);
    src.sampled_data_d(0).assign(L"1, 2, 3");
    
    src.write(sof0, 0);
    src.write(sof1, 0);
    
    sof0.close();
    sof1.close();

    sof0.open(file_text);
    sof1.open(file_bin);

    AudioFile dst_text;
    dst_text.read(sof0, 0);

    if (!dst_text.eq(src)) {
      src.debug(L"before write (text)");
      dst_text.debug(L"text read");
      return Error::handle(name(), L"read", Error::TEST, __FILE__, __LINE__);
    }
    
    AudioFile dst_bin;
    dst_bin.read(sof1, 0);
    
    if (!dst_bin.eq(src)) {
      dst_bin.debug(L"bin read");
      return Error::handle(name(), L"read", Error::TEST, __FILE__, __LINE__);
    }

    sof0.close();
    sof1.close();
  }

  // --------------------------------------------------------------------
  //
  // 3. check data i/o methods
  //
  // --------------------------------------------------------------------

  if (level_a >= Integral::BRIEF) {
    Console::put(L"testing data i/o methods (core functionality):\n");
    Console::increaseIndention();
  }
  
  Filename file_text;
  Filename file_bin;
  Integral::makeTemp(file_text);
  Integral::makeTemp(file_bin);

  Filename output400;
  Filename output8000;
  Filename output8000a;
  Filename output32000;
  Filename output32000a;
  Filename output200b;
  Filename output_full;
  Filename output_fulla;
  Filename output_swap;
  Filename output_swapa;
  Filename output_sof;
  Filename output_full_sof;
  Filename output_text;
  Filename output_full_af;
  Filename output_full_sp;
  
  {

    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 1: testing 400 bytes in 4 chunks:\n");
    }


    //  test 1: copy a 400 byte file in 4 chunks
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/input_400.raw");
    Integral::makeTemp(output400);
    File::registerTemp(output400);
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    AudioFile dst(BINARY, RAW);
    dst.setID(src.getID());
    dst.open(output400, File::WRITE_ONLY);
    src.setNumChannels(1);
    dst.setNumChannels(1);

    // get the number of samples
    //
    if (src.getNumSamples() != 400) {
      Console::put(L"make sure your input raw files contains 400 samples");
      return Error::handle(name(), L"getNumSamples", Error::TEST,
			   __FILE__, __LINE__);
    }
    
    // read the first 0.01 second samples into a vector
    //
    Vector<VectorFloat> data(1);
    src.getData(data, 0.0, 0.01);             // 0.01 * 8000 = 80 samples
    
    // write these 80 samples to the output
    //
    dst.writeAudioData(data, 0);
    
    // read a window of samples into a vector
    //
    src.getWindow(data, 0.02, 0.02);

    // write these 160 samples to the output
    //
    dst.writeAudioData(data, 0);

    // read samples of a certain range into a vector
    //
    src.getRange(data, 0.03, 0.05);

    // write these 160 samples to the output
    //
    dst.writeAudioData(data, 0);

    if (src.getID().ne(L"input_400")) {
      src.getID().debug(L"id_d");
      return Error::handle(name(), L"getID", Error::TEST, __FILE__, __LINE__);
    }

    src.close();
    dst.close();

    // make sure the output file is equivalent
    //
    if (!File::compare(input, output400)) {
      return Error::handle(name(), L"compare", Error::TEST,__FILE__,__LINE__);
    }
    
    // write this file configuration a temporary file
    //
    Sof sof0;
    sof0.open(file_text, File::WRITE_ONLY, File::TEXT);
    Sof sof1;
    sof1.open(file_bin, File::WRITE_ONLY, File::BINARY);

    src.write(sof0, 0);
    src.write(sof1, 0);

    sof0.close();
    sof1.close();
  }
  
  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 2: testing 16000 bytes in 80 chunks:\n");
    }

    //  test 2: copy a 16000 byte file in 80 chunks. note that
    // this will require more data to be buffered since the block_size
    // is 4096 samples.
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/input_8000.raw");
    Integral::makeTemp(output8000);
    File::registerTemp(output8000);
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    AudioFile dst(BINARY, RAW);

    src.setNumChannels(1);
    
    // read the configuration from the Sof AudioFile
    //
    Sof sof0;
    sof0.open(file_text);
    dst.read(sof0, 0);
    dst.setID(src.getID());
    dst.open(output8000, File::WRITE_ONLY);
    sof0.close();
    
    // loop through 100 samples at a time
    //
    for (long i = 0; i < 80; i++) {
    
      Vector<VectorFloat> data(1);
      src.getData(data(0), 0, i * 100, 100l);

      // write these 100 samples to the output
      //
      dst.writeAudioData(data, 0);
    }
    src.close();
    dst.close();

    // we can't compare the files since the output is an Sof file
    //
  }
  
  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 2a: testing 16000 bytes in 1 chunk:\n");
    }

    // test 2a: copy a 16000 byte file in 1 chunk. note that
    // this will require more data to be buffered since the block_size
    // is 4096 samples.
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/input_8000.raw");
    Integral::makeTemp(output8000a);
    File::registerTemp(output8000a);

    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    AudioFile dst(BINARY, RAW);
    VectorFloat coeffs(L"1.0,0.0,0.0");
    src.setMaCoeff(coeffs);
    src.setNumChannels(1);
    
    Sof sof0;
    sof0.open(file_bin);
    dst.readSofStart(sof0, 0);
    dst.setID(src.getID());
    dst.open(output8000a, File::WRITE_ONLY);
    sof0.close();

    Vector<VectorFloat> data(1);
    src.getData(data(0), 0, 0l, 8000);
    dst.writeAudioData(data, 0);

    src.close();
    dst.close();

    // make sure the output file is equivalent to that of the last step
    //
    if (!File::compare((unichar*)output8000, (unichar*)output8000a)) {
      return Error::handle(name(), L"compare", Error::TEST,__FILE__,__LINE__);
    }
  }
  
  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 3: testing 64000 bytes in 640 chunk:\n");
    }

    //  test 3: copy a 64000 sample file in 640 chunks. note
    // that this will require more data to be buffered since the
    // block_size is 4096 samples. this will also have to clear out
    // the start of the circular buffer since.
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/input_32000.raw");
    Integral::makeTemp(output32000);
    File::registerTemp(output32000);
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    AudioFile dst(BINARY, RAW);
    dst.setID(src.getID());
    dst.open(output32000, File::WRITE_ONLY);
    src.setNumChannels(1);
    dst.setNumChannels(1);
    
    // loop through 100 samples at a time
    //
    for (long i = 0; i < 320; i++) {
    
      Vector<VectorFloat> data(1);
      src.getData(data(0), 0, i * 100, 100l);

      // write these 100 samples to the output
      //
      dst.writeAudioData(data, 0);
    }
    src.close();
    dst.close();

    // make sure the output file is equivalent
    //
    if (!File::compare(input, output32000)) {
      return Error::handle(name(), L"compare", Error::TEST,__FILE__,__LINE__);
    }
  }

  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 3a: testing 64000 bytes in 1 chunk:\n");
    }

    //  test 3a: copy a 16000 byte file in 1 chunk. note that
    // this will require more data to be buffered since the block_size
    // is 4096 samples.
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/input_32000.raw");
    Integral::makeTemp(output32000a);    
    File::registerTemp(output32000a);
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);    
    src.open(input);
    AudioFile dst(BINARY, RAW);
    dst.setID(src.getID());
    dst.open(output32000a, File::WRITE_ONLY);

    if (src.file_format_d != RAW) {
      return Error::handle(name(), L"type", Error::TEST, __FILE__, __LINE__);
    }
    if (dst.file_format_d != RAW) {
      return Error::handle(name(), L"type", Error::TEST, __FILE__, __LINE__);
    }
    
    src.setNumChannels(1);
    dst.setNumChannels(1);
    
    Vector<VectorFloat> data(1);
    src.getData(data(0), 0, 0l, 32000);
    dst.writeAudioData(data, 0);

    // now that we are at the end of the file, read the first 200
    // bytes again.
    //
    src.getData(data(0), 0, 0l, 200);
    Integral::makeTemp(output200b);
    File::registerTemp(output200b);
    AudioFile dstb;
    dstb.setNumChannels(1);
    dstb.open(output200b, File::WRITE_ONLY);
    dstb.writeAudioData(data, 0);
    dstb.close();
    
    src.close();
    dst.close();

    // make sure the output file is equivalent
    //
    if (!File::compare(input, output32000a)) {
      return Error::handle(name(), L"compare", Error::TEST,__FILE__,__LINE__);
    }
  }

  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 4: testing entire file:\n");
    }

    //  test 4: copy the full file
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/little_endian.raw");
    Integral::makeTemp(output_full); 
    File::registerTemp(output_full);
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    AudioFile dst(BINARY, RAW);
    dst.setID(src.getID());
    dst.open(output_full, File::WRITE_ONLY);
    src.setNumChannels(1);
    dst.setNumChannels(1);
    
    // loop through 100 samples at a time
    //
    Vector<VectorFloat> data(1);
    long i = 0;
    while (src.getData(data(0), 0, i * 100l, 100) > 0) {
      
      // write these 100 samples to the output
      //
      dst.writeAudioData(data, 0);
      i++;
    }
    src.close();
    dst.close();

    // make sure the output file is equivalent
    //
    if (!File::compare(input, output_full)) {
      return Error::handle(name(), L"compare", Error::TEST,__FILE__,__LINE__);
    }
  }

  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 4a: testing entire file in 1 chunk:\n");
    }

    // test 4a: copy the full file in one chunk
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/little_endian.raw");
    Integral::makeTemp(output_fulla); 
    File::registerTemp(output_fulla);
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    AudioFile dst(BINARY, RAW);
    dst.setID(src.getID());
    dst.open(output_fulla, File::WRITE_ONLY);
    src.setNumChannels(1);
    dst.setNumChannels(1);
    
    // loop through 100 samples at a time
    //
    Vector<VectorFloat> data(1);
    src.getData(data(0), 0, 0l, 10000000l);
    dst.writeAudioData(data, 0);

    src.close();
    dst.close();

    // make sure the output file is equivalent
    //
    if (!File::compare(input, output_fulla)) {
      return Error::handle(name(), L"compare", Error::TEST,__FILE__,__LINE__);
    }
  }

  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 5a: testing swapped read :\n");
    }

    // test 5a: read data from swapped and unswapped sources and compare
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/input_8000.raw");
    Filename input_swap(L"$ISIP_DEVEL/doc/examples/data/audio/input_8000_swapped.raw");
    
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    src.setNumChannels(1);

    AudioFile src_swap;
    src_swap.setFileFormat(AudioFile::RAW);
    src_swap.setFileType(BINARY);
    src_swap.open(input_swap);
    src_swap.setNumChannels(1);
    src_swap.setBMode(SWAP);

    if (level_a >= Integral::ALL) {
      src.debug(L"native");
      src_swap.debug(L"swap");
    }
    
    // loop through 100 samples at a time
    //
    Vector<VectorFloat> data(1);
    src.getData(data(0), 0, 0l, 100);

    Vector<VectorFloat> data_swap(1);
    src_swap.getData(data_swap(0), 0, 0l, 100);

    if (data_swap(0).ne(data(0))) {
      data_swap(0).debug(L"swapped");
      data(0).debug(L"native");
      return Error::handle(name(), L"read-swap", Error::TEST, __FILE__,
			   __LINE__);
    }

    src.getData(data(0), 0, 100l, 100);
    src_swap.getData(data_swap(0), 0, 100l, 100);

    if (data_swap(0).ne(data(0))) {
      return Error::handle(name(), L"read-swap", Error::TEST, __FILE__,
			   __LINE__);
    }

    src.close();
    src_swap.close();
  }

  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 5b: test swapped write\n");
    }

    // test 5b: read data unswapped source, write to a swapped source,
    //          read it back in swapped and compare.
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/input_8000.raw");
    Integral::makeTemp(output_swap);
    output_swap.concat(L".raw");
    File::registerTemp(output_swap);
        
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    src.setNumChannels(1);

    AudioFile dst(BINARY, RAW);
    dst.setID(src.getID());
    dst.open(output_swap, File::WRITE_ONLY);
    dst.setNumChannels(1);
    dst.setBMode(SWAP);


    // read in the data
    //
    Vector<VectorFloat> data(1);
    src.getData(data(0), 0, 0l, 8000);

    dst.writeAudioData(data, 0);

    src.close();
    dst.close();

    // make sure the output file is equivalent to our reference file
    //
    if (!File::compare((unichar*)output_swap, L"$ISIP_DEVEL/doc/examples/data/audio/input_8000_swapped.raw")) {
      return Error::handle(name(), L"compare", Error::TEST,__FILE__,__LINE__);
    }
  }

  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 5c: test swapped read\n");
    }

    // test 5c: read data from swapped and unswapped sources and compare
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/input_8000.raw");
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    src.setNumChannels(1);

    AudioFile src_swap;
    src_swap.setFileFormat(AudioFile::RAW);
    src_swap.setFileType(BINARY);
    src_swap.open(output_swap);
    src_swap.setNumChannels(1);
    src_swap.setBMode(SWAP);

    if (level_a >= Integral::ALL) {
      src.debug(L"native");
      src_swap.debug(L"swap");
    }
    
    // loop through 100 samples at a time
    //
    Vector<VectorFloat> data(1);
    Vector<VectorFloat> data_swap(1);
    long i = 0;
    while (src.getData(data(0), 0, i * 100l, 100) > 0) {

      // read in data from the swapped source
      //
      if (src_swap.getData(data_swap(0), 0, i * 100l, 100) != 100) {
	return Error::handle(name(), L"getData", Error::TEST,
			     __FILE__, __LINE__);
      }

      if (data_swap(0).ne(data(0))) {
	data_swap(0).debug(L"swapped");
	data(0).debug(L"native");
	return Error::handle(name(), L"read-swap", Error::TEST, __FILE__,
			     __LINE__);
      }
      i++;
    }

    src.close();
    src_swap.close();
  }

  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 6a: write to an Sof audio file:\n");
    }

    // test 6a: write to an Sof audio file
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/input_8000.raw");
    Integral::makeTemp(output_sof); 
    File::registerTemp(output_sof);
    
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    src.setNumChannels(1);

    AudioFile dst(TEXT, SOF);
    dst.setID(src.getID());
    dst.open(output_sof, File::WRITE_ONLY);
    
    // loop through 100 samples at a time
    //
    Vector<VectorFloat> data(1);
    long i = 0;
    while (src.getData(data(0), 0, i * 100l, 100) > 0) {
      dst.writeAudioData(data, 0);
      i++;
    }

    src.close();
    dst.close();
  }

  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 6b: read from an Sof audio file:\n");
    }

    // test 6b: read from an Sof audio file
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/input_8000.raw");
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    src.setNumChannels(1);

    AudioFile src_sof(TEXT, SOF);
    src_sof.open(output_sof, File::READ_ONLY);
    
    // loop through 100 samples at a time
    //
    Vector<VectorFloat> data(1);
    Vector<VectorFloat> data_sof(1);
    long i = 0;
    while (src.getData(data(0), 0, i * 100l, 100) > 0) {

      if (!src_sof.getData(data_sof(0), 0, i * 100l, 100) > 0) {
	return Error::handle(name(), L"getData", Error::TEST,
			     __FILE__, __LINE__);
      }

      if (data_sof(0).ne(data(0))) {
	data_sof(0).debug(L"sof");
	data(0).debug(L"raw");
	return Error::handle(name(), L"read-sof", Error::TEST, __FILE__,
			     __LINE__);
      }
      i++;
    }

    src.close();
    src_sof.close();
  }

  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 6c: write to a big Sof audio file:\n");
    }

    // test 6c: write to a big Sof audio file
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/little_endian.raw");
    Integral::makeTemp(output_full_sof); 
    File::registerTemp(output_full_sof);
    
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    src.setNumChannels(1);

    AudioFile dst;
    dst.setNumChannels(1);
    dst.setID(src.getID());
    dst.open(output_full_sof, File::WRITE_ONLY);
    
    // loop through 100 samples at a time
    //
    Vector<VectorFloat> data(1);
    long i = 0;
    while (src.getData(data(0), 0, i * 100l, 100) > 0) {
      dst.writeAudioData(data, 0);
      i++;
    }

    src.close();
    dst.close();
  }

  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 6d: read from a big Sof audio file:\n");
    }

    // test 6d: read from a big Sof audio file
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/little_endian.raw");
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    src.setNumChannels(1);

    AudioFile src_sof;
    src_sof.sample_num_bytes_d = 4;
    src_sof.file_format_d = SOF;
    src_sof.open(output_full_sof, File::READ_ONLY);

    // the object should configure itself from the file
    //
    if (src_sof.sample_num_bytes_d != (Long)2) {
      return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
    }
    if (src_sof.num_channels_d != (Long)1) {
      return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
    }
    if (src_sof.file_format_d != SOF) {
      return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
    }

    
    // loop through 100 samples at a time
    //
    Vector<VectorFloat> data(1);
    Vector<VectorFloat> data_sof(1);
    long i = 0;
    while (src.getData(data(0), 0, i * 100l, 100) > 0) {

      if (!src_sof.getData(data_sof(0), 0, i * 100l, 100) > 0) {
	return Error::handle(name(), L"getData", Error::TEST,
			     __FILE__, __LINE__);
      }

      if (data_sof(0).ne(data(0))) {
	Long(i).debug(L"i=");
	data_sof(0).debug(L"sof");
	data(0).debug(L"raw");
	return Error::handle(name(), L"read-sof", Error::TEST, __FILE__,
			     __LINE__);
      }
      i++;
    }

    src.close();
    src_sof.close();

    // the object should restore it's configuration
    //
    if (src_sof.sample_num_bytes_d != (Long)4) {
      return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
    }

    if (src_sof.file_format_d != SOF) {
      return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
    }
  }
  
  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 6e: write to a text Sof audio file:\n");
    }

    // test 6e: write to an Sof audio file
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/input_8000.raw");
    Integral::makeTemp(output_text); 
    File::registerTemp(output_text);
    
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    src.setNumChannels(1);

    AudioFile dst(TEXT, SOF);
    dst.setID(src.getID());
    dst.open(output_text, File::WRITE_ONLY);

    // loop through 100 samples at a time
    //
    Vector<VectorFloat> data(1);
    long i = 0;
    while (src.getData(data(0), 0, i * 100l, 100) > 0) {
      dst.writeAudioData(data, 0);
      i++;
    }

    src.close();
    dst.close();
  }

  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 6f: read from a text Sof audio file:\n");
    }

    // test 6f: read from an Sof audio file
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/input_8000.raw");
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    src.setNumChannels(1);

    AudioFile src_sof(TEXT, SOF);
    src_sof.open(output_text, File::READ_ONLY);

    if (src_sof.getID().ne(L"input_8000")) {
      return Error::handle(name(), L"getID", Error::TEST, __FILE__, __LINE__);
    }
    
    // loop through 100 samples at a time
    //
    Vector<VectorFloat> data(1);
    Vector<VectorFloat> data_sof(1);
    long i = 0;
    while (src.getData(data(0), 0, i * 100l, 100) > 0) {

      if (!src_sof.getData(data_sof(0), 0, i * 100l, 100) > 0) {
	return Error::handle(name(), L"getData", Error::TEST,
			     __FILE__, __LINE__);
      }

      if (data_sof(0).ne(data(0))) {
	data_sof(0).debug(L"sof");
	data(0).debug(L"raw");
	return Error::handle(name(), L"read-sof", Error::TEST, __FILE__,
			     __LINE__);
      }
      i++;
    }

    src.close();
    src_sof.close();
  }

  // this code is to test multichannel capabilities of the AudioFile
  // class but it causes segmentation fault. the reason is that there
  // is a memory problem in multichannel processing of audiofile which
  // is waiting for purify.
  //
  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 6g: testing 16000 bytes in 80 chunks for multichannel data:\n");
    }

    //  test 6g: copy a 16000 byte file in 80 chunks. note that
    // this will require more data to be buffered since the block_size
    // is 4096 samples.
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/input_8000.raw");
    
    Filename output;
    Integral::makeTemp(output);
    output.concat(L".raw");
    File::registerTemp(output);
    AudioFile src(BINARY, RAW);
    src.open(input);
    AudioFile dst(TEXT);

    dst.setID(src.getID());
    src.setNumChannels(2);
    dst.setNumChannels(2);
    dst.open(output, File::WRITE_ONLY);

    // loop through 100 samples at a time
    //
    for (long i = 0; i < 40; i++) {
    
      Vector<VectorFloat> data(2);
      src.getData(data, i * 100, 100l);
      
      // write these 100 samples to the output
      //
      dst.writeAudioData(data);
    }
    src.close();
    dst.close();
  }

  if (level_a >= Integral::BRIEF) {
    Console::decreaseIndention();
  }

  // --------------------------------------------------------------------
  //
  // 4. check i/o methods for audiofile format (WAV)
  //
  // --------------------------------------------------------------------

#ifdef HAVE_AUDIOFILE
  
  if (level_a >= Integral::BRIEF) {
    Console::put(L"testing data i/o methods (core functionality) for SGI library on WAV format:\n");
    Console::increaseIndention();
  }

  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 7a: write to a big SGI (WAV) audio file:\n");
    }
    
    // test 7a: write to a big WAV audiofile
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/little_endian.raw");
    Integral::makeTemp(output_full_af); 
    File::registerTemp(output_full_af);
    
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    src.setNumChannels(1);
    
    AudioFile dst;
    dst.setFileFormat(AudioFile::WAV);
    dst.File::setBMode(File::LITTLE_ENDIAN);// WAV is defined for LITTLE-ENDIAN
    dst.setNumChannels(1);
    dst.open(output_full_af, File::WRITE_ONLY);
    
    // loop through 100 samples at a time
    //
    Vector<VectorFloat> data(1);
    long i = 0;
    while (src.getData(data(0), 0, i * 100l, 100) > 0) {
      dst.writeAudioData(data, 0);
      i++;
    }
    
    src.close();
    dst.close();
  }
  
  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 7b: read from a big SGI (WAV) audio file:\n");
    }

    // test 7b: read from a big Sof audio file
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/little_endian.raw");
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    src.setNumChannels(1);

    AudioFile src_af;
    src_af.setSampleNumBytes(4);
    src_af.setFileFormat(AudioFile::WAV);
    src_af.File::setBMode(File::LITTLE_ENDIAN);
    src_af.open(output_full_af, File::READ_ONLY);
    
    // the object should configure itself from the file
    //
    if (src_af.sample_num_bytes_d != (Long)2) {
      return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
    }
    if (src_af.num_channels_d != (Long)1) {
      return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
    }
    if (src_af.file_format_d != WAV) {
      return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
    }
    
    
    // loop through 100 samples at a time
    //
    Vector<VectorFloat> data(1);
    Vector<VectorFloat> data_af(1);
    long i = 0;
    while (src.getData(data(0), 0, i * 100l, 100) > 0) {

      if (!src_af.getData(data_af(0), 0, i * 100l, 100) > 0) {
	return Error::handle(name(), L"getData", Error::TEST,
			     __FILE__, __LINE__);
      }

      if (data_af(0).ne(data(0))) {
	Long(i).debug(L"i=");
	data_af(0).debug(L"sgi audiofile (WAV)");
	data(0).debug(L"raw");
	return Error::handle(name(), L"read-sgi-audiofile(WAV)", Error::TEST, __FILE__,
			     __LINE__);
      }
      i++;
    }

    src.close();
    src_af.close();

    // the object should restore it's configuration
    //
    if (src_af.sample_num_bytes_d != (Long)4) {
      return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
    }

    if (src_af.file_format_d != WAV) {
      return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
    }
  }
  
  if (level_a >= Integral::BRIEF) {
    Console::decreaseIndention();
  }
#endif
  
  // --------------------------------------------------------------------
  //
  // 5. check i/o methods for NIST sphere format
  //
  // --------------------------------------------------------------------
  
#ifdef HAVE_SPHERE
  
  if (level_a >= Integral::BRIEF) {
    Console::put(L"testing data i/o methods (core functionality) for NIST library on PCM format:\n");
    Console::increaseIndention();
  }

  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 7a: write to a big NIST Sphere (PCM) audio file:\n");
    }
    
    // test 7a: write to a big PCM SPHERE
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/little_endian.raw");
    Integral::makeTemp(output_full_sp); 
    File::registerTemp(output_full_sp);
    
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    src.setNumChannels(1);
    
    AudioFile dst;
    dst.setFileFormat(AudioFile::SPHERE);
    dst.setCompType(AudioFile::PCM);
    dst.setNumChannels(1);
    dst.open(output_full_sp, File::WRITE_ONLY);
    
    // loop through 100 samples at a time
    //
    Vector<VectorFloat> data(1);
    long i = 0;
    while (src.getData(data(0), 0, i * 100l, 100) > 0) {
      dst.writeAudioData(data, 0);
      i++;
    }
    
    src.close();
    dst.close();
  }
  
  {
    if (level_a >= Integral::BRIEF) {
      Console::put(L"test 7b: read from a big NIST Sphere (PCM) audio file:\n");
    }

    // test 7b: read from a big NIST Sphere (PCM) audio file
    //
    Filename input(L"$ISIP_DEVEL/doc/examples/data/audio/little_endian.raw");
    AudioFile src;
    src.setFileFormat(AudioFile::RAW);
    src.setFileType(BINARY);
    src.open(input);
    src.setNumChannels(1);

    AudioFile src_sp;
    src_sp.setSampleNumBytes(4);
    src_sp.setFileFormat(AudioFile::SPHERE);
    src_sp.setCompType(AudioFile::PCM);
    src_sp.open(output_full_sp, File::READ_ONLY);
    
    // the object should configure itself from the file
    //
    if (src_sp.sample_num_bytes_d != (Long)2) {
      return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
    }
    if (src_sp.num_channels_d != (Long)1) {
      return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
    }
    if (src_sp.file_format_d != SPHERE) {
      return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
    }
    
    
    // loop through 100 samples at a time
    //
    Vector<VectorFloat> data(1);
    Vector<VectorFloat> data_sp(1);
    long i = 0;
    while (src.getData(data(0), 0, i * 100l, 100) > 0) {

      if (!src_sp.getData(data_sp(0), 0, i * 100l, 100) > 0) {
	return Error::handle(name(), L"getData", Error::TEST,
			     __FILE__, __LINE__);
      }

      if (data_sp(0).ne(data(0))) {
	Long(i).debug(L"i=");
	data_sp(0).debug(L"Nist Sphere (PCM)");
	data(0).debug(L"raw");
	return Error::handle(name(), L"read-Nist-sphere(PCM)", Error::TEST,
			     __FILE__,    __LINE__);
      }
      i++;
    }

    src.close();
    src_sp.close();

    // the object should restore it's configuration
    //
    if (src_sp.sample_num_bytes_d != (Long)4) {
      return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
    }

    if (src_sp.file_format_d != SPHERE) {
      return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
    }
  }
  
  if (level_a >= Integral::BRIEF) {
    Console::decreaseIndention();
  }
#endif
  
  //---------------------------------------------------------------------------
  //
  // 6. print completion message
  //
  //---------------------------------------------------------------------------

  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }

  if (level_a > Integral::NONE) {
    String output(L"diagnostics passed for class ");
    output.concat(name());
    output.concat(L"\n");
    Console::put(output);
  }

  // exit gracefully
  //
  return true;
}
