⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 snd.h

📁 这个版本修正了已知的Bug,同时添加了部分函数
💻 H
字号:
#include <stdio.h>
#include <i86.h>
#include <dos.h>
#include <conio.h>
#include <mem.h>
#include "dma.h"

short lk_sb_irq=-1,  lk_sb_dma=-1;
short lk_sb_stereo=0,   lk_sb_16bit=0;

char  snd_init(short addr,short irq,short dma);
void  snd_rest();
void  _isr();
void   snd_play(Voc *buf,int sample);
Voc  *load_voc(char *file);
int flen=0;
///////////////////////////////////////////////////////////////////////////

struct
{ long  phy;
  short size;
  short selector;
  char *data;
} dma_buf[2];

struct 
{ int   sample;
  unsigned long  len_to_play;
  char *data_to_play;
} snd_buf; 

extern short lk_sb_stereo, lk_sb_16bit;
 short IntNumbers[] = {
  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77 };
long   int  lk_dma_mix_size;
//long lk_dma_size=0x10000/8;
unsigned short lk_dma_size=32767;

#define BUFSIZE lk_dma_size

 int  lk_sb_freq=-1;
 int  sb_bufnum=0;
 int  sb_init_flag=0;
 char snd_playing=0;
 char snd_create_buffers(int size,int block);
 void snd_release_buffers();
 void set_isr();
 void rest_isr();
 void snd_stop();
 void interrupt interrupt_isr();
 void interrupt far (*old_interrupt)()=NULL;
 void snd_play_buffer(char buf,unsigned short size,int sampleRate);
///////////////////////////////////////////////////////

char snd_create_buffers(int size,int block)
{ int first_size;
  char i;
  if (size<16384L) size=16384L;
  if (block==1) first_size=size*2; else first_size=size;
  i=grp_dma_alloc(first_size,&dma_buf[0].phy,&dma_buf[0].selector);
  if (i) { dma_buf[0].phy=0; return 1; }
  dma_buf[0].size=first_size; dma_buf[0].data=(char*)dma_buf[0].phy;
  
  if (block==2)
  { i=grp_dma_alloc(size,&dma_buf[1].phy,&dma_buf[1].selector);
    if (i) {
      grp_dma_free(size,dma_buf[0].phy,dma_buf[0].selector);
      dma_buf[0].phy=dma_buf[1].phy=0;
	} dma_buf[1].size=size; dma_buf[1].data=(char*)dma_buf[1].phy;
  }
   else {
        dma_buf[1].data=dma_buf[0].data+size; 
	dma_buf[1].phy=dma_buf[0].phy+size;
	dma_buf[1].size=0; dma_buf[1].selector=dma_buf[0].selector;
  }
return 0;
}

 void  snd_release_buffers()
{ int i;
  for (i=0;i<2;i++) if (dma_buf[i].phy&&dma_buf[i].size>0) {
    grp_dma_free(dma_buf[i].size,dma_buf[i].phy,dma_buf[i].selector);
    dma_buf[i].phy=dma_buf[i].size=0;
  }
}


char  snd_init(short addr,short irq,short dma)
{ short dma8,dma16; 
  int block=2;
  timer_init();
  if (sb_init_flag) return 0;
  if (addr<0||irq<0||dma<0) {
     GetBlasterEnv(&addr,&dma8,&dma16,&irq);
     dma=dma8;
  }
  if (addr<0||irq<0||dma<0) return -1;
  lk_sb_port=addr; lk_sb_dma=dma; lk_sb_irq=irq;
  if (ResetDsp(1)) return -2;

  if (snd_create_buffers(lk_dma_size,block)) return -3;
  set_isr();
  WritePortC(0xd1);
  sb_init_flag=1;
  atexit(snd_rest);
  return 0;
}

void  snd_rest()
{ if (sb_init_flag==0) return ;
  snd_stop();
  rest_isr();
  snd_release_buffers();
  WritePortC(0xd3);
}

#define PIC1MODE        0x20    // for irq 0 - 7
#define PIC1MASK        0x21
#define PIC2MODE        0xA0    // for irq 8 - 15
#define PIC2MASK        0xA1
#define PICEOI          0x20    // End Of Interrupt

 void set_isr()
{   int  Intr_num;
    int  Intr_mask;

    if (old_interrupt!=NULL) return ;
    Intr_num =  IntNumbers[lk_sb_irq];
    Intr_mask = 1 << lk_sb_irq;
    old_interrupt=_dos_getvect(Intr_num);
    _disable();
    _dos_setvect(Intr_num,interrupt_isr);
    _enable();
    outp(PIC1MASK, inp(PIC1MASK) & ~Intr_mask);
    outp(PIC2MASK, inp(PIC2MASK) & ~(Intr_mask >> 8));
}

void rest_isr()
{   int  Intr_num;
    int  Intr_mask;

    if (old_interrupt==NULL) return ;
    Intr_num =  IntNumbers[lk_sb_irq];
    Intr_mask = 1 << lk_sb_irq;

    outp(PIC1MASK, inp(PIC1MASK) | Intr_mask);
    outp(PIC2MASK, inp(PIC2MASK) | (Intr_mask >> 8));
#ifdef TEST
    remove_int(_isr);
#endif
    _disable();
    _dos_setvect(Intr_num,old_interrupt);
    _enable();
    old_interrupt=NULL;
}
///////////////////////////////////////////////////////
 void snd_sample_rate(unsigned int rate)
{  WritePortC(0x40);
   WritePortC((unsigned char)(256-1000000/rate));
}

 void snd_play_buffer(int size)
{  WritePortC(0x14);
   WritePortC((size-1) & 0xFF);
   WritePortC((size-1) >> 8);

}

void snd_play_buffer(char buf,unsigned short size, int sampleRate)
{
  if (dma_buf[buf].phy==0)return;
  snd_sample_rate(sampleRate);
  if (size>dma_buf[buf].size) size=dma_buf[buf].size;
  sb_bufnum=buf;  
  grp_dma_start(lk_sb_dma,dma_buf[buf].phy,size,0,0);
  snd_play_buffer(size);
}
///////////////////////////////////////////////////////////////////////////

void snd_playA()
{ memset(dma_buf[0].data,0,lk_dma_size);
  snd_play_buffer(0,1,snd_buf.sample);
  WritePortC(0xd1);
}

void snd_stop()
{ResetDsp(1);
}

void snd_play(Voc *buf,int sample)
{
  snd_buf.sample=sample;
  if(buf->size>lk_dma_size)
  snd_buf.len_to_play=lk_dma_size;
  else
  snd_buf.len_to_play=buf->size;
  snd_buf.data_to_play=buf->dat;
  buf->same=sample;
#ifdef TEST
  install_int(_isr,4000);
#endif
  memset(dma_buf[0].data,0,lk_dma_size);
  snd_play_buffer(0,1,sample);
  WritePortC(0xd1);
}
///////////////////////////////////////////////////////

void _isr()
{
if(flen>0&&snd_playing)
    {
      if(flen-lk_dma_size>0)
      {
      flen-=lk_dma_size;
      snd_buf.len_to_play=lk_dma_size;
      }
      else
       {
       snd_buf.len_to_play=flen;
       }
       ResetDsp(1);
      snd_playA();
  snd_playing=0;
    }
}


void interrupt interrupt_isr()
{ int len;
  char cont=1;
  len=snd_buf.len_to_play;
  if (len>lk_dma_size) len=lk_dma_size;
  if(snd_buf.len_to_play==0||len==0||snd_buf.data_to_play==NULL)cont=0;
    snd_playing=1;
  if (cont) {
    snd_playing=0;
    sb_bufnum = 1 - sb_bufnum; 
    memcpy(dma_buf[sb_bufnum].data,snd_buf.data_to_play,len);
    grp_dma_start(lk_sb_dma, dma_buf[sb_bufnum].phy, lk_dma_size, FALSE, FALSE);
    snd_buf.len_to_play-=len;
    snd_buf.data_to_play+=len;
    snd_play_buffer(sb_bufnum,len,snd_buf.sample);
    snd_playing=1;
    }
    outp(0x20, 0x20);
}


Voc *load_voc(char *file)
{FILE *fp;
int len;
Voc *voc=new Voc;
if((fp=fopen(file,"rb"))==NULL){
sprintf(grp_err,"Load Voc File %s Error.",file);
return FALSE;
}

fseek(fp,0L,SEEK_END);
len=ftell(fp)-27;
flen=len;
if(flen>lk_dma_size)flen-=lk_dma_size;
voc->size=len;
rewind(fp);

voc->dat=new char [len];
if(voc->dat==NULL){
sprintf(grp_err,"Malloc Snd System memony Error.");return FALSE;
}
fseek(fp,27L,SEEK_SET);
fread(voc->dat,1,len,fp);
fclose(fp);
return voc;
}

void destroy_voc(Voc *voc)
{if(voc!=NULL)
{ if(voc->dat!=NULL)delete []voc->dat;
 delete voc;
}
}

short AutoDetect()
{ short found=0, i=10, b;
  static detect=0;
  if (detect) return lk_sb_port;

  for (lk_sb_port=0x210;lk_sb_port<=0x260&&!found;)
   { outp(lk_sb_port+0x6,1);
     delay(3); for (b=3;b>=0;b--);
     outp(lk_sb_port+0x06,0);
     for (b=50;b>0&&inp(lk_sb_port+0x0e)<128;b--);
     if ((b==0)||inp(lk_sb_port+0x0a)!=0xaa)
      { i--;
	if (!i); {i=10; lk_sb_port+=0x10; }
      }
     else { found=1; detect=1; }
   }
  return ((found==1)?lk_sb_port:0);
}

short ResetDsp(short data)
{  int x;
   outp(0x06+lk_sb_port, data);
   for (x=0; x<8; x++) inp(0x06+lk_sb_port);
   outp(0x06+lk_sb_port, 0);
   if (ReadPortC() != 0xAA) return -1;
   return 0;
}

short GetBlasterEnv(short *_sb_port,short *_sb_dma8,short *_sb_dma16,short *_sb_irq)
{  char *blaster=getenv("BLASTER");
   *_sb_port=*_sb_dma8=*_sb_dma16=*_sb_irq=-1;
   if (blaster) { 
      while (*blaster) {
	 while ((*blaster == ' ') || (*blaster == '\t'))
	    blaster++;

	 if (*blaster) {
	    switch (*blaster) {

	       case 'a': case 'A':
		     *_sb_port = strtol(blaster+1, NULL, 16);
		  break;

	       case 'i': case 'I':
		     *_sb_irq = strtol(blaster+1, NULL, 10);
		  break;

	       case 'd': case 'D':
		  *_sb_dma8 = strtol(blaster+1, NULL, 10);
		  break;

	       case 'h': case 'H':
		  *_sb_dma16 = strtol(blaster+1, NULL, 10);
		  break;
	    }

	    while ((*blaster) && (*blaster != ' ') && (*blaster != '\t'))
	       blaster++;
	 }
      }
      return 1;
   }
  return 0;
}

char WritePortC(unsigned char value)
{ int i;
  for (i=0;i<0xffff ;i++ )
  { if (!(inp(0x0C+lk_sb_port) & 0x80)) {
       outp(lk_sb_port+0x0c,value);
    return 0;
    }
  } return -1;
}

unsigned char ReadPortC()
{ short b;
  for (b=50;b>0&&inp(lk_sb_port+0x0e)<128;b--);
  return inp(lk_sb_port+0x0a);
}






⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -