home *** CD-ROM | disk | FTP | other *** search
/ ftp.4front-tech.com / ftp.4front-tech.com.tar / ftp.4front-tech.com / ossfree / snd-util-3.8.tar.gz / snd-util-3.8.tar / sndkit / OSSlib / guslib.c < prev    next >
C/C++ Source or Header  |  1997-02-25  |  6KB  |  275 lines

  1. #ifndef PATCH_PATH
  2. #define PATCH_PATH "/dos/ultrasnd/midi"
  3. #endif
  4.  
  5. #include <stdio.h>
  6. #include <sys/ultrasound.h>
  7. #include <sys/soundcard.h>
  8. #include <sys/ioctl.h>
  9. #include <sys/soundcard.h>
  10. #include <strings.h>
  11. #include <unistd.h>
  12. #include <fcntl.h>
  13. #include "gmidi.h"
  14.  
  15. static int instrmap[256] = {-1, 0};
  16. static int initialized = 0;
  17.  
  18. struct pat_header
  19.   {
  20.     char            magic[12];
  21.     char            version[10];
  22.     char            description[60];
  23.     unsigned char   instruments;
  24.     char            voices;
  25.     char            channels;
  26.     unsigned short  nr_waveforms;
  27.     unsigned short  master_volume;
  28.     unsigned long   data_size;
  29.   };
  30.  
  31. struct sample_header
  32.   {
  33.     char            name[7];
  34.     unsigned char   fractions;
  35.     long            len;
  36.     long            loop_start;
  37.     long            loop_end;
  38.     unsigned short  base_freq;
  39.     long            low_note;
  40.     long            high_note;
  41.     long            base_note;
  42.     short           detune;
  43.     unsigned char   panning;
  44.  
  45.     unsigned char   envelope_rate[6];
  46.     unsigned char   envelope_offset[6];
  47.  
  48.     unsigned char   tremolo_sweep;
  49.     unsigned char   tremolo_rate;
  50.     unsigned char   tremolo_depth;
  51.  
  52.     unsigned char   vibrato_sweep;
  53.     unsigned char   vibrato_rate;
  54.     unsigned char   vibrato_depth;
  55.  
  56.     char            modes;
  57.  
  58.     short           scale_frequency;
  59.     unsigned short  scale_factor;
  60.   };
  61.  
  62. SEQ_USE_EXTBUF();
  63.  
  64. int             seqfd;
  65.  
  66. int
  67. get_dint(unsigned char *p)
  68. {
  69.     int i;
  70.     unsigned int v=0;
  71.  
  72.     for (i=0;i<4;i++)
  73.         {
  74.         v |= (p[i] << (i*8));
  75.      }
  76.     return (int)v;
  77. }
  78.  
  79. unsigned short
  80. get_word(unsigned char *p)
  81. {
  82.     int i;
  83.     unsigned short v=0;
  84.  
  85.     for (i=0;i<2;i++)
  86.         v |= (*p++ << (i*8));
  87.     return (short)v;
  88. }
  89.  
  90. short
  91. get_int(unsigned char *p)
  92. {
  93.    return (short)get_word(p);
  94. }
  95.  
  96. int
  97. gusinit(int seqfd, int dev)
  98. {
  99.  
  100.       initialized=1;
  101.  
  102.     if (ioctl (seqfd, SNDCTL_SEQ_RESETSAMPLES, &dev) == -1)
  103.     {
  104.         fprintf(stderr, "OSSlib: Can't reset GM programs. Device %d\n",
  105.                 dev);
  106.         perror("GUS init");
  107.         exit(-1);
  108.     }
  109.  
  110.     return 0;
  111. }
  112.  
  113. int
  114. gusload (int seqfd, int type, int dev, int pgm)
  115. {
  116.   int             i, n, patfd, print_only = 0;
  117.   struct synth_info info;
  118.   struct pat_header header;
  119.   struct sample_header sample;
  120.   unsigned char buf[256];
  121.   char            name[256];
  122.   long            offset;
  123.   struct patch_info *patch;
  124.  
  125.   if (!initialized)
  126.      gusinit(seqfd, dev);
  127.  
  128.   if (pgm<0 || pgm>255)
  129.      return 0;
  130.  
  131.   if (instrmap[pgm] == pgm)
  132.      return 0;
  133.  
  134.   instrmap[pgm] = pgm;
  135.  
  136.   if (patch_names[pgm][0] == 0) /* Not defined */
  137.      return 0;
  138.  
  139.   sprintf (name, PATCH_PATH "/%s.pat", patch_names[pgm]);
  140. /* fprintf(stderr, "Loading instrument %d from %s\n", pgm, name); */
  141.  
  142.   if ((patfd = open (name, O_RDONLY, 0)) == -1)
  143.     {
  144.       perror (name);
  145.       return 0;
  146.     }
  147.  
  148.   if (read (patfd, buf, 0xef) != 0xef)
  149.     {
  150.       fprintf (stderr, "%s: Short file\n", name);
  151.       exit (-1);
  152.     }
  153.  
  154.   memcpy ((char *) &header, buf, sizeof (header));
  155.  
  156.   if (strncmp (header.magic, "GF1PATCH110", 12))
  157.     {
  158.       fprintf (stderr, "%s: Not a patch file\n", name);
  159.       exit (-1);
  160.     }
  161.  
  162.   if (strncmp (header.version, "ID#000002", 10))
  163.     {
  164.       fprintf (stderr, "%s: Incompatible patch file version\n", name);
  165.       exit (-1);
  166.     }
  167.  
  168.   header.nr_waveforms = get_word(&buf[85]);
  169.   header.master_volume = get_word(&buf[87]);
  170.  
  171.   offset = 0xef;
  172.  
  173.   for (i = 0; i < header.nr_waveforms; i++)
  174.     {
  175.       if (lseek (patfd, offset, 0) == -1)
  176.     {
  177.       perror (name);
  178.       exit (-1);
  179.     }
  180.  
  181.       if (read (patfd, &buf, sizeof (sample)) != sizeof (sample))
  182.     {
  183.       fprintf (stderr, "%s: Short file\n", name);
  184.       exit (-1);
  185.     }
  186.  
  187.       memcpy ((char *) &sample, buf, sizeof (sample));
  188.  
  189.       sample.fractions = (char)buf[7];
  190.       sample.len = get_dint(&buf[8]);
  191.       sample.loop_start = get_dint(&buf[12]);
  192.       sample.loop_end = get_dint(&buf[16]);
  193.       sample.base_freq = get_word(&buf[20]);
  194.       sample.low_note = get_dint(&buf[22]);
  195.       sample.high_note = get_dint(&buf[26]);
  196.       sample.base_note = get_dint(&buf[30]);
  197.       sample.detune = get_int(&buf[34]);
  198.       sample.panning = (unsigned char) buf[36];
  199.  
  200.       memcpy (sample.envelope_rate, &buf[37], 6);
  201.       memcpy (sample.envelope_offset, &buf[43], 6);
  202.  
  203.       sample.tremolo_sweep = (unsigned char) buf[49];
  204.       sample.tremolo_rate = (unsigned char) buf[50];
  205.       sample.tremolo_depth = (unsigned char) buf[51];
  206.  
  207.       sample.vibrato_sweep = (unsigned char) buf[52];
  208.       sample.vibrato_rate = (unsigned char) buf[53];
  209.       sample.vibrato_depth = (unsigned char) buf[54];
  210.       sample.modes = (unsigned char) buf[55];
  211.       sample.scale_frequency = get_int(&buf[56]);
  212.       sample.scale_factor = get_word(&buf[58]);
  213.  
  214.       offset = offset + 96;
  215.       patch = (struct patch_info *) malloc (sizeof (*patch) + sample.len);
  216.       if (patch == NULL)
  217.      {
  218.         fprintf(stderr, "Failed to allocate %d bytes of memory\n",
  219.                 sizeof (*patch) + sample.len);
  220.         exit(0);
  221.      }
  222.  
  223.       patch->key = GUS_PATCH;
  224.       patch->device_no = dev;
  225.       patch->instr_no = pgm;
  226.       patch->mode = sample.modes | WAVE_TREMOLO |
  227.     WAVE_VIBRATO | WAVE_SCALE;
  228.       patch->len = sample.len;
  229.       patch->loop_start = sample.loop_start;
  230.       patch->loop_end = sample.loop_end;
  231.       patch->base_note = sample.base_note;
  232.       patch->high_note = sample.high_note;
  233.       patch->low_note = sample.low_note;
  234.       patch->base_freq = sample.base_freq;
  235.       patch->detuning = sample.detune;
  236.       patch->panning = (sample.panning - 7) * 16;
  237.  
  238.       memcpy (patch->env_rate, sample.envelope_rate, 6);
  239.       memcpy (patch->env_offset, sample.envelope_offset, 6);
  240.  
  241.       patch->tremolo_sweep = sample.tremolo_sweep;
  242.       patch->tremolo_rate = sample.tremolo_rate;
  243.       patch->tremolo_depth = sample.tremolo_depth;
  244.  
  245.       patch->vibrato_sweep = sample.vibrato_sweep;
  246.       patch->vibrato_rate = sample.vibrato_rate;
  247.       patch->vibrato_depth = sample.vibrato_depth;
  248.  
  249.       patch->scale_frequency = sample.scale_frequency;
  250.       patch->scale_factor = sample.scale_factor;
  251.  
  252.       patch->volume = header.master_volume;
  253.  
  254.       if (lseek (patfd, offset, 0) == -1)
  255.     {
  256.       perror (name);
  257.       exit (-1);
  258.     }
  259.  
  260.       if (read (patfd, patch->data, sample.len) != sample.len)
  261.         {
  262.           fprintf (stderr, "%s: Short file\n", name);
  263.           exit (-1);
  264.         }
  265.  
  266.       SEQ_WRPATCH (patch, sizeof (*patch) + sample.len);
  267.  
  268.       offset = offset + sample.len;
  269.     }
  270.     
  271.     close(patfd);
  272.     free(patch);
  273.     return 0;
  274. }
  275.