home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 June B / Pcwk6b98.iso / Mpeg3 / Dos / MP3 / MPG12304.EXE / AUDIO.C next >
C/C++ Source or Header  |  1997-05-11  |  7KB  |  387 lines

  1. #include <dos.h>
  2. #include "audio.h"
  3. #include "mpg123.h"
  4. #include "mdma.h"
  5. #include "mirq.h"
  6.  
  7. #define DMA_SIZE 32768
  8.  
  9. void interrupt far newhandler();
  10. void SB_PlayStop(void);
  11. void SB_PlayStart(void);
  12. void SB_MixerStereo(void);
  13. void SB_MixerMono(void);
  14. BOOL SB_WaitDSPWrite(void);
  15. BOOL SB_WaitDSPRead(void);
  16. BOOL SB_WriteDSP(UBYTE);
  17. UWORD SB_ReadDSP(void);
  18. void SB_SpeakerOn(void);
  19. void SB_SpeakerOff(void);
  20. void SB_ResetDSP(void);
  21. BOOL SB_Ping(void);
  22. UWORD SB_GetDSPVersion(void);
  23. BOOL SB_IsThere(void);
  24.  
  25. static UWORD sb_port;          /* sb base port */
  26.  
  27. static DMAMEM *SB_DMAMEM;
  28. static char *SB_DMABUF;
  29.  
  30. static UBYTE SB_TIMECONSTANT;
  31.  
  32. static UBYTE PIC1MSK;
  33. static UBYTE PIC2MSK;
  34.  
  35. static UWORD sb_int;           /* interrupt vector that belongs to sb_irq */
  36. static UWORD sb_ver;           /* DSP version number */
  37. static UBYTE sb_irq;           /* sb irq */
  38. static UBYTE sb_lodma;         /* 8 bit dma channel (1.0/2.0/pro) */
  39. static UBYTE sb_hidma;         /* 16 bit dma channel (16/16asp) */
  40. static UBYTE sb_dma;           /* current dma channel */
  41.  
  42. UWORD last=0;
  43. UWORD curr=0;
  44.  
  45. BOOL playing=0;
  46. int mixfreq;
  47.  
  48. PVI oldhandler;
  49.  
  50. int audio_open(struct audio_info_struct *ai)
  51. {
  52.     ULONG t;
  53.  
  54.     if(!SB_IsThere()){
  55.     fprintf(stderr,"SB not detected.");
  56.     return -1;
  57.     }
  58.  
  59.   if(sb_ver<0x400){
  60.     fprintf(stderr,"SB16 not detected.");
  61.     return -1;
  62.     }
  63.  
  64.   sb_dma=sb_hidma;
  65.  
  66.   SB_DMAMEM=MDma_AllocMem(DMA_SIZE);
  67.  
  68.     if(SB_DMAMEM==NULL){
  69.     fprintf(stderr,"Couldn't allocate page-contiguous dma-buffer");
  70.     return -1;
  71.     }
  72.  
  73.     SB_DMABUF=(char *)MDma_GetPtr(SB_DMAMEM);
  74.  
  75.   memset(SB_DMABUF,0,DMA_SIZE);
  76.  
  77.     oldhandler=MIrq_SetHandler(sb_irq,newhandler);
  78.   return 0;
  79. }
  80.  
  81. int audio_set_rate(struct audio_info_struct *ai)
  82. {
  83.   mixfreq=ai->rate;
  84.   return 0;       
  85. }
  86.  
  87. int audio_set_channels(struct audio_info_struct *ai)
  88. {
  89.   return 0;       // not neccessary :)
  90. }
  91.  
  92. int audio_play_samples(struct audio_info_struct *ai,short *src,int size)
  93. {
  94.   UWORD todo,left;
  95.  
  96.   left=size*2;
  97.  
  98.   if (playing==0) SB_PlayStart();
  99.  
  100. wait:
  101.   curr=(DMA_SIZE-MDma_Todo(sb_dma))&0xfffc;
  102.  
  103.   if(curr>last){
  104.     todo=curr-last;
  105.  
  106.     if(todo>left)
  107.     {
  108.       memcpy(&SB_DMABUF[last],(char *)src,left);
  109.       last += left;
  110.       if(last>=DMA_SIZE) last=0;
  111.       return 0;
  112.     }
  113.     else
  114.     {
  115.  //     memcpy(&SB_DMABUF[last],(char *)src,todo);
  116.  //     last += todo;
  117.  //     src += todo;
  118.  //     left-=todo;
  119.  
  120.  // WHAT THE FUCK IS WRONG WITH THIS???
  121.  
  122.       goto wait;
  123.     }
  124.  
  125.     }
  126.     else{
  127.     todo=DMA_SIZE-last;
  128.  
  129.     if(todo>left)
  130.     {
  131.       memcpy(&SB_DMABUF[last],(char *)src,left);
  132.       last += left;
  133.       return 0;
  134.     }
  135.     else
  136.     {
  137.       memcpy(&SB_DMABUF[last],(char *)src,todo);
  138.       left-=todo;
  139.       last=0;
  140.       src+=todo;
  141.       goto wait;
  142.     }
  143.     }
  144. }
  145.  
  146. int audio_close(struct audio_info_struct *ai)
  147. {
  148.   SB_PlayStop();
  149.   MIrq_SetHandler(sb_irq,oldhandler);
  150.     MDma_FreeMem(SB_DMAMEM);
  151.   return 0;
  152. }
  153.  
  154. void interrupt far newhandler(MIRQARGS)
  155. {
  156.   inportb(sb_port+0xf);
  157.     MIrq_EOI(sb_irq);
  158. }
  159.  
  160. BOOL SB_WaitDSPWrite(void)
  161. /*
  162.     Waits until the DSP is ready to be written to.
  163.  
  164.     returns FALSE on timeout
  165. */
  166. {
  167.     UWORD timeout=32767;
  168.  
  169.     while(timeout--){
  170.         if(!(inportb(DSP_WRITE_STATUS)&0x80)) return 1;
  171.     }
  172.     return 0;
  173. }
  174.  
  175.  
  176.  
  177. BOOL SB_WaitDSPRead(void)
  178. /*
  179.     Waits until the DSP is ready to read from.
  180.  
  181.     returns FALSE on timeout
  182. */
  183. {
  184.     UWORD timeout=32767;
  185.  
  186.     while(timeout--){
  187.         if(inportb(DSP_DATA_AVAIL)&0x80) return 1;
  188.     }
  189.     return 0;
  190. }
  191.  
  192.  
  193.  
  194. BOOL SB_WriteDSP(UBYTE data)
  195. /*
  196.     Writes byte 'data' to the DSP.
  197.  
  198.     returns FALSE on timeout.
  199. */
  200. {
  201.     if(!SB_WaitDSPWrite()) return 0;
  202.     outportb(DSP_WRITE_DATA,data);
  203.     return 1;
  204. }
  205.  
  206.  
  207.  
  208. UWORD SB_ReadDSP(void)
  209. /*
  210.     Reads a byte from the DSP.
  211.  
  212.     returns 0xffff on timeout.
  213. */
  214. {
  215.     if(!SB_WaitDSPRead()) return 0xffff;
  216.     return(inportb(DSP_READ_DATA));
  217. }
  218.  
  219.  
  220.  
  221. void SB_SpeakerOn(void)
  222. /*
  223.     Enables DAC speaker output.
  224. */
  225. {
  226.     SB_WriteDSP(0xd1);
  227. }
  228.  
  229.  
  230.  
  231. void SB_SpeakerOff(void)
  232. /*
  233.     Disables DAC speaker output
  234. */
  235. {
  236.     SB_WriteDSP(0xd3);
  237. }
  238.  
  239.  
  240.  
  241. void SB_ResetDSP(void)
  242. /*
  243.     Resets the DSP.
  244. */
  245. {
  246.     int t;
  247.     /* reset the DSP by sending 1, (delay), then 0 */
  248.     outportb(DSP_RESET,1);
  249.     for(t=0;t<8;t++) inportb(DSP_RESET);
  250.     outportb(DSP_RESET,0);
  251. }
  252.  
  253.  
  254.  
  255. BOOL SB_Ping(void)
  256. /*
  257.     Checks if a SB is present at the current baseport by
  258.     resetting the DSP and checking if it returned the value 0xaa.
  259.  
  260.     returns: TRUE   => SB is present
  261.              FALSE  => No SB detected
  262. */
  263. {
  264.     SB_ResetDSP();
  265.     return(SB_ReadDSP()==0xaa);
  266. }
  267.  
  268.  
  269.  
  270. UWORD SB_GetDSPVersion(void)
  271. /*
  272.     Gets SB-dsp version. returns 0xffff if dsp didn't respond.
  273. */
  274. {
  275.     UWORD hi,lo;
  276.  
  277.     if(!SB_WriteDSP(0xe1)) return 0xffff;
  278.  
  279.     hi=SB_ReadDSP();
  280.     lo=SB_ReadDSP();
  281.  
  282.     return((hi<<8)|lo);
  283. }
  284.  
  285. static BOOL SB_IsThere(void)
  286. {
  287.     char *envptr,c;
  288.     static char *endptr;
  289.  
  290.     sb_port =0xffff;
  291.     sb_irq  =0xff;
  292.     sb_lodma=0xff;
  293.     sb_hidma=0xff;
  294.  
  295.   if((envptr=(char *)getenv("BLASTER"))==NULL) return 0;
  296.  
  297.     while(1){
  298.  
  299.         /* skip whitespace */
  300.  
  301.         do c=*(envptr++); while(c==' ' || c=='\t');
  302.  
  303.         /* reached end of string? -> exit */
  304.  
  305.         if(c==0) break;
  306.  
  307.         switch(c){
  308.  
  309.             case 'a':
  310.             case 'A':
  311.                 sb_port=strtol(envptr,&endptr,16);
  312.                 break;
  313.  
  314.             case 'i':
  315.             case 'I':
  316.                 sb_irq=strtol(envptr,&endptr,10);
  317.                 break;
  318.  
  319.             case 'd':
  320.             case 'D':
  321.                 sb_lodma=strtol(envptr,&endptr,10);
  322.                 break;
  323.  
  324.             case 'h':
  325.             case 'H':
  326.                 sb_hidma=strtol(envptr,&endptr,10);
  327.                 break;
  328.  
  329.             default:
  330.                 strtol(envptr,&endptr,16);
  331.                 break;
  332.         }
  333.         envptr=endptr;
  334.     }
  335.  
  336.     if(sb_port==0xffff || sb_irq==0xff || sb_lodma==0xff) return 0;
  337.  
  338.     /* determine interrupt vector */
  339.  
  340.     sb_int = (sb_irq>7) ? sb_irq+104 : sb_irq+8;
  341.  
  342.     if(!SB_Ping()) return 0;
  343.  
  344.     /* get dsp version. */
  345.  
  346.     if((sb_ver=SB_GetDSPVersion())==0xffff) return 0;
  347.  
  348.     return 1;
  349. }
  350.  
  351. static void SB_PlayStart(void)
  352. {
  353.     MIrq_OnOff(sb_irq,1);
  354.  
  355.     if(!MDma_Start(sb_dma,SB_DMAMEM,DMA_SIZE,INDEF_WRITE)){
  356.       return;
  357.     }
  358.  
  359.     SB_WriteDSP(0x41);
  360.  
  361.     SB_WriteDSP(mixfreq>>8);
  362.     SB_WriteDSP(mixfreq&0xff);
  363.  
  364.     SB_WriteDSP(0xb6);
  365.     SB_WriteDSP(0x30);
  366.  
  367.     SB_WriteDSP(0xff);
  368.     SB_WriteDSP(0xef);
  369.  
  370.     playing=1;
  371. }
  372.  
  373. static void SB_PlayStop(void)
  374. {
  375.     if ((DMA_SIZE-MDma_Todo(sb_dma))&0xfffc > last)
  376.       while ((DMA_SIZE-MDma_Todo(sb_dma))&0xfffc>last);
  377.  
  378.     while ((DMA_SIZE-MDma_Todo(sb_dma))&0xfffc <last);
  379.  
  380.     MDma_Stop(sb_dma);
  381.     MIrq_OnOff(sb_irq,0);
  382.     SB_SpeakerOff();
  383.     SB_ResetDSP();
  384.     SB_ResetDSP();
  385. }
  386.  
  387.