#include <io.h>
#include <fcntl.h>
#include <share.h>
#include <stdlib.h>
#include <string.h>
#include <sys\stat.h>
#include <i86.h>
#include <conio.h>
#include <stdio.h>

typedef unsigned char byte;
typedef unsigned short int word;
typedef short int word_s;
typedef unsigned long dword;

char NameWAV[] = "wav.rs";

#define SB_HALF_BUFSIZE 2048
#define SB_BUFSIZE (SB_HALF_BUFSIZE<<1)

//============= SB ==============
word SbIRQ;
word SbIOaddr;
word SbType;
word SbDMAchan;
char *SB_buffer;
char *glob_DATE=0, SB_Installed = 0;
word SB_Dos_header;
char Type_Data[] = { {1}, {3}, {2}, {4} };
char STEREO=0;
char part=0;
//============= DMA =============
word DMA_complete;
word IntNum;
void far *OldIRQ;
word dma_errno;

int to_move;
long index;
long length;
int  SB_complete=1;

word page_table[] = { {0x87},{0x83},{0x81},{0x82} };

// Types of Sound Blaster Cards
#define  SB15   1
#define  SBPro  2
#define  SB20   3
#define  SB16   4

// Defines for Sound Blaster and Sound Blaster Pro IO address
#define  LEFT_FM_STATUS    0     // Pro only
#define  LEFT_FM_ADDRESS   0     // Pro only
#define  LEFT_FM_DATA      1     // Pro only
#define  RIGHT_FM_STATUS   2     // Pro only
#define  RIGHT_FM_ADDRESS  2     // Pro only
#define  RIGHT_FM_DATA     3     // Pro only
#define  MIXER_ADDRESS     4     // Pro only
#define  MIXER_DATA        5     // Pro only
#define  DSP_RESET         6
#define  FM_STATUS         8
#define  FM_ADDRESS        8
#define  FM_DATA           9
#define  DSP_READ_DATA     0xA
#define  DSP_WRITE_DATA    0xC
#define  DSP_WRITE_STATUS  0xC
#define  DSP_DATA_AVAIL    0xE
#define  CD_ROM_DATA       0x10  // Pro only
#define  CD_ROM_STATUS     0x11  // Pro only
#define  CD_ROM_RESET      0x12  // Pro only
#define  CD_ROM_ENABLE     0x13  // Pro only

// DSP Commands
#define  DIRECT_8_BIT_DAC       0x10
#define  DMA_8_BIT_DAC          0x14
#define  DMA_2_BIT_DAC          0x16
#define  DMA_2_BIT_REF_DAC      0x17
#define  AutoInitStart          0x1C
#define  DIRECT_ADC             0x20
#define  DMA_ADC                0x24
#define  MIDI_READ_POLL         0x30
#define  MIDI_READ_IRQ          0x31
#define  MIDI_WRITE_POLL        0x38
#define  TIME_CONSTANT          0x40
#define  DMA_8_BIT_DAC_HI_INIT  0x48        // for high-speed SB Pro transfers
#define  DMA_4_BIT_DAC          0x74
#define  DMA_4_BIT_REF_DAC      0x75
#define  DMA_26_BIT_DAC         0x76
#define  DMA_26_BIT_REF_DAC     0x77
#define  DMA_8_BIT_DAC_HI_START 0x91        // for high-speed SB Pro transfers
#define  DMA_8_BIT_ADC_HI_START 0x99        // for high-speed SB Pro transfers
#define  HALT_DMA               0xD0
#define  CONTINUE_DMA           0xD4
#define  SPEAKER_ON             0xD1
#define  SPEAKER_OFF            0xD3
#define  AutoInit_OFF           0xDA
#define  DSP_ID                 0xE0
#define  DSP_VER                0xE1
#define  DSP_COPYRIGHT          0xE3
#define  INT_REQUEST            0xF2
#define  MDAC1                  0x61
#define  MDAC2                  0x62
#define  MDAC3                  0x63
#define  MDAC4                  0x64
#define  MDAC5                  0x65
#define  MDAC6                  0x66
#define  MDAC7                  0x67

//DMA
#define  DMA_MASK   0xA     //DMAC mask (write-only)
#define  MODE       0xB     //DMAC mode (read/write)
#define  RESET_CMD  0x4     // DMA_MASK reset
#define  READ_CMD   0x48    // read (from memory) mode  [out to bus]
#define  READ_CMD1  0x58    // read (from memory) mode  [out to bus]
#define  WRITE_CMD  0x44    // write (to memory) mode   [in from bus]
#define  WRITE_CMD1 0x54    // write (to memory) mode   [in from bus]
#define  Byte_Ptr   0xC     // byte pointer flip-flop

//---------------------- WAV ------------------------
#define WAVE_FORMAT_PCM 1

#pragma pack(2)

typedef struct {
/* File header */
  char riff[4];
  long filesize;
  char rifftype[4];
} RiffHeader;

typedef struct {
  char chunk_id[4];
  long chunksize;
} Chunk;

typedef struct {
  short wFormatTag;
  short nChannels;
  long nSamplesPerSec;
  long nAvgBytesPerSec;
  short nBlockAlign;
  short wBitsPerSample;
} WAVEFORMAT;

typedef struct {
        char     id[10];                /* Library ID string           */
        char     copyright[50];         /* Copyright notice            */
        word     version;               /* pcxLib version              */
        char     label[40];             /* Library volume label        */
        char     xtra[20];              /* filler                      */
} LIBHEADER;

typedef struct
{
 char     synch;                 /* Synch byte                  */
 char     filename[13];          /* Image file name             */
 long     filesize;              /* File size                   */
 word     date;                  /* File date                   */
 word     time;                  /* File time                   */
 word     pack;                  /* Packing type                */
 char     note[40];              /* Image note                  */
 char     xtra[20];              /* Extra filler                */
} LIBDIR;

#pragma pack()

extern void far *DPMI_getvect(char);
extern void DPMI_setvect(char,void far*);
word d_alc_DPMI(dword bufsize,void *ptr);
void d_free_DPMI(word);

typedef struct
{
 char vect;
 void far *ptrfunc;
}interpt;

interpt Int_Data[] =
{
 {0x08 + 0x02,0},
 {0x08 + 0x03,0},
 {0x08 + 0x05,0},
 {0x08 + 0x07,0},
 {0x68 + 0x0a,0}
};

void ACK( void )
{ if (SbIRQ > 7) outp(0xA0,0x20); outp(0x20,0x20); inp(SbIOaddr+DSP_DATA_AVAIL); };
void __interrupt _loadds INT_TEST2(void) { SbIRQ = 2; ACK(); }
void __interrupt _loadds INT_TEST3(void) { SbIRQ = 3; ACK(); }
void __interrupt _loadds INT_TEST5(void) { SbIRQ = 5; ACK(); }
void __interrupt _loadds INT_TEST7(void) { SbIRQ = 7; ACK(); }
void __interrupt _loadds INT_TESTa(void) { SbIRQ = 0x0a; ACK(); }

void __interrupt _loadds SBHandler()
{
 _asm{STI};
 DMA_complete = 1;

 inp(SbIOaddr+DSP_DATA_AVAIL); if(SbIRQ > 7) outp(0xA0,0x20); outp(0x20,0x20);
}

__interrupt _loadds Interrupt_Function( void )
{
 index += to_move/2;
 if(index>=length)
 {SB_complete=1;sb_voice(0);
  writedsp(HALT_DMA); writedsp(AutoInit_OFF); writedsp(HALT_DMA); goto end;
 }
 if( index + to_move/2 > length ) to_move = (int)(length - index);
 memcpy(SB_buffer+part*SB_HALF_BUFSIZE,glob_DATE+index,to_move/2);
 if(part)part=0;else part=1;
end:
 inp(SbIOaddr+DSP_DATA_AVAIL); if(SbIRQ > 7) outp(0xA0,0x20); outp(0x20,0x20);
 _asm{STI};
// Sb_Out_Voice_DMA( SB_buffer, to_move,STEREO,0 );
};


void writedsp(char simb)
{
 while(inp(SbIOaddr+DSP_WRITE_STATUS)&0x80);
 outp(SbIOaddr+DSP_WRITE_STATUS,simb);
}

void sb_voice(char on) { if(on) writedsp(SPEAKER_ON);else writedsp(SPEAKER_OFF); }
void writemixer(char x,char y)
{ outp(SbIOaddr+MIXER_ADDRESS,x); outp(SbIOaddr+MIXER_ADDRESS+1,y); }


void sb_init_voice_dma( void( __interrupt * handler)() )
{
 char k,k1;

 IntNum = SbIRQ + 0x08;
 if( SbIRQ > 7 ) IntNum += 0x60;
 OldIRQ = DPMI_getvect(IntNum);
 if(!handler) handler = SBHandler;
 DPMI_setvect(IntNum,handler);
 k1=1;
 if(SbIRQ > 7){ k=inp(0xA1); k1<<=(SbIRQ-8); outp(0xA1,k&(k1^0xFF)); }
 else { k=inp(0x21); k1<<=SbIRQ; outp(0x21,k&(k1^0xFF)); }
}

void Sb_DeInit_Voice_DMA(void)
{
 char k,k1;

 sb_voice(0);
// if(SbType >= SBPro) writemixer(0x0e,0x11);          // Turn off stereo output
 DPMI_setvect(IntNum,OldIRQ);
 k1=1;
 if(SbIRQ > 7) { k=inp(0xA1); k1<<=(SbIRQ-8); outp(0xA1,k|k1);}
 else { k=inp(0x21); k1<<=SbIRQ; outp(0x21,k|k1);}
}

char dma_reset(char Channel)
{
 if(Channel > 3) {dma_errno = 0x0C; return(-1);}
 else
 {
  _asm{CLI};
  outp(DMA_MASK,Channel|RESET_CMD);
  outp(Byte_Ptr,0);
  outp(DMA_MASK,Channel);
  _asm{STI};
  dma_errno = 0;
  return(0);
 }
}

char readdsp()
{
 int i;

 for(i=0;i<100;i++) if(inp(SbIOaddr+DSP_DATA_AVAIL)&0x80) break;
 return(inp(SbIOaddr+DSP_DATA_AVAIL-4));
}

word get_dsp_ver()
{
 word v1;
 writedsp(DSP_VER);
 delay(100);

 while((v1=readdsp())==0x55);
 v1<<=8; *(char *)(&v1) = readdsp();
 return(v1);
}

char dma_setup(word Channel, char *data_buff, word len, word Dir,word autoin)
{
 char k; word d;

 dma_errno = 0;
 if(Channel > 3) {dma_errno = 0x0C; return(-1);}
 if(autoin) if(!Dir) k=WRITE_CMD1; else k=READ_CMD1;
 else if(!Dir) k=WRITE_CMD; else k=READ_CMD;
 if(((dword)data_buff&0xFFFF)+len > 0xFFFF) {dma_errno = 2; return(-1);}
 _asm{CLI};
 outp(DMA_MASK,Channel|RESET_CMD);
 outp(Byte_Ptr,0);
 outp(MODE,Channel|k);
 d=Channel<<1;
 outp(d,(dword)data_buff); outp(d,(dword)data_buff>>8);
 outp(d+1,len); outp(d+1,len>>8);
 outp(page_table[Channel],(dword)data_buff>>16);
 outp(DMA_MASK,Channel);
 _asm{STI};
 return(0);
}

int Sb_Out_Voice_DMA(char *data_buff, word dlen, int stereo,int hi_spd)
{
 DMA_complete = 0;

 dlen -= 1;   // DMA always transfers one more byte than given length
              // (so it can transfer a full 64k).  Apparently, the SB
              // DSP knows about this and expects the same value you
              // give the DMAC chip.
 if(dma_reset(SbDMAchan)!=0) return(1);
 if(dma_setup(SbDMAchan,data_buff,dlen,1,0)!=0) return(1);
 if(stereo && SbType >= SBPro) writemixer(0x0e,0x13);
 if(hi_spd && SbType >= SBPro) writedsp(DMA_8_BIT_DAC_HI_INIT);
 else writedsp(DMA_8_BIT_DAC);
 writedsp(dlen); writedsp(dlen>>8);
 if(hi_spd && SbType >= SBPro) writedsp(DMA_8_BIT_DAC_HI_START);
 sb_voice(1);
 return(0);
}

int Sb_Out_Voice_DMA1(char *data_buff, word dlen, int stereo,int hi_spd)
{
 word dlen1;
 DMA_complete = 0;
 dlen1=(dlen+1)/2;
 dlen -= 1; dlen1 -= 1;

// if(dma_reset(SbDMAchan)!=0) return(1);
 if(dma_setup(SbDMAchan,data_buff,dlen,1,1)!=0) return(1);
 if(stereo && SbType >= SBPro) writemixer(0x0e,0x13);
 writedsp(DMA_8_BIT_DAC_HI_INIT);
 writedsp(dlen1); writedsp(dlen1>>8);
 writedsp(AutoInitStart);
 sb_voice(1);
 part=0;
 return(0);
}

char sb_detect()
{
 int i,ii;
 word d;

 SbType=SB15;
 SbIOaddr=0x210;
 for(i=0;i<6;i++,SbIOaddr+=0x10)
 {
  d=SbIOaddr+DSP_RESET;
  outp(d,1); delay(10); outp(d,0);
  for(ii=0,d+=4;ii<100;ii++) if(inp(d)==0xAA) break;
  if(ii<100) break;
 }
 if(i>=6) return(-1);

 for( i=0; i<sizeof(Int_Data)/sizeof(interpt); i++ ) Int_Data[i].ptrfunc=DPMI_getvect(Int_Data[i].vect);
 DPMI_setvect(Int_Data[0].vect,INT_TEST2); DPMI_setvect(Int_Data[1].vect,INT_TEST3);
 DPMI_setvect(Int_Data[2].vect,INT_TEST5); DPMI_setvect(Int_Data[3].vect,INT_TEST7);
 DPMI_setvect(Int_Data[4].vect,INT_TESTa);

 _asm{cli};
 i=inp(0x21); outp(0x21,0x53&i);
 ii=inp(0xA1); outp(0xA1,0xFB&ii);
 _asm{sti};

 SbIRQ = 0;
 writedsp(INT_REQUEST);       //Запрос прерывания
 delay(100);
 _asm{cli}; outp(0x21,i); outp(0xA1,ii); _asm{sti};

 for( i=0; i<sizeof(Int_Data)/sizeof(interpt); i++ ) DPMI_setvect(Int_Data[i].vect,Int_Data[i].ptrfunc);
 if(!SbIRQ) return(-2);

 sb_voice(0); // don't want to make any noise
 sb_init_voice_dma(0);
 for(SbDMAchan = 1,DMA_complete=0;DMA_complete;)
 {
  Sb_Out_Voice_DMA(SB_buffer,1,1,0);
  delay(100);
  if(DMA_complete != 1)
  {
   if (SbDMAchan == 1)     { SbDMAchan = 3; continue;}
   else if(SbDMAchan == 3) { SbDMAchan = 0; continue;}
   else { Sb_DeInit_Voice_DMA();return(-3);}
  }
  Sb_DeInit_Voice_DMA();
 }

 d=get_dsp_ver(); d--; d>>=8;
 SbType = Type_Data[d-1];

 return(0);
}

int SB_Initialize()
{
 int rc;
 if(SB_Dos_header) d_free_DPMI(SB_Dos_header);
 SB_Dos_header=d_alc_DPMI(SB_BUFSIZE,&SB_buffer);
 rc = sb_detect(); if(rc)return(rc);
 sb_init_voice_dma( Interrupt_Function );
 SB_Installed = 1;
 return 0;
};

int SB_DeInitialize()
{
 if(SB_Installed)
 {
//  while(!SB_complete);
  SB_complete=1;sb_voice(0);
  writedsp(HALT_DMA); writedsp(AutoInit_OFF); writedsp(HALT_DMA);

  Sb_DeInit_Voice_DMA();
 }
 if(SB_Dos_header) d_free_DPMI(SB_Dos_header);
 SB_Installed=0;SB_Dos_header=0;
 return 0;
};

int SB_via(char *wav)
{
 Chunk *ch;
 WAVEFORMAT *wf;

 wav+=sizeof(RiffHeader);
 for(;;)
 {
  ch=(Chunk *)wav;
  if(!strncmp(ch->chunk_id,"fmt ",4))
  {
   wav+=sizeof(Chunk); wf=(WAVEFORMAT *)wav; wav+=ch->chunksize;
   if(wf->wFormatTag!=1) return 3;
   if(wf->nChannels==1)STEREO=0;
   else if(wf->nChannels==2)STEREO=1;
   else return 3;
   if(wf->wBitsPerSample!=8) return 3;
   writedsp(TIME_CONSTANT);
   writedsp(256-(1000000/(wf->nSamplesPerSec*wf->nChannels)));
   continue;
  }
  if(!strncmp(ch->chunk_id,"data",4))
  {
   length = ch->chunksize; wav+=sizeof(Chunk);
   break;
  }
  wav+=(sizeof(Chunk)+ch->chunksize);
 }
 length = (length >> 1 ) << 1;

 if(glob_DATE) { free(glob_DATE); glob_DATE=0; }
 glob_DATE=calloc(length+1023,1);
 memcpy(glob_DATE,wav,ch->chunksize);

 index=0;
 to_move=SB_BUFSIZE;
 if( index + to_move > length ) to_move = (int)(length - index);
 memcpy(SB_buffer,glob_DATE+index,to_move);
 index+=to_move/2;
 SB_complete = 0;

 Sb_Out_Voice_DMA1( SB_buffer, to_move,STEREO,0);
 return 0;
};

int SB_via_File( char * File_Name )
{
 int handle;
 char *str;

 if(!SB_Installed || !SbType ) return -1;
 if(!SB_complete) return -5;
 if((handle = open( File_Name, O_BINARY | O_RDWR)) == -1) return 1;
 if((length = filelength(handle))<=0) return 2;

 str=calloc(length,1); read(handle,str,length);
 SB_via(str);
 free(str);
 close(handle);

 return 0;
};

int SB_Lib_via( char * File_Name )
{
 int fh,count=0,flib_len;
 char *str;
 LIBDIR lbpcx;
 LIBHEADER lbpcxHd;

 if(!SB_Installed || !SbType ) return -1;
 if(!SB_complete) return -2;
 if((fh=open(NameWAV,O_BINARY|O_RDONLY)) <= 0) return 1;
 flib_len=(long)filelength(fh)-sizeof(LIBHEADER);
 read(fh,&lbpcxHd,sizeof(LIBHEADER));
 for(;;)
 {read(fh,&lbpcx,sizeof(LIBDIR)); count+=sizeof(LIBDIR);
  if(count > flib_len) return (-3);
  if(!strncmp(lbpcx.filename,File_Name,12)) break;
  count+=lbpcx.filesize; lseek(fh,lbpcx.filesize,SEEK_CUR);
 }
 str=calloc(lbpcx.filesize,1); read(fh,str,lbpcx.filesize);
 SB_via(str);
 free(str);
 close(fh);

 return 0;
}

int getFonem(byte *buf,char *NameLib,char *NameF)
{
 int fh,count=0,flib_len,len_tmp;
 char *str,*str1;
 LIBDIR lbpcx;
 LIBHEADER lbpcxHd;
 Chunk *ch;
 WAVEFORMAT *wf;

 if((fh=open(NameLib,O_BINARY|O_RDONLY)) <= 0) return -1;
 flib_len=(long)filelength(fh)-sizeof(LIBHEADER);
 read(fh,&lbpcxHd,sizeof(LIBHEADER));

 for(;;)
 {
  read(fh,&lbpcx,sizeof(LIBDIR)); count+=sizeof(LIBDIR);
  if(count > flib_len) return (-1);
  if(!strncmp(lbpcx.filename,NameF,12)) break;
  count+=lbpcx.filesize; lseek(fh,lbpcx.filesize,SEEK_CUR);
 }
 str1=str=calloc(1,lbpcx.filesize); read(fh,str,lbpcx.filesize); close(fh);
 str+=sizeof(RiffHeader);
 for(;;)
 {
  ch=(Chunk *)str;
  if(!strncmp(ch->chunk_id,"fmt ",4))
  {
   str+=sizeof(Chunk); wf=(WAVEFORMAT *)str; str+=ch->chunksize;
   if(wf->wFormatTag!=1) return -1;
   if(wf->nChannels>1) return -1;
   if(wf->wBitsPerSample!=8) return -1;
   continue;
  }
  if(!strncmp(ch->chunk_id,"data",4))
  { len_tmp = ch->chunksize; str+=sizeof(Chunk); break; }
  str+=(sizeof(Chunk)+ch->chunksize);
 }
 memcpy(buf,str,len_tmp);
 free(str1);
 return(len_tmp);
// return(10001);
}


//Синтезация речи


int sinth(char *str2,char **str4,char lng)
{
 int i,ii,len,l_tmp,l_tmp_pr,tip=0,tip_pr=0,n_1,max_l,max_r,min_l,min_r,maxLnFon=8000;
 char str1[20],k[5],*str,pred_c;
 byte *WavBuf=NULL,*tempBuf,pred_c1;
 float f_max,f_min;
 RiffHeader rif;
 WAVEFORMAT wf;
 Chunk ch;
 enum {prep=0,glasn,sogl};
 l_tmp_pr=prep;

 if(!SB_complete)return(0);

 str = calloc(1,strlen(str2)+1); strcpy(str,str2);
 for(i=strlen(str)-1;i>=0;i--)if(str[i]==' ')str[i]=0;else break;
 if(!strlen(str)){free(str); return(0);}

 tempBuf = calloc(1,maxLnFon); WavBuf = calloc(strlen(str),maxLnFon);
 for(len=0,i=0;i<strlen(str);i++)
 {
  if(str[i]>='а' && str[i]<='п'||str[i]=='i') str[i]-=0x20;
  if(str[i]>='р' && str[i]<='я') str[i]-=0x50;
  if(str[i]=='ё'||str[i]=='ї'||str[i]=='є') str[i]--;

  memset(k,0,5); n_1=1;
//Украинский
  if(lng==1)
   switch(str[i])
   {
    case 'Ї': strcpy(k,"Й1");tip=sogl; str[i]='И'; i--; goto sint;
    case 'Е': str[i]='Э'; break;
    case 'Є': str[i]='Е'; break;
    case 'I': str[i]='И'; break;
    case 'И': str[i]='Ы'; break;
    case 0x27 : str[i]='Ъ'; break;         // Знак <'> в Украинском
   }

  switch(str[i])
  {
   case 'Е': case 'Ё': case 'Ю':  case 'Я':
     if(tip_pr!=sogl) {strcpy(k,"Й1");tip=sogl; i--;} else {k[0] =pred_c= str[i]; tip=glasn;}
     break;
   case 'А': case 'О': case 'И': case 'У': case 'Ы': case 'Э': case 'Ь':
     k[0] = pred_c = str[i]; tip=glasn; break;
   case 'К': case 'Т': case 'П': case 'Ц':
     if(tip_pr!=prep) {k[0] = 'Ъ';tip=prep; i--;} else {k[0] = str[i]; tip=sogl;}
     break;
   case 'Б': case 'В': case 'Г': case 'Д': case 'Ж': case 'З': case 'Й':
   case 'Л': case 'М': case 'Н': case 'Р': case 'С': case 'Ф':
   case 'Х': case 'Ч': case 'Ш': case 'Щ':
     k[0] = str[i]; tip=sogl; break;
   case 'Ъ': k[0] = 'Ъ'; tip=prep; break;
   case ' ': n_1=3; k[0] = 'Ъ'; tip=prep; break;
   case ',': n_1=5; k[0] = 'Ъ'; tip=prep; break;
   case '.': n_1=7; k[0] = 'Ъ'; tip=prep; break;
   case '+':
//     if(pred_c=='Е') k[0]='Е';
     if(pred_c=='Ё')      k[0]='О';
     else if(pred_c=='Ю') k[0]='У';
     else if(pred_c=='Я') k[0]='А';
     else                 k[0] = pred_c;
     tip=glasn;
     break;
  }
  sint:
  if(k[0])
  {
   sprintf(str1,"%s.WAV",k);
   l_tmp=getFonem(tempBuf,"wav.rs",str1); if(l_tmp== -1) continue;
//Сглаживание гласных по краям
   if(tip==glasn||tip_pr==glasn)
   {
    max_l=max_r=min_l=min_r=128;
    if(tip_pr!=prep)
     for(ii= -250;ii<-1;ii++) {max_l=max(WavBuf[len+ii],max_l); min_l=min(WavBuf[len+ii],min_l);}
    for(ii=0;ii<250;ii++) {max_r=max(tempBuf[ii],max_r); min_r=min(tempBuf[ii],min_r);}
    f_max=((float)max_l-128.)/((float)max_r-128.+1.); f_min=(128.-(float)min_l)/(128.-(float)min_r+1.);
    if(tip==glasn)
     for(ii=0;ii<l_tmp/2;ii++)
     {
      f_max+= 0.003*(1.0-f_max); f_min+= 0.003*(1.0-f_min);
      if(tempBuf[ii]>128) tempBuf[ii]= (tempBuf[ii]-128)*f_max+128;
      else tempBuf[ii]= 128 - (128 - tempBuf[ii])*f_min;
     }
    else
     for(ii=1;ii<l_tmp_pr/2;ii++)
     {
      f_max+= 0.01*(1.0-f_max); f_min+= 0.01*(1.0-f_min);
      if(WavBuf[len-ii]>128) WavBuf[len-ii]= (WavBuf[len-ii]-128)/f_max+128;
      else WavBuf[len-ii]= 128 - (128 - WavBuf[len-ii])/f_min;
     }
   }
   for(ii=0;ii<n_1;ii++)
   {len+=l_tmp;// WavBuf1=calloc(1,len);                              // realloc в данном случае почему то глючит, при
//    if(WavBuf) { memcpy(WavBuf1,WavBuf,len-l_tmp); free(WavBuf);}   // больших невыравненых по слову значениях длины
//    WavBuf=WavBuf1;
//    if(WavBuf) WavBuf=realloc(WavBuf,len); else WavBuf=calloc(1,len);
    memcpy(WavBuf+len-l_tmp,tempBuf,l_tmp);
   }
  }
  tip_pr=tip; l_tmp_pr=l_tmp;
 }
 free(tempBuf); free(str);

 *str4=str=calloc(1,sizeof(RiffHeader)+2*sizeof(Chunk)+sizeof(WAVEFORMAT)+len);
 strncpy(rif.riff,"RIFF",4); rif.filesize=len+sizeof(RiffHeader)-8+2*sizeof(Chunk)+sizeof(WAVEFORMAT);
 strncpy(rif.rifftype,"WAVE",4);
 strncpy(ch.chunk_id,"fmt ",4); ch.chunksize = sizeof(wf);
 wf.wFormatTag = 1; wf.nChannels = 1;
 wf.nSamplesPerSec = 22050; wf.nAvgBytesPerSec = 22050;
 wf.nBlockAlign = 1; wf.wBitsPerSample=8;
 memcpy(str,&rif,sizeof(RiffHeader)); str+=sizeof(RiffHeader);
 memcpy(str,&ch,sizeof(Chunk));       str+=sizeof(Chunk);
 memcpy(str,&wf,sizeof(WAVEFORMAT));  str+=sizeof(WAVEFORMAT);
 strncpy(ch.chunk_id,"data",4); ch.chunksize = len;
 memcpy(str,&ch,sizeof(Chunk));       str+=sizeof(Chunk);
 memcpy(str,WavBuf,len); free(WavBuf);
 return(sizeof(RiffHeader)+2*sizeof(Chunk)+sizeof(WAVEFORMAT)+len);
}

int hear(char *file)
{
 int fh,fh1,len_tmp,i;
 char *str,*str1,str2[256];
 Chunk *ch;
 WAVEFORMAT *wf;
 int last_zn=0,last_zn1,tmp_zn,last_i,cur_st,last_st,count_tp,count_ft=1;

 if((fh=open(file,O_BINARY|O_RDWR)) <= 0) return -1;
 str1=str=calloc(1,filelength(fh)); read(fh,str,filelength(fh)); close(fh);
 str+=sizeof(RiffHeader);
 for(;;)
 {
  ch=(Chunk *)str;
  if(!strncmp(ch->chunk_id,"fmt ",4))
  {
   str+=sizeof(Chunk); wf=(WAVEFORMAT *)str; str+=ch->chunksize;
   if(wf->wFormatTag!=1) return -1;
   if(wf->nChannels>1) return -1;
   if(wf->wBitsPerSample!=8) return -1;
   continue;
  }
  if(!strncmp(ch->chunk_id,"data",4))
  { len_tmp = ch->chunksize; str+=sizeof(Chunk); break; }
  str+=(sizeof(Chunk)+ch->chunksize);
 }
// memcpy(buf,str,len_tmp);
 if((fh1=open("alg.err",O_BINARY|O_RDWR|O_CREAT|O_TRUNC)) <= 0) {free(str1); return -1;}

 for(last_zn1=last_st=cur_st=last_i=i=0;i<len_tmp;i++)
 {
  tmp_zn=(byte)str[i]-128;
//  if(last_zn==tmp_zn) if(cur_st!=0&&last_st==0)   count_tp++; else {count_tp=0; last_st= 0; }
  if(last_zn<tmp_zn)  if(cur_st!= 1&&last_st== 1) count_tp++; else {count_tp=0; last_st=  1;last_zn1=tmp_zn;}
  if(last_zn>tmp_zn)  if(cur_st!=-1&&last_st==-1) count_tp++; else {count_tp=0; last_st= -1;last_zn1=tmp_zn;}
  if(count_tp>=count_ft)
  {
   cur_st=last_st;
   sprintf(str2,"Тип перехода - %d; время - %d; значение - %d \n",cur_st,i-last_i,last_zn);
   write(fh1,str2,strlen(str2));
   last_i=i-count_tp; count_tp=0;
  }
  last_zn=tmp_zn;
 }
 free(str1); close(fh1);

 return(0);
}