/*
** quake2wav converts data read from raw data files as generated by the 
** 8 channel A/D converter into a wav file which can be further processed by
** appropriate audio tools. The output is scaled so that the maximum amplitude
** is +1 or -1, so be somewhat careful when listening to the raw wav file.
**
** DEC-2002, B. Ulmann fecit.
*/

#include <stdio.h>      
#include <stdlib.h>
#include <string.h>

#define STRING_LENGTH 133
#define MAX_DATA 4194304 /* Maximum number of samples to be processed */

int main (int argc, char **argv)
{
  int i, j,
      channel,
      counter = 0,
      file_len,
      sample_rate,
      sample_rate_times_2;
  
  float value,
      maximum = 0.,
      data [MAX_DATA];

  char line [STRING_LENGTH],
    *row;

  FILE *input_handle, *output_handle;

  if (argc < 5) /* Wrong number of arguments, print usage description */
  {
    printf ("Usage: seismo_wav <sample_rate> <channel> <file1> [<file2]... \
<output_file>\n");
    return -1;
  }

  printf ("Opening output file >>%s<<\n", argv [argc - 1]);
  if (!(output_handle = fopen (argv [argc - 1], "w")))
  {
    printf ("Unable to open output file!\n");
    return -2;
  }

  printf ("Using sample rate %d. Converting channel %d.\n", 
          sample_rate = atoi (argv [1]),
          channel = atoi (argv [2]));

  for (i = 3; i < argc - 1; i++)
  {
    printf ("Processing file >>%s<<\n", argv [i]);
    if (!(input_handle = fopen (argv [i], "r")))
    {
      printf ("Unable to open input file!\n");
      return -3;
    }

    fgets (line, STRING_LENGTH, input_handle);  /* Skip first line */

    fgets (line, STRING_LENGTH, input_handle);
    for (;;)
    {
      row = strtok (line, " ");                 /* Get first token from line */
      for (j = 0; row && j < channel; j++)      /* Skip channels if desired */
        row = strtok (0, " ");

      if (!row)
      {
        printf ("Unexpected end of line - channel number too large? Abort!\n");
        return -1;
      }

      sscanf (row, "%f", &value);

      if ((data [counter++] = value) > maximum) /* Determine new maximum */
        maximum = value;

      fgets (line, STRING_LENGTH, input_handle);
      if (feof (input_handle))
        break;
    }

    fclose (input_handle);
  }

  printf ("%d files with %d lines of data processed\n\
Maximum amplitude: %f\nWriting file >>%s<<\n",
          argc - 4, counter, maximum, argv [argc - 1]);

  /* Write output file */

  file_len = counter + 36;
  sample_rate_times_2 = sample_rate << 1;

  fprintf (output_handle, "\
RIFF%c%c%c%cWAVEfmt%c\
%c%c%c%c\
%c%c%c%c\
%c%c%c%c\
%c%c%c%c\
%c%c%c%cdata\
%c%c%c%c",
	   (char) (file_len & 0xff),
	   (char) ((file_len >> 8) & 0xff),
           (char) ((file_len >> 16) & 0xff),
	   (char) (file_len >> 24),
	   0x20, 
	   (char) 0x10, (char) 0, (char) 0, (char) 0,
	   (char) 1, (char) 0, (char) 1, (char) 0,
	   (char) (sample_rate & 0xff),
	   (char) ((sample_rate >> 8) & 0xff),
	   (char) ((sample_rate >> 16) & 0xff),
	   (char) (sample_rate >> 24),
	   (char) (sample_rate_times_2 & 0xff),
	   (char) ((sample_rate_times_2 >> 8) & 0xff),
	   (char) ((sample_rate_times_2 >> 16) & 0xff),
	   (char) (sample_rate_times_2 >> 24),
	   (char) 2, (char) 0, (char) 0x10, (char) 0,
	   (char) (counter & 0xff),
	   (char) ((counter >> 8) & 0xff),
	   (char) ((counter >> 16) & 0xff),
	   (char) (counter >> 24));

  for (i = 0; i < counter; i++)
  {
      j = (int) (32767. * data [i] / maximum);
      fprintf (output_handle, "%c%c", j & 0xff, j >> 8);
  }

  fclose (output_handle);
  printf ("%d samples written.\n", counter);
  return 0;
}
