home *** CD-ROM | disk | FTP | other *** search
/ PC Loisirs 18 / cd.iso / sharewar / mikm202 / source / drvgus / gusplaym.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-09-18  |  4.8 KB  |  295 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. #include "mtypes.h"
  5.  
  6. #include "forte.h"
  7. #include "gf1proto.h"
  8. #include "gf1hware.h"
  9.  
  10. #include "extern.h"
  11. #include "ultraerr.h"
  12. #include "ultraext.h"
  13.  
  14. #include "mdriver.h"
  15.  
  16.  
  17. extern ULTRA_CFG config;
  18.  
  19. #define MAXHANDLE 125           // should be enough for now
  20.  
  21. ULONG Ultra[MAXHANDLE];
  22. ULONG Ultrs[MAXHANDLE];
  23.  
  24. /* Ultra[] holds the sample dram adresses
  25.    of the samples of a module */
  26.  
  27.  
  28. extern UNIMOD *pf;
  29.  
  30.  
  31. void SetOther(UBYTE voice,ULONG frq,UBYTE ivol,UBYTE pan)
  32. {
  33.     UltraSetFrequency(voice,frq);
  34.     UltraVectorLinearVolume(voice,6U*ivol,0x3f,0);
  35.     UltraSetBalance(voice,pan>>4);
  36. }
  37.  
  38.  
  39. void HandleVolume(int voice)
  40. {
  41.     UWORD vol;
  42.     ULONG base,start,size,reppos,repend;
  43.     GHOLD *aud;
  44.  
  45.     aud=&ghld[voice];
  46.  
  47.     if(aud->kick){
  48.  
  49.         aud->kick=0;
  50.  
  51.         base=Ultra[aud->handle];
  52.  
  53.         start=aud->start;
  54.         reppos=aud->reppos;
  55.         repend=aud->repend;
  56.         size=aud->size;
  57.  
  58.         if(aud->flags&SF_16BITS){
  59.             start<<=1;
  60.             reppos<<=1;
  61.             repend<<=1;
  62.             size<<=1;
  63.         }
  64.  
  65.         /* Stop current sample and start a new one */
  66.  
  67.         UltraStopVoice(voice);
  68.  
  69.         SetOther(voice,aud->frq,aud->vol,aud->pan);
  70.  
  71.         if(aud->flags&SF_LOOP){
  72.  
  73.             // Start a looping sample
  74.  
  75.             UltraStartVoice(voice,
  76.                             base+start,
  77.                             base+reppos,
  78.                             base+repend,0x8|((aud->flags&SF_16BITS)?4:0)|
  79.                             ((aud->flags&SF_BIDI)?16:0));
  80.         }
  81.         else{
  82.  
  83.             // Start a one-shot sample
  84.  
  85.             UltraStartVoice(voice,
  86.                             base+start,
  87.                             base+start,
  88.                             base+size+2,(aud->flags&SF_16BITS)?4:0);
  89.         }
  90.     }
  91. }
  92.  
  93.  
  94. void GUS_Update(void)
  95. {
  96.     int t;
  97.     GHOLD *aud;
  98.  
  99.     for(t=0;t<md_numchn;t++){
  100.  
  101.         aud=&ghld[t];
  102.  
  103.         if(aud->kick){
  104.             if(UltraReadVolume(t)<100){
  105.                 HandleVolume(t);
  106.             }
  107.             else{
  108.                 UltraVectorLinearVolume(t,0,0x3f,VL_WAVE_IRQ);
  109.             }
  110.         }
  111.         else{
  112.             SetOther(t,aud->frq,aud->vol,aud->pan);
  113.         }
  114.     }
  115. }
  116.  
  117.  
  118.  
  119. WORD GUS_Load(FILE *fp,ULONG length,ULONG loopstart,ULONG loopend,UWORD flags)
  120. /*
  121.     callback routine for the MODLOAD module.
  122.  
  123.     fp                      :file ptr to that sample
  124.     smp                     :Sampleinfo of the sample that is being loaded.
  125. */
  126. {
  127.     int handle,t;
  128.     long p,l;
  129.  
  130.     SL_Init(fp,flags,flags|SF_SIGNED);
  131.  
  132.     // Find empty slot to put sample address in
  133.  
  134.     for(handle=0;handle<MAXHANDLE;handle++){
  135.         if(Ultra[handle]==0) break;
  136.     }
  137.  
  138.     if(handle==MAXHANDLE){
  139.         myerr=ERROR_OUT_OF_HANDLES;
  140.         return -1;
  141.     }
  142.  
  143.     if(flags&SF_16BITS){
  144.         length<<=1;
  145.         loopstart<<=1;
  146.         loopend<<=1;
  147.     }
  148.  
  149.     // Allocate GUS dram and store the address in Ultra[handle]
  150.     // Alloc 8 bytes more for anticlick measures. see below.
  151.  
  152.     if(UltraMemAlloc(length+8,&Ultra[handle])!=ULTRA_OK){
  153.         myerr=ERROR_SAMPLE_TOO_BIG;
  154.         return -1;
  155.     }
  156.  
  157.     // Load the sample
  158.  
  159.     Ultrs[handle]=length+8;
  160.     p=Ultra[handle];
  161.     l=length;
  162.  
  163.     while(l>0){
  164.         char buffer[512];
  165.         long todo;
  166.  
  167.         todo=(l>512) ? 512 : l;
  168.  
  169.         SL_Load(buffer,todo);
  170.  
  171.         UltraDownload(buffer,0,p,todo+8,TRUE);
  172.  
  173.         p+=todo;
  174.         l-=todo;
  175.     }
  176.  
  177.     if(flags&SF_LOOP && !(flags&SF_BIDI)){  // looping sample ?
  178.  
  179.         /*      Anticlick for looping samples:
  180.             Copy the first bytes in the loop
  181.             beyond the end of the loop */
  182.  
  183.         for(t=0;t<8;t++){
  184.             UltraPoke(Ultra[handle]+loopend+t,
  185.                       UltraPeek(Ultra[handle]+loopstart+t));
  186.         }
  187.     }
  188.     else{
  189.  
  190.         /*      Anticlick for one-shot samples:
  191.             Zero the bytes beyond the end of the sample.
  192.         */
  193.  
  194.         for(t=0;t<8;t++){
  195.             UltraPoke(Ultra[handle]+length+t,0);
  196.         }
  197.     }
  198.  
  199.     return handle;
  200. }
  201.  
  202.  
  203.  
  204. void GUS_UnLoad(WORD handle)
  205. /*
  206.     callback routine to unload samples
  207.  
  208.     smp                     :sampleinfo of sample that is being freed
  209. */
  210. {
  211.     UltraMemFree(Ultrs[handle],Ultra[handle]);
  212.     Ultra[handle]=0;
  213. }
  214.  
  215.  
  216.  
  217. BOOL GUS_Init(void)
  218. {
  219.     if(!(md_mode&DMODE_16BITS)){
  220.         md_mode|=DMODE_16BITS;          // gus can't do 8 bit mixing
  221.     }
  222.  
  223.     if(!(md_mode&DMODE_STEREO)){
  224.         md_mode|=DMODE_STEREO;          // gus can't do mono mixing
  225.     }
  226.  
  227.     /* get gus config */
  228.  
  229.     if(!UltraGetCfg(&config)){
  230.         myerr="Ultrasound env. string not found..";
  231.         return 0;
  232.     }
  233.  
  234.     /* Set up 14 channels */
  235.  
  236.     if(UltraOpen(&config,14)==NO_ULTRA){
  237.         myerr="No ultrasound card found";
  238.         return 0;
  239.     }
  240.  
  241.     /* Grab the 80 microsecond timer handler */
  242.  
  243.     UltraVolumeHandler(HandleVolume);
  244.     return 1;
  245. }
  246.  
  247.  
  248.  
  249. void GUS_Exit(void)
  250. {
  251.     UltraClose();
  252. }
  253.  
  254.  
  255.  
  256. void GUS_PlayStart(void)
  257. {
  258.     // init number of voices
  259.  
  260.     UltraNumVoices((md_numchn<14)?14:md_numchn);
  261.     md_mixfreq=(md_numchn<=14) ? 44100 : (617400L/md_numchn);
  262.  
  263.     // Let's make some noise !
  264.  
  265.     UltraEnableOutput();
  266. }
  267.  
  268.  
  269.  
  270. void GUS_PlayStop(void)
  271. {
  272.     UltraDisableOutput();
  273. }
  274.  
  275.  
  276. BOOL GUS_IsThere(void)
  277. {
  278.     return(getenv("ULTRASND")!=NULL);
  279. }
  280.  
  281.  
  282. DRIVER gusdriver={
  283.     NULL,
  284.     "Gravis Ultrasound",
  285.     "MikMod GUS Driver v0.2 (uses the GUS-SDK 2.11)",
  286.     GUS_IsThere,
  287.     GUS_Load,
  288.     GUS_UnLoad,
  289.     GUS_Init,
  290.     GUS_Exit,
  291.     GUS_PlayStart,
  292.     GUS_PlayStop,
  293.     GUS_Update
  294. };
  295.