#include                <iostream>
#include                <fstream>
#include                <math.h>
using namespace         std;
ifstream::pos_type      getPointer;
const char             *fname;
char                    str[60];

int                     Int_Sign4( int first, int second, int third, int forth  ) ;
int                     Int_USign4( int first, int second, int third, int forth  );
int                     Int_USign2( int first, int second );
int                     Int_Sign2( int first, int second );
double                  Extend_10(int X0,int X1,int X2,int X3,int X4,int X5,int X6,int X7,int X8,int X9 );


int                     main (int argc, char * const argv[]) 
{ int                   val , i , filesize ,numbframes, NumbChan ;
  double                extendVal, sampleRate, time ;
  std::ofstream ofile;
 if (argc !=2 )
{ printf("usage  ./aiff2txt  file2convert.aiff \n");
  exit(0);
}

  //fname =              "4.7uf.aiff";
  ofile.open("converted_aiff.txt",ios::out);
  int x=33;
  // ofile<<x;
 // ofile.close();

  fname =               argv[1];
  cout                  <<" "<< fname << "  " ;
  ofile             <<"filename = "<< fname << "  \n" ;

  ifstream              file (fname, ios::in|ios::binary|ios::ate);
  if                    (file.is_open())
{ getPointer =          file.tellg();  
  cout                  << "       file size is " << getPointer << " \n";
  ofile                << "file size = " << getPointer << " \n";
  filesize =             getPointer;   // cout << "       file size2 is " << filesize << " \n";
  file.seekg (          0, ios::beg);   // repositions get pointer to beginning
}

  cout                   << "ADDR  TYPE          VALUE   \n";
  ofile                << "ADDR  TYPE          VALUE   \n";
  getPointer =          file.tellg();  
  cout                  <<  getPointer << "     IFF_HEADER  ";
  ofile                <<  getPointer << "     IFF_HEADER  ";

  file.read(str,4);     str[4]= '\0';  
  cout                  <<"  " << str << " \n" ;
  ofile                <<"  " << str << " \n" ;

  
  getPointer =          file.tellg();  
  cout                  <<  getPointer << "     FILE_SIZE   ";
  ofile                <<  getPointer << "     FILE_SIZE   ";
  file.read(str,4);     
  val =                 Int_USign4( str[0], str[1], str[2], str[3]  );
  cout                  <<"  " << val << " \n" ;
  ofile                <<"  " << val << " \n" ;

  
  getPointer =          file.tellg();  
  cout                  <<  getPointer << "     TYPE_AIFF   ";
  ofile                <<  getPointer << "     TYPE_AIFF   ";

  file.read(str,4);     str[4]= '\0';  
  cout                  <<"  " << str << " \n" ;
  ofile                <<"  " << str << " \n" ;

  
  getPointer =          file.tellg();  
  cout                  <<  getPointer << "    COMMON_CHUNK";
  ofile                <<  getPointer << "    COMMON_CHUNK";

  file.read(str,4);     str[4]= '\0';  
  cout                  <<"  " << str << " \n" ;
  ofile                <<"  " << str << " \n" ;

  
  getPointer =          file.tellg();  
  cout                  <<  getPointer << "    CHUNK_SIZE  ";
  ofile                <<  getPointer << "    CHUNK_SIZE  ";

  file.read(str,4);     
  val =                 Int_USign4( str[0], str[1], str[2], str[3]  );
  cout                  <<"  " << val << " \n" ;
  ofile                <<"  " << val << " \n" ;

  
  getPointer =          file.tellg();  
  cout                  <<  getPointer << "    NUMB_CHAN   ";
  ofile                  <<  getPointer << "    NUMB_CHAN   ";

  file.read(str,2);     
  val =                 Int_USign2( str[0], str[1] );
  cout                   <<"  " << val << " \n" ;
  ofile                 <<"  " << val << " \n" ;

  NumbChan  =            val;
  
  getPointer =          file.tellg();  
  cout                  <<  getPointer << "    NUMB_FRAM   ";
  ofile                  <<  getPointer << "    NUMB_FRAM   ";

  file.read(str,4);     
  val =                 Int_USign4( str[0], str[1], str[2], str[3]);
  numbframes =          val;
  cout                  <<"  " << val << " \n" ;
  ofile                  <<"  " << val << " \n" ;


  getPointer =          file.tellg();  
  cout                  <<  getPointer << "    SAMP_SIZE   ";
  ofile                  <<  getPointer << "    SAMP_SIZE   ";

  file.read(str,2);     
  val =                 Int_USign2( str[0], str[1] );
  cout                  <<"  " << val << " \n" ;
  ofile                  <<"  " << val << " \n" ;

  
  getPointer =          file.tellg();  
  cout                  <<  getPointer << "    SAMP_RATE   ";
  ofile                  <<  getPointer << "    SAMP_RATE   ";

  file.read(str,10);      
  extendVal =            Extend_10(str[0],str[1],str[2],str[3],str[4],str[5],str[6],str[7],str[8],str[9] );
  cout                   <<"  " << extendVal << " \n" ;
  ofile                   <<"  " << extendVal << " \n" ;

  sampleRate =           extendVal; 
  
  getPointer =          file.tellg();  
  cout                  <<  getPointer << "    SSND_CHUNK  ";
  ofile                  <<  getPointer << "    SSND_CHUNK  ";

  file.read(str,4);     str[4]= '\0';  
  cout                  <<"  " << str << " \n" ;
  ofile                  <<"  " << str << " \n" ;

  
  getPointer =          file.tellg();  
  cout                  <<  getPointer << "    CHUNK_SIZE  ";
  ofile                  <<  getPointer << "    CHUNK_SIZE  ";

  file.read(str,4);     
  val =                 Int_USign4( str[0], str[1], str[2], str[3]);
  cout                  <<"  " << val << " \n" ;
  ofile                  <<"  " << val << " \n" ;

  
  getPointer =          file.tellg();  
  cout                  <<  getPointer << "    OFFSET      ";
  ofile                  <<  getPointer << "    OFFSET      ";

  file.read(str,4);     
  val =                 Int_USign4( str[0], str[1], str[2], str[3]);
  cout                  <<"  " << val << " \n" ;
  ofile                  <<"  " << val << " \n" ;

  
  getPointer =          file.tellg();  
  cout                  <<  getPointer << "    BLOCK_SIZE  ";
  ofile                  <<  getPointer << "    BLOCK_SIZE  ";

  file.read(str,4);     
  val =                 Int_USign4( str[0], str[1], str[2], str[3]);
  cout                   <<"  " << val << " \n" ;
  ofile                   <<"  " << val << " \n" ;

  
  // numbframes = 15;

  for                  (i=0; i< numbframes -4  ; i++) 
{ getPointer =          file.tellg();  
  file.read(str,2);     
  val =                 Int_Sign2( str[0], str[1] );

  time =                (double) i/ sampleRate;
//cout                  << time <<"  " << val  ;
  ofile                << time <<"  " << val  ;


  if                  ( NumbChan > 1 )
{ file.read(str,2);     
  val =                 Int_Sign2( str[0], str[1] );
//cout                  <<"  " << val  ;
  ofile                <<"  " << val  ;

}
//cout                  << " \n" ;
  ofile                << " \n" ;
  
}

  ofile.close();
  cout                  <<"Output is stored in <converted_aiff.txt>  \n" ;

    return 0;
}


double                Extend_10(int X0,int X1,int X2,int X3,int X4,int X5,int X6,int X7,int X8,int X9 )
{ if                  ( X0 <0 ) X0 =  X0+256;
  if                  ( X1 <0 ) X1 =  X1+256;
  if                  ( X2 <0 ) X2 =  X2+256;
  if                  ( X3 <0 ) X3 =  X3+256;
  if                  ( X4 <0 ) X4 =  X4+256;
  if                  ( X5 <0 ) X5 =  X5+256;
  if                  ( X6 <0 ) X6 =  X6+256;
  if                  ( X7 <0 ) X7 =  X7+256;
  if                  ( X8 <0 ) X8 =  X8+256;
  if                  ( X9 <0 ) X9 =  X9+256;
  int                 exp , i ,bit,testbit, scalebit;
  exp                 = (X0 & 127);         // mask = 01111111
  exp =               0;                    //cout << "  exp "<< exp <<" <<   \n" ; 
  for                 (i=1; i< 8  ; i++) 
{ bit =               (int) pow(2,15-i);
  exp =               exp + (X0 & bit); 
}
  for                 (i=0; i< 8  ; i++) 
{ bit =               (int) pow(2,7-i);
  exp =               exp + (X1 & bit); 
} exp                 = exp +1;  // add offset
  double              matval,matvalb , value;
  matval =            0;
  for                 (i=0; i< 8  ; i++) 
{ bit =                pow(2,7-i);
  scalebit =           pow(2,i+3);     
  testbit =           (X2 & bit);                                    
  matvalb =           (double) 8*(X2 & bit)/(bit*scalebit);    
  matval  =           matval + matvalb;                       
  matvalb =           (double) 8*(X3 & bit)/(256*bit*scalebit);  
  matval  =           matval + matvalb;                       
  matvalb =           (double) 8*(X4 & bit)/(256*256*bit*scalebit); 
  matval  =           matval + matvalb;                     
} value =             matval*pow(2,exp);
  return value;
}



int                   Int_Sign2( int first, int second )
{ int                 numb ;
  if                  ( second <0 ) second =  second+256;
  numb  =             256*first + second;
  return numb;
}

int                   Int_USign2( int first, int second )
{ int                 numb ;
  if                  ( first  <0 ) first  =  first+256;
  if                  ( second <0 ) second =  second+256;
  numb  =             256*first + second;
  return numb;
}


int                   Int_USign4( int first, int second, int third, int forth  )
{ int                 numb ;
  if                  ( first  <0 ) first  =  first+256;
  if                  ( second <0 ) second =  second+256;
  if                  ( third  <0 ) third  =  third +256;
  if                  ( forth  <0 ) forth  =  forth +256;
  numb  =             256*(256*(256*first + second)+third )+forth;
  return numb;
}


int                   Int_Sign4( int first, int second, int third, int forth  )
{ int                 numb ;
  if                  ( second <0 ) second =  second+256;
  if                  ( third  <0 ) third  =  third +256;
  if                  ( forth  <0 ) forth  =  forth +256;
  numb  =             256*(256*(256*first + second)+third )+forth;
 // cout << " " << first << " " << second<< " " << third<< " " << forth << " \n";
  return numb;
}


/*  
donsauer$ g++ -v aiff2txt.c -o aiff2txt
donsauer$ ./aiff2txt   0.1uf.aiff  
*/

