#include #include #include #include #include #include #include #include #include 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>=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='а' && 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;ii128) tempBuf[ii]= (tempBuf[ii]-128)*f_max+128; else tempBuf[ii]= 128 - (128 - tempBuf[ii])*f_min; } else for(ii=1;ii128) WavBuf[len-ii]= (WavBuf[len-ii]-128)/f_max+128; else WavBuf[len-ii]= 128 - (128 - WavBuf[len-ii])/f_min; } } for(ii=0;iichunk_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;itmp_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); }