void sigFunc( short num, void *msg );

/*
 *      IMPLEMENTATION NOTES
 *
 *      Converting is achieved by interpolating the input samples in
 *      order to evaluate the represented continuous input slope at
 *      sample instances of the new rate (resampling). It is implemented
 *      as a polyphase FIR-filtering process (see reference). The rate
 *      conversion factor is determined by a rational factor. Its
 *      nominator and denominator are integers of almost arbitrary
 *      value, limited only by coefficient memory size.
 *
 *      General rate conversion formula:
 *
 *          out(n*Tout) = SUM in(m*Tin) * g((n*d/u-m)*Tin) * Tin
 *                    over all m
 *
 *      FIR-based rate conversion formula for polyphase processing:
 *
 *                        L-1
 *          out(n*Tout) = SUM in(A(i,n)*Tin) * g(B(i,n)*Tin) * Tin
 *                        i=0
 *
 *          A(i,n) = i - (L-1)/2 + [n*d/u]
 *                 = i - (L-1)/2 + [(n%u)*d/u] + [n/u]*d
 *          B(i,n) = n*d/u - [n*d/u] + (L-1)/2 - i
 *                 =  ((n%u)*d/u)%1  + (L-1)/2 - i
 *          Tout   = Tin * d/u
 *
 *        where:
 *          n,i         running integers
 *          out(t)      output signal sampled at t=n*Tout
 *          in(t)       input signal sampled in intervalls Tin
 *          u,d         up- and downsampling factor, integers
 *          g(t)        interpolating function
 *          L           FIR-length of realized g(t), integer
 *          /           float-division-operator
 *          %           float-modulo-operator
 *          []          integer-operator
 *
 *        note:
 *          (L-1)/2     in A(i,n) can be omitted as pure time shift yielding
 *                      a causal design with a delay of ((L-1)/2)*Tin.
 *          n%u         is a cyclic modulo-u counter clocked by out-rate
 *          [n/u]*d     is a d-increment counter, advanced when n%u resets
 *          B(i,n)*Tin  can take on L*u differnt values, at which g(t)
 *                      has to be sampled as a coefficient array
 *
 *      Interpolation function design:
 *
 *          The interpolation function design is based on a sinc-function
 *          windowed by a gaussian function. The former determines the
 *          cutoff frequency, the latter limits the necessary FIR-length by
 *          pushing the outer skirts of the resulting impulse response below
 *          a certain threshold fast enough. The drawback is a smoothed
 *          cutoff inducing some aliasing. Due to the symmetry of g(t) the
 *          group delay of the filtering process is contant (linear phase).
 *
 *          g(t) = 2*fgK*sinc(pi*2*fgK*t) * exp(-pi*(2*fgG*t)**2)
 *
 *        where:
 *          fgK         cutoff frequency of sinc function in f-domain
 *          fgG         key frequency of gaussian window in f-domain
 *                      reflecting the 6.82dB-down point
 *
 *        note:
 *          Taking fsin=1/Tin as the input sampling frequncy, it turns out
 *          that in conjunction with L, u and d only the ratios fgK/(fsin/2)
 *          and fgG/(fsin/2) specify the whole proces. Requiring fsin, fgK
 *          and fgG as input purposely keeps the notion of absolute
 *          frequencies.
 *
 *      Numerical design:
 *
 *          Samples are expected to be 16bit-signed integers, alternating
 *          left and right channel in case of stereo mode- The byte order
 *          per sample is selectable. FIR-filtering is implemented using
 *          32bit-signed integer arithmetic. Coefficients are scaled to
 *          find the output sample in the high word of accumulated FIR-sum.
 *
 *          Interpolation can lead to sample magnitudes exceeding the
 *          input maximum. Worst case is a full scale step function on the
 *          input. In this case the sinc-function exhibits an overshoot of
 *          2*9=18percent (Gibb's phaenomenon). In any case sample overflow
 *          can be avoided by a gain of 0.8.
 *
 *          If u=d=1 and if the input stream contains only a single sample,
 *          the whole length of the FIR-filter will be written to the output.
 *          In general the resulting output signal will be (L-1)*fsout/fsin
 *          samples longer than the input signal. The effect is that a
 *          finite input sequence is viewed as padded with zeros before the
 *          `beginning' and after the `end'.
 *
 *          The output lags ((L-1)/2)*Tin behind to implement g(t) as a
 *          causal system corresponding to a causal relationship of the
 *          discrete-time sequences in(m/fsin) and out(n/fsout) with
 *          resepect to a sequence time origin at t=n*Tin=m*Tout=0.
 *
 *
 *      REFERENCES
 *
 *          Crochiere, R. E., Rabiner, L. R.: "Multirate Digital Signal
 *          Processing", Prentice-Hall, Englewood Cliffs, New Jersey, 1983
 *
 *          Zwicker, E., Fastl, H.: "Psychoacoustics - Facts and Models",
 *          Springer-Verlag, Berlin, Heidelberg, New-York, Tokyo, 1990
 */

#define INCL_DOSPROCESS
#define INCL_DOS

#include <os2.h>
#include <math.h>
#include <stdio.h>
#include <io.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <process.h>
#include <sys\stat.h>

#include "mmioos2.h"
#include "..\..\..\units\common.src\bastypes.h"
#include "..\..\..\units\common.src\util.h"
#include "..\..\..\units\common.src\cfg_file.h"
#include "..\..\..\units\common.src\num2nam.h"
#include "..\..\common\source\global.h"
#include "..\..\common\source\texte.h"
#include "..\..\..\units\common.src\os.h"

/*
 *      adaptable defines and globals
 */

#define M_PI 3.14159265358979323846

#ifndef MAXUP
#define MAXUP           0x400           /* MAXUP*MAXLENGTH worst case malloc */
#endif

#ifndef MAXLENGTH
#define MAXLENGTH       0x400           /* max FIR length */
#endif

#define OUTBUFFSIZE     MAXLENGTH       /* fit >=MAXLENGHT samples */
#define INBUFFSIZE      (2*MAXLENGTH)   /* fit >=2*MAXLENGTH samples */
#define sqr(a)  ((a)*(a))

/*
 *      other globals
 */
double  g_ampli = 0.8;                  /* default gain, don't change */
int
        g_outfilehandle = 0,            /*  */
        g_firlen  = 0,                  /* FIR-length */
        g_up = 0,                       /* upsampling factor */
        g_down = 0                      /* downsampling factor */
;

LONG
        g_sin[INBUFFSIZE],              /* input buffer */
        g_sout[OUTBUFFSIZE],            /* output buffer */
        *g_coep                         /* coefficient array pointer */
;
double
        g_fsi =0.0,                          /* input sampling frequency */
        g_fgk =0.0,                          /* sinc-filter cutoff frequency */
        g_fgg =0.0                          /* gaussian window key frequency */
;                                       /* (6.8dB down freq. in f-domain) */

MMAUDIOHEADER mmAudHdr;

UCHAR reverse_byte[256]={
0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
};

/*
 * linear2alaw() - Convert a 16-bit linear alw value to 8-bit A-law
 *
 * linear2alaw() accepts an 16-bit integer and encodes it as A-law data.
 *
 *              Linear Input Code       Compressed Code
 *      ------------------------        ---------------
 *      0000000wxyza                    000wxyz
 *      0000001wxyza                    001wxyz
 *      000001wxyzab                    010wxyz
 *      00001wxyzabc                    011wxyz
 *      0001wxyzabcd                    100wxyz
 *      001wxyzabcde                    101wxyz
 *      01wxyzabcdef                    110wxyz
 *      1wxyzabcdefg                    111wxyz
 *
 */
UCHAR linear2alaw(long alw_val)  /* 2's complement (16-bit range) */
{
  long          mask = 0;
  long          seg = 0;
  unsigned char aval = 0;
  static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF,
                            0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};

  if (alw_val >= 0) {
    mask = 0xD5;                /* sign (7th) bit = 1 */
  } else {
    mask = 0x55;                /* sign bit = 0 */
    alw_val = -alw_val;
  }

  if(alw_val<0x7ff8)
    alw_val+=8;

  if(alw_val<0x10)
    mask = 0xD5;

        /* Convert the scaled magnitude to segment number. */

  for (seg = 0; seg < 8; seg++) {
    if (alw_val <= seg_end[seg])
      break;
    }

        /* Combine the sign, segment, and quantization bits. */

  if (seg >= 8)         /* out of range, return maximum value. */
    return (0x7F ^ mask);
  else {
    aval = seg << 4;
    if (seg < 2)
      aval |= (alw_val >> 4) & 0xf;
    else
      aval |= (alw_val >> (seg + 3)) & 0xf;
    return (aval ^ mask);
  }
}

/*
 *      evaluate sinc(x) = sin(x)/x safely
 */
double sinc(double x) {
  return(fabs(x) < 1E-50 ? 1. : sin(fmod(x,2*M_PI))/x);
}

/*
 *      evaluate interpolation function g(t) at t
 *      integral of g(t) over all times is expected to be one
 */
double interpol_func(double t, double fgk, double fgg) {
  return (2*fgk*sinc(M_PI*2*fgk*t)*exp(-M_PI*sqr(2*fgg*t)));
}

/*
 *      evaluate coefficient from i, q=n%u by sampling interpolation function
 *      and scale it for integer multiplication used by FIR-filtering
 */
LONG coefficient(long i, long q, long firlen, double fgk, double fgg, double fsi,
                 long up, long down, double amp) {
  return(
    (int)(0x10000 * amp *
       interpol_func(
         (fmod(q*down/(double)up,1.) + (firlen-1)/2 - i) / fsi,
         fgk,
         fgg
       ) / fsi
    )
  );
}

/*
 *      transfer n LONGs from  s to d
 */
void transfer_int(LONG *s, LONG *d, long n) {
  LONG *e;

  if (n < 1)
    return;
  e = d + n;
  while (d != e)
    *d++ = *s++;
}

/*
 *      zerofill n LONGs from s
 */
void zerofill(LONG *s, long n) {
  LONG *e;

  if (n < 1)
    return;
  e = s + n;
  while (s != e)
    *s++ = 0;
}

/*
 *      convert buffer of n samples to LONGs
 */
void bsample_to_int(void *buff, long n) {
  UCHAR *s;
  LONG *d;

  if (n < 1)
    return;
  s = (UCHAR*)buff + n;
  d = (LONG*)buff + n;
  while (s != buff) {
    *--d = ((LONG)(*--s)-128L)<<8;
  }
}

/*
 *      convert buffer of n samples to LONGs
 */
void bsample2_to_int(void *buff, long n) {
  UCHAR *s;
  LONG *d;

  if (n < 1)
    return;
  s = (UCHAR*)buff + n*2;
  d = (LONG*)buff + n;
  while (s != buff) {
    *--d = (((LONG)(*--s)-128L)<<7)+(((LONG)(*--s)-128L)<<7);
  }
}

/*
 *      convert buffer of n samples to LONGs
 */
void sample_to_int(void *buff, long n) {
  short *s;
  LONG *d;

  if (n < 1)
    return;
  s = (short*)buff + n;
  d = (LONG*)buff + n;
  while (s != buff) {
    *--d = (LONG)(*--s);
  }
}

/*
 *      convert buffer of n samples to LONGs
 */
void sample2_to_int(void *buff, long n) {
  short *s;
  LONG *d;

  if (n < 1)
    return;
  s = (short*)buff + n*2;
  d = (LONG*)buff + n;
  while (s != buff) {
    *--d = ((LONG)(*--s)+(LONG)(*--s))>>1;
  }
}

/*
 *      convert buffer of n LONGs to samples
 */
void int_to_sample(short *buff, long n) {
  short *s, *e;
  UCHAR *d;

  if (n < 1)
    return;
  s = buff;
  d = (UCHAR*)buff;
  e = buff + n*2;
  while (s != e) {
    s++;
    *d++ = reverse_byte[linear2alaw(*s++)];
  }
}

/*
 *      convert buffer of n LONGs to samples
 */
void intlo_to_sample(short *buff, long n) {
  short *s, *e;
  UCHAR *d;

  if (n < 1)
    return;
  s = buff;
  d = (UCHAR*)buff;
  e = buff + n*2;
  while (s != e) {
    *d++ = reverse_byte[linear2alaw(*s++)];
    s++;
  }
}

/*
 *      FIR-routines,
 *      this is where we need all the MIPS
 */
void fir(register LONG *inp, register LONG *coep, long firlen, LONG *outp) {
  register LONG akku = 0, *endp;
  long n1 = (firlen / 8) * 8, n0 = firlen % 8;

  endp = coep + n1;
  while (coep != endp) {
    akku += *inp++ * *coep++;
    akku += *inp++ * *coep++;
    akku += *inp++ * *coep++;
    akku += *inp++ * *coep++;
    akku += *inp++ * *coep++;
    akku += *inp++ * *coep++;
    akku += *inp++ * *coep++;
    akku += *inp++ * *coep++;
  }

  endp = coep + n0;
  while (coep != endp) {
    akku += *inp++ * *coep++;
  }
  *outp = akku;
}

/*
 *      filtering from input buffer to output buffer;
 *      returns number of processed samples in output buffer:
 *      if it is not equal to output buffer size,
 *      the input buffer is expected to be refilled upon entry, so that
 *      the last firlen numbers of the old input buffer are
 *      the first firlen numbers of the new input buffer;
 *      if it is equal to output buffer size, the output buffer
 *      is full and is expected to be stowed away;
 *
 */
long filtering_on_buffers(LONG *inp, long insize, LONG *outp, long outsize,
                         LONG *coep, long firlen, long up, long down) {
  static long inbaseidx = 0, inoffset = 0, cycctr = 0, outidx = 0;

  for (;;) {
    inoffset = (cycctr * down)/up;
    if ((inbaseidx + inoffset + firlen) > insize) {
      inbaseidx -= insize - firlen + 1;
      return(outidx);
    }
    fir(inp + inoffset + inbaseidx,
       coep + cycctr * firlen,
       firlen, outp + outidx++);
    cycctr++;
    if (!(cycctr %= up))
      inbaseidx += down;
    if (!(outidx %= outsize))
      return(outsize);
  }
}

/*
 *      read and convert input sample format to integer
 */
long intread(HMMIO hmmioSrc, void *buff, long n, long Bits, long Channels) {
  long rd = 0;

 if(Channels==2) {
  if(Bits==8) {
    if ((rd = mmioRead (hmmioSrc, buff, n*2)) <= 0)
      return(rd);
    bsample2_to_int(buff,n);
    return(rd/2);
  } else {
    if ((rd = mmioRead (hmmioSrc, buff, n*sizeof(short)*2)) <= 0)
      return(rd);
    sample2_to_int(buff,n);
    return(rd/sizeof(short)/2);
  }
 } else {
  if(Bits==8) {
    if ((rd = mmioRead (hmmioSrc, buff, n)) <= 0)
      return(rd);
    bsample_to_int(buff,n);
    return(rd);
  } else {
    if ((rd = mmioRead (hmmioSrc, buff, n*sizeof(short))) <= 0)
      return(rd);
    sample_to_int(buff,n);
    return(rd/sizeof(short));
  }
 }
}

/*
 *      do some conversion jobs and write
 */
long intwrite(long hd, LONG *buff, long n) {
  long written = 0;

  int_to_sample((short*)buff, n);
  if ((written = write(g_outfilehandle, buff, n)) <= 0)
    return(written);
  return(written);
}

/*
 *      do some conversion jobs and write
 */
long intlowrite(long hd, LONG *buff, long n) {
  long written = 0;

  intlo_to_sample((short*)buff, n);
  if ((written = write(g_outfilehandle, buff, n)) <= 0)
    return(written);
  return(written);
}

/*
 *      set up coefficient array
 */
void make_coe(void) {
  long i = 0, q =0;

  for (i = 0; i < g_firlen; i++) {
    for (q = 0; q < g_up; q++) {
      g_coep[q * g_firlen + i] = coefficient(i, q, g_firlen,
        g_fgk, g_fgg, g_fsi, g_up, g_down, g_ampli);
    }
  }
}


void comp_para(void) {
  long u = 0,d=0;
  double fin1=0.0,fdiff=0.0;

  fdiff=HUGE_VAL;

  for(u=1;u<=1024;u++) {
    d=(g_fsi*u)/8000.;
    fin1=(8000.*d)/u;
    if(fdiff>fabs(g_fsi-fin1)) {
      fdiff=fabs(g_fsi-fin1);
      g_up=u;
      g_down=d;
    }
    d++;
    fin1=(8000.*d)/u;
    if(fdiff>fabs(g_fsi-fin1)) {
      fdiff=fabs(g_fsi-fin1);
      g_up=u;
      g_down=d;
    }
    if(fdiff==0.)
      break;
  }

  if (g_up >= g_down) { /* upsampling */
    g_fgg = g_fsi * 0.0116;
    g_fgk = g_fsi * 0.461;
    g_firlen = 162;
  } else {      /* downsampling */
    g_fgg = (g_up * g_fsi * 0.0116)/g_down;
    g_fgk = (g_up * g_fsi * 0.461)/g_down;
    g_firlen = (162 * g_down)/g_up;
  }
}

/*
 *      main
 */

short wav2alw(char *InName)
{
  long insize = 0, outsize = 0, skirtlen=0;
  MMIOINFO      mmioinfoSource;
  unsigned long         ulAudioHeaderLength=0;
  HMMIO         hmmioSource;
  unsigned long         ulBytesRead=0;
  LONG          rc=0;
  char          OutName[300];
  char          *help;
  char          helpstr[300];

  memset (g_sin ,0,sizeof(LONG)*INBUFFSIZE);
  memset (g_sout,0,sizeof(LONG)*OUTBUFFSIZE);

  if (InName[0] == '*') return (-200);
  if (!util_file_exist(InName)) {
     sprintf (helpstr,STR_NOT_FOUND,InName);
     sigFunc (1,helpstr);
     return (-100);
  }

  if (!strstr(InName,".wav")) return (-101);

  strcpy (OutName,InName);

  help = strstr(OutName,".wav");
  *(++help) = 'a';
  *(++help) = 'l';
  *(++help) = 'w';

  strcpy (OutName,util_strip_path(OutName));

  if (util_file_exist(OutName)) {
     if (util_file_age(InName) <= util_file_age(OutName)) return (-102);
  }

  /*******************************/
  /* Set up/open the SOURCE file */
  /*******************************/

  memset (&mmioinfoSource, 0L, sizeof (MMIOINFO));

  mmioinfoSource.ulTranslate = MMIO_TRANSLATEHEADER | MMIO_TRANSLATEDATA;

  hmmioSource = mmioOpen (InName, &mmioinfoSource,
                          MMIO_READ | MMIO_DENYWRITE);
  if (!hmmioSource) {
//    perror(InName);
    return (2);
  }

  /****************************/
  /* Obtain the SOURCE HEADER */
  /****************************/
  mmioQueryHeaderLength (hmmioSource, (PLONG)&ulAudioHeaderLength, 0L, 0L);
  if (ulAudioHeaderLength != sizeof (MMAUDIOHEADER)) {
    /* We have a problem.....possibly incompatible versions */
    mmioClose (hmmioSource, 0L);
//    perror(InName);
    return (4);
  }

  rc = (LONG)mmioGetHeader (hmmioSource, &mmAudHdr,
               (LONG)sizeof (MMAUDIOHEADER), (PLONG)&ulBytesRead,
               0L, 0L);

  if (rc != MMIO_SUCCESS) {
     /* Header unavailable */
    mmioClose (hmmioSource, 0L);
//    perror(InName);
    return (4);
  }

//  printf("\nType of wave format: %d",mmAudHdr.mmXWAVHeader.WAVEHeader.usFormatTag);
//  printf("\nNumber of channels: %d",mmAudHdr.mmXWAVHeader.WAVEHeader.usChannels);
//  printf("\nSampling rate: %ld",mmAudHdr.mmXWAVHeader.WAVEHeader.ulSamplesPerSec);
//  printf("\nAvg bytes per sec: %ld",mmAudHdr.mmXWAVHeader.WAVEHeader.ulAvgBytesPerSec);
//  printf("\nBlock Alignment in bytes: %d",mmAudHdr.mmXWAVHeader.WAVEHeader.usBlockAlign);
//  printf("\nBits per sample: %d",mmAudHdr.mmXWAVHeader.WAVEHeader.usBitsPerSample);

  g_outfilehandle=open(OutName,O_CREAT|O_BINARY|O_TRUNC|O_RDWR,S_IWRITE|S_IREAD);
  if (g_outfilehandle==-1) {
//    perror(OutName);
    mmioClose (hmmioSource, 0L);
    return(-1);
  }

  if(mmAudHdr.mmXWAVHeader.WAVEHeader.ulSamplesPerSec < 7984 ||
     mmAudHdr.mmXWAVHeader.WAVEHeader.ulSamplesPerSec > 8016) {

    g_fsi=mmAudHdr.mmXWAVHeader.WAVEHeader.ulSamplesPerSec;

    comp_para();

    if ((g_coep = (LONG*)malloc(g_firlen * g_up * sizeof(int))) == NULL) {
//        fprintf(stderr, "cannot allocate coefficient memory\n");
      return (-2);
    }
    make_coe();
    skirtlen = g_firlen - 1;
    zerofill(g_sin, skirtlen);
    do {
      insize = intread(hmmioSource, g_sin + skirtlen,
        INBUFFSIZE - skirtlen,
        mmAudHdr.mmXWAVHeader.WAVEHeader.usBitsPerSample,
        mmAudHdr.mmXWAVHeader.WAVEHeader.usChannels);
      if (insize < 0 || insize > INBUFFSIZE - skirtlen) {
//        perror(InName);
        close(g_outfilehandle);
        free(g_coep);
        return (-3);
      }
      for (;;) {
        outsize = filtering_on_buffers(g_sin, skirtlen + insize,
            g_sout, OUTBUFFSIZE, g_coep, g_firlen, g_up, g_down);
        if (outsize != OUTBUFFSIZE) {
          transfer_int(g_sin + insize, g_sin, skirtlen);
          break;
        }
        if (intwrite(g_outfilehandle, g_sout, outsize) != outsize) {
//          perror(OutName);
          free(g_coep);
          return (-4);
        }
      };
    } while (insize > 0);
    zerofill(g_sin + skirtlen, skirtlen);
    do {
      outsize = filtering_on_buffers(g_sin, skirtlen + skirtlen,
          g_sout, OUTBUFFSIZE, g_coep, g_firlen, g_up, g_down);
      if (intwrite(g_outfilehandle, g_sout, outsize) != outsize) {
//        perror(OutName);
        free(g_coep);
        return (-5);
      }
    } while (outsize == OUTBUFFSIZE);

    free(g_coep);

  } else { /* Input is 8000Sample/s no rate conversion */
    do {
      insize = intread(hmmioSource, g_sin,
        INBUFFSIZE,
        mmAudHdr.mmXWAVHeader.WAVEHeader.usBitsPerSample,
        mmAudHdr.mmXWAVHeader.WAVEHeader.usChannels);
      if (insize < 0 || insize > INBUFFSIZE) {
//        perror(InName);
        close(g_outfilehandle);
        return (-6);
      }
      if (intlowrite(g_outfilehandle, g_sin, insize) != insize) {
//        perror(OutName);
        return (-7);
      }
    } while (insize > 0);
  }

  if (close(g_outfilehandle)) {
//    perror(OutName);
    return (-8);
  }

  mmioClose (hmmioSource, 0L);

  return 0;
}

/*******************************************************************/

short runflag = 0;


void convert_all_lookup (char *filename)
{
  FILE *namedat;
  char str [300];
  char help[300];
  char *strptr;

  namedat = fopen (filename,"r");
  if (namedat) {
     while (fgets(str,200,namedat)) {
        if((str[0] != '#') && (strchr(str,'|'))) {
           strptr = &str[0];
           strptr = strchr(strptr,'|');
           strptr++;
           strptr = strchr(strptr,'|');
           strptr++;
           *strchr(strptr,'|') = 0;

           strcpy (help,check_time(strptr));
           wav2alw (help);
        }
     }
     fclose (namedat);
  }
}

void wav2alw_all (void)
{
  char help[200];

  convert_all_lookup (NAMFILE);
  convert_all_lookup (PRTFILE);

  config_file_read_string(STD_CFG_FILE,WELCOME_WAVE ,help,WELCOME_WAVE_DEF);
  strcpy (help,check_time(help));
  wav2alw (help);

  config_file_read_string(STD_CFG_FILE,RINGRING_WAVE,help,RINGRING_WAVE_DEF);
  strcpy (help,check_time(help));
  wav2alw (help);
}

void _Optlink convert_all (void *arglist)
{
   while (runflag) OsSleep (250);
   runflag++; sigFunc( 7, &runflag);
      wav2alw_all();
   runflag--; sigFunc( 7, &runflag);
};

void _Optlink convert (void *filename)
{
   while (runflag) OsSleep (250);
   runflag++; sigFunc( 7, &runflag);
   wav2alw (filename);
   runflag--; sigFunc( 7, &runflag);
};

void wav2alw_convert_all  (void)
{
  _beginthread (convert_all, NULL, os2_stack_of_thread, NULL);
//convert_all(NULL);
};

void wav2alw_convert      (char * filename)
{
  _beginthread (convert, NULL, os2_stack_of_thread, (void *)filename);
//convert(filename);
};

short  wav2alw_convert_runs (void)
{
  return (runflag);
};


