// file: sig_read_1.cc
//

// isip include files
//
#include "Signal.h"
#include "signal_constants.h"

// method: read_cc
//
// arguments:
//   char_1*& in (input) input raw data
//   float_8*& data: (output) portion of the signal to output. this memory
//                   is allocated externally
//   int_4 start_samp: (input) beginning point of the desired data
//   int_4 end_samp: : (input) end point of the desired data
//   int_4& num_samples: : (output) number of samples read
//
// return: logical_1 indicating status
//
// this method gets the desired time window. if the start sample is less than
// zero, then the start of the data is at index 0. if the end time is greater
// than the end of the file, then the end sample is set to the end of the file.
// if the end sample is less than the start sample, then an error is returned.
//
logical_1 Signal::read_cc(char*& in_a, float_8*& data_a,
			  int_4 start_samp_a, int_4 end_samp_a,
			  int_4 channel_a, int_4& num_samples_a) {

  // zero out the number of samples read
  //
  num_samples_a = 0;
  
  // make sure that the file is open
  //
  if (in_a == NULL) {

    // return with error
    //
    error_handler_cc((char_1*)"read_cc", (char_1*)"signal file is not open");

    return ISIP_FALSE;
  }

  // make sure that the data pointer is null, else error
  //
  if (data_a == (float_8*)NULL) {

    // return with error
    //
    error_handler_cc((char_1*)"read_cc", (char_1*)"data is not allocated");
    return ISIP_FALSE;
  }

  // determine the end time and check against the end of file
  //
  if (end_samp_a > (file_size_d / (num_chans_d * num_bytes_d))) {

    // set the end time to the end of file time
    //
    end_samp_a = (file_size_d / (num_chans_d * num_bytes_d));
  }

  // make sure that the end and start times are within bounds
  //
  if (end_samp_a < start_samp_a) {

    // return with error
    //
    return ISIP_FALSE;
  }

  // test the bounds of the start and end time
  //
  if (start_samp_a < 0) {

    // set start sample to 0
    //
    start_samp_a = (int_4)0;
  }

  // compute the number of samples to be obtained
  //
  num_samples_a = end_samp_a - start_samp_a;

  // allocate memory for the data and memory for reading in the data
  //
  char_1* in_data;
  //= new char_1[num_samples_a * num_chans_d * num_bytes_d];
  
  // seek to the starting point in the data
  //
  in_data = (char_1*) in_a + start_samp_a * num_bytes_d * num_chans_d;

  // read the data into the data buffer
  //
  int_4 samples_read = file_size_d - start_samp_a * num_chans_d * num_bytes_d;

  // check that the number of samples read is correct
  //
  if (samples_read < num_samples_a) {

    fprintf(stdout, "samples_read = %d\n", (int)samples_read);
    fflush(stdout);
    
    // return with error
    //
    error_handler_cc((char_1*)"read_cc",
		     (char_1*)"could not read all samples");
    return ISIP_FALSE;
  }

  // swap bytes if necessary
  //
  if (swap_byte_flag_d == ISIP_TRUE) {

    // loop over all two-byte sequences and swap bytes
    //
    // determine how many times through the loop we should go
    //
    int_4 loop_its = (num_samples_a * num_bytes_d * num_chans_d) / (int_4)2;

    // set a pointer to the beginning of the buffer
    //
    char_1* temp = in_data;
    for (int_4 i = 0; i < loop_its; i++) {
      char_1 samp = temp[0];
      temp[0] = temp[1];
      temp[1] = samp;
      temp += 2;
    }
  }

  // loop over all data and convert it to floating point values
  //
  int_4 loop_its = num_samples_a * num_chans_d;
  int_4 sample_val = 0;
  for (int_4 i = 0; i < loop_its; i++) {

    // compute the sample value
    //
    if (num_bytes_d == (int_4)2) {
      sample_val = *((short*)(in_data +
			      (i * num_chans_d + channel_a) * num_bytes_d));
    }
    else if (num_bytes_d == (int_4)4) {
      sample_val = *((int_4*)(in_data +
			     (i * num_chans_d + channel_a) * num_bytes_d));
    }

    else {

      // free memory
      //
      delete [] in_data;

      // return with error
      //
      error_handler_cc((char_1*)"read_cc",
		       (char_1*)"number of bytes per sample is invalid");
      return ISIP_FALSE;
    }
    
    // assign the value of this sample
    //
    data_a[i] = (float_8)sample_val;
  }

  // delete memory and clean up
  //
  //  delete [] in_data;
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
