/*****************************************************************************
** FILE IDENTIFICATION
**
**   Name:          wdq2wav.h
**   Purpose:       Header file for wdq2wav.cpp
**   Programmer:    Kevin Rosenberg <kevin@rosenberg.net>
**   Date Started:  Jan 2003
**
**  Copyright (c) 2003 Kevin Rosenberg
**
**  $Id$
**
**  This program is free software; you can redistribute it and/or modify
**  it under the terms of the GNU General Public License (version 2) as
**  published by the Free Software Foundation.
**
**  This program is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**  GNU General Public License for more details.
**
**  You should have received a copy of the GNU General Public License
**  along with this program; if not, write to the Free Software
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
******************************************************************************/

#include <stdio.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <sstream>
#include <ctime>
#include <fcntl.h>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef _WIN32
#include <io.h>
#include <getopt.h>
#else
#include <unistd.h>
#endif

#ifdef __linux__
#include <endian.h>
#if __BYTE_ORDER == __BIG_ENDIAN
#define WORDS_BIG_ENDIAN 1
#endif
#endif

extern const char* g_szIdStr;
extern bool g_quiet;
extern bool g_verbose;
extern bool g_debug;

#define MAX_INPUT_STR 256

void error_msg (const char *msg);
void info_msg (const char *msg);
void info_msg_sans_newline (const char *msg);

bool wdq2wav (const char* wdq_fname, const int channel, const char *wav_fname, bool play);

class WindaqFile
{
public:
  WindaqFile (const char* fname);
  ~WindaqFile ();
  bool ReadHeader();

  bool m_valid;
  std::string m_error;
  int m_fd;
  bool m_bLegacy_format;
  bool m_bHires;
  int m_nMaxChannels;
  int m_nChannels;
  unsigned long int m_nSamples;
  double m_sample_rate;
  std::string m_strFile;
  unsigned int m_sr_denom, m_sr_numer;
  unsigned short int m_nHeader_bytes, m_channel_offset, m_nBytes_channel_header;
  unsigned int m_nData_bytes;
  unsigned int m_time_acq_start;
  unsigned int m_time_acq_stop;
  double m_time_between_channel_samples;

  bool any_packed_channels();
  bool is_channel_packed(int iChannel);
};

class WindaqChannel
{
public:
  WindaqFile& r_wdq;
  signed short int *m_data;
  double m_slope;
  double m_intercept;
  unsigned int m_channel;
  bool m_valid;
  std::string m_units;
  signed short int m_min_raw_data;
  signed short int m_max_raw_data;
  double m_max_scaled_data;
  double m_min_scaled_data;
  double m_raw_mean;

  WindaqChannel (WindaqFile& wdq, const int channel);
  ~WindaqChannel ();
  double raw2measured(signed short int raw) const { return (raw * m_slope) + m_intercept; }

 private:
  bool read_channel_data();
};


class WavFile
{
 public:
  bool m_valid;
  signed short int* m_data;
  unsigned long int m_nSamples;
  std::string m_strFile;
  int m_fd;
  double m_rate;
  unsigned int m_nChannels;
  unsigned int m_nBitsPerSample;
  unsigned int m_nBytesPerSample;
  unsigned long int m_nHeaderBytes;
  long int m_nDataBytes;
  long int m_nFileBytes;

  WavFile (WindaqChannel& wdq_channel, const char* fname);
  ~WavFile ();

  bool WriteFile ();

  bool Play();

 private:
  bool fill_header();
};

template<class T>
inline T nearest (double x)
{
  return (x > 0 ?
          static_cast<T>(x+0.5) : static_cast<T>(x-0.5));
}
