home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / sun / volume3 / sparctracker / str.c < prev   
C/C++ Source or Header  |  1992-03-02  |  18KB  |  504 lines

  1. /***********************************************************************/
  2. /*                                                                     */
  3. /* str.c - plays sound/noisetracker files on a SparcStation            */
  4. /*                                                                     */
  5. /* Authors  : Liam Corner - zenith@dcs.warwick.ac.uk                   */
  6. /*            Marc Espie - espie@dmi.ens.fr                            */
  7. /* Version  : 1.20 - 3 November 1991                                   */
  8. /*                                                                     */
  9. /* Usage    : str32 <filename>                                         */
  10. /*            [f|z]cat filename | str32                                */
  11. /*                                                                     */
  12. /***********************************************************************/
  13.  
  14.  
  15. #include <stdio.h>
  16. #include <malloc.h>
  17.  
  18.  
  19. /**********************************************************/
  20. /* uS is the number of uSeconds that a byte is played for */
  21. /* Sparc plays at 8000 bytes/sec  =>  1 byte = 125 uSec   */
  22. /* VSYNC is the number of bytes played in 1/50 sec        */
  23. /* ie 0.02/(uS * 10**-6)                                  */
  24. /**********************************************************/
  25. #define uS 125
  26. #define VSYNC 160
  27. #define AUDIO "/dev/audio"
  28.  
  29. #define MIN(A,B) ((A)<(B) ? (A) : (B))
  30. #define MAX(A,B) ((A)>(B) ? (A) : (B))
  31.  
  32.  
  33. typedef struct {    /***********************************/
  34.   char *info;       /* Sample                          */
  35.   int length;       /* Length of sample                */
  36.   float volume;     /* Fractional volume 0-1 (min-max) */
  37.   int rep_start;    /* Byte offset of repeat start     */
  38.   int rep_end;      /* Byte offset of repeat end       */
  39. } Voice;            /***********************************/
  40.  
  41.  
  42. typedef struct {                 /**************************/
  43.   char sample [64][4];           /* Sample number          */
  44.   char effect [64][4];           /* Effect number          */
  45.   unsigned char params [64][4];  /* Effect parameters      */
  46.   int period [64][4];            /* Period (pitch) of note */
  47. } Pattern;                       /**************************/
  48.  
  49.  
  50. typedef struct {         /***********************************************/
  51.   char samp;             /* Sample number of current note               */
  52.   int pitch;             /* Current channel pitch (index to step_table) */
  53.   int slide;             /* Step size of pitch slide (if any)           */
  54.   int doslide;
  55.   unsigned int pointer;  /* Current sample position                     */
  56.   unsigned int step;     /* Sample offset increment (gives pitch)       */
  57.   float volume;          /* Fractional volume of current note           */
  58.   float volslide;
  59.   int doslidevol;
  60.   int doporta;
  61.   int pitchgoal;
  62.   int portarate;
  63. } Channel;               /***********************************************/
  64.  
  65.  
  66. /*****************************************************************************/
  67. /* Skips the next 'n' input bytes - because fseek won't work on stdin        */
  68. /*****************************************************************************/
  69. void byteskip (fp, bytes)
  70. FILE *fp;
  71. int bytes;
  72.     {
  73.     int loop;
  74.  
  75.     for (loop = 0; loop < bytes; loop++)
  76.         getc(fp);
  77.     }
  78.  
  79.  
  80. /************************************************************************/
  81. /*      For routine 'cvt' only                                          */
  82. /************************************************************************/
  83. /*      Copyright 1989 by Rich Gopstein and Harris Corporation          */
  84. /************************************************************************/
  85.  
  86. unsigned int cvt(ch)
  87. int ch;
  88.     {
  89.     int mask;
  90.  
  91.     if (ch < 0)
  92.         {
  93.         ch = -ch;
  94.         mask = 0x7f;
  95.         }
  96.     else
  97.         mask = 0xff;
  98.  
  99.     if (ch < 32)
  100.         {
  101.         ch = 0xF0 | 15 - (ch / 2);
  102.         }
  103.     else if (ch < 96)
  104.         {
  105.         ch = 0xE0 | 15 - (ch - 32) / 4;
  106.         }
  107.     else if (ch < 224)
  108.         {
  109.         ch = 0xD0 | 15 - (ch - 96) / 8;
  110.         }
  111.     else if (ch < 480)
  112.         {
  113.         ch = 0xC0 | 15 - (ch - 224) / 16;
  114.         }
  115.     else if (ch < 992)
  116.         {
  117.         ch = 0xB0 | 15 - (ch - 480) / 32;
  118.         }
  119.     else if (ch < 2016)
  120.         {
  121.         ch = 0xA0 | 15 - (ch - 992) / 64;
  122.         }
  123.     else if (ch < 4064)
  124.         {
  125.         ch = 0x90 | 15 - (ch - 2016) / 128;
  126.         }
  127.     else if (ch < 8160)
  128.         {
  129.         ch = 0x80 | 15 - (ch - 4064) /  256;
  130.         }
  131.     else
  132.         {
  133.         ch = 0x80;
  134.         }
  135.     return (mask & ch);
  136.     }
  137.  
  138.  
  139. char *getstring(f, len)
  140. FILE *f;
  141. int len;
  142.     {
  143.     static char s[150];
  144.     int i;
  145.  
  146.     for (i = 0; i < len; i++)
  147.         s[i] = fgetc(f);
  148.     s[len] = '\0';
  149.     return s;
  150.     }
  151.  
  152. #define OLD 0
  153. #define NEW 1
  154.  
  155. int main (argc, argv)
  156. int argc;
  157. char **argv;
  158.     {
  159.     FILE *fp, *audio;
  160.     int loop;
  161.     int notes, note, channel, vsync;
  162.     int pat, pat_num;
  163.     int byte, bytes;
  164.     int step_table[1024];
  165.     int speed=6;                      /* Default speed is 6 */
  166.     int end_pattern=0;
  167.     char songlength;
  168.     char tune[128];
  169.     char num_patterns=0;
  170.     unsigned char ulaw;
  171.     float dummy1, dummy2;
  172.     Voice voices[32];
  173.     Pattern patterns[64];
  174.     Channel ch[4];
  175.     int nvoices;
  176.     int effect;
  177.  
  178.     int type;   /* module type: old or new */
  179.     char *command;  /* the actual command name used */
  180.  
  181.     command = argv[0];
  182.     if (strcmp(argv[0], "str32") == 0)
  183.         type = NEW;
  184.     else if (strcmp(argv[0], "str15") == 0)
  185.         type = OLD;
  186.     else
  187.         {
  188.         fprintf(stderr,
  189.             "Error: command should be named either str15 or str32\n");
  190.         exit(1);
  191.         }
  192.  
  193.     if (type == OLD)
  194.         nvoices = 15;
  195.     else
  196.         nvoices = 31;
  197.  
  198.     if (argc>2)
  199.         {
  200.         fprintf(stderr,"Usage: %s [<filename>]\n", command);
  201.         exit(1);
  202.         }
  203.  
  204. /***********************************************************************/
  205. /* Creates a table of the byte_step << 16 for a given pitch            */
  206. /* The step and pointer are stored << 16 to get accuracy without floats*/
  207. /* eg to get double pitch only play every other byte                   */
  208. /* so step of 0x10000 is normal pitch, 0x8000 is half,                 */
  209. /* 0x20000 is double.  Pointer is >> 16 when accessed,                 */
  210. /* so 0x10000 is 1st byte, 0x20000 2nd etc                             */
  211. /* I have no idea where the other numbers are from, I copied them from */
  212. /* a SoundTracker player for the Acorn Archimedes                      */
  213. /*                                                                     */
  214. /* Actually, these other numbers are highly dependent on the amiga hw. */
  215. /***********************************************************************/
  216.     step_table[0] = 0;
  217.     for (loop = 1; loop < 1024; loop++)
  218.         {
  219.         dummy1 = 3575872 / loop;
  220.         dummy2 = (dummy1 / (1000000 /uS) ) * 60000;
  221.         step_table[loop] = (int)dummy2;
  222.         }
  223.  
  224.     if (argc < 2)
  225.         fp = stdin;
  226.     else
  227.         fp = fopen(argv[1], "r");
  228.     if (fp == NULL)
  229.         {
  230.         fprintf(stderr, "%s: unable to open tune file %s\n",
  231.             command, argv[1]);
  232.         exit(1);
  233.         }
  234.  
  235.         /* read song name */
  236.     printf("Module : %s\n\n", getstring(fp, 20));
  237.  
  238.         /* Reads in the sample-information tables */
  239.     for (loop = 1; loop <= nvoices; loop++)
  240.         {
  241.         printf("%6d : %s\n", loop, getstring(fp, 22));
  242.         voices[loop].length = ( (getc(fp) << 8) | getc(fp) ) * 2;
  243.         getc(fp);
  244.         voices[loop].volume = getc(fp);
  245.         voices[loop].volume = MIN(voices[loop].volume, 64);
  246.         voices[loop].volume /= 64;   /* Volume is a fraction */
  247.         voices[loop].rep_start = ( (getc(fp) << 8) | getc(fp) ) * 2;
  248.         voices[loop].rep_end = ( (getc(fp) << 8) | getc(fp) ) * 2;
  249.         if (voices[loop].rep_end <= 4)
  250.             voices[loop].rep_end = 0;
  251.         else
  252.             {
  253.                 /* If there is a repeat then end=start+length, but must be */
  254.                 /* less than the sample length.  Not sure if this is 100%  */
  255.                 /* correct, but it seems to work OK :-)                    */
  256.             if (voices[loop].rep_end + voices[loop].rep_start - 1
  257.                 > voices[loop].length)
  258.                 voices[loop].rep_start >>= 1;
  259.             voices[loop].rep_end += voices[loop].rep_start;
  260.             voices[loop].rep_end = MIN(voices[loop].rep_end,
  261.                 voices[loop].length);
  262.             }
  263.         }
  264.     voices[0].length = 0;
  265.  
  266.     songlength = getc(fp);
  267.     byteskip(fp, 1);
  268.  
  269.         /* Reads in the tune */
  270.     for (loop = 0; loop < 128; loop++)
  271.         {
  272.         tune[loop] = getc(fp);
  273.         if (tune[loop] > num_patterns)
  274.             num_patterns = tune[loop];
  275.         }
  276.     num_patterns++;
  277.  
  278.         /* skip over sig (usually M.K.) */
  279.     if (type == NEW)
  280.         byteskip(fp,4);
  281.  
  282.         /* Reads in the patterns */
  283.     for (pat_num = 0; pat_num < num_patterns; pat_num++)
  284.         {
  285.             /* 64 notes per pattern  */
  286.         for (notes = 0; notes < 64; notes++)
  287.             {
  288.                 /* 4 channels per note   */
  289.             for (channel = 0; channel < 4; channel++)
  290.                 {
  291.                 note = (getc(fp) << 24) | (getc(fp) << 16) |
  292.                     (getc(fp) << 8) | getc(fp);
  293.                 (patterns[pat_num]).effect[notes][channel] =
  294.                     (note & 0xF00) >> 8;
  295.                 (patterns[pat_num]).params[notes][channel] = note & 0xFF;
  296.                 (patterns[pat_num]).sample[notes][channel] =
  297.                     ( (note & 0xF000) >> 12) | ( (note >> 24) & 0x10);
  298.                 (patterns[pat_num]).period[notes][channel] =
  299.                     MIN( (note & 0xFFF0000) >> 16, 1023);
  300.                 }
  301.             }
  302.         }
  303.  
  304.         /* Stores the samples voices as an array of char */
  305.     for (loop = 1; loop <= nvoices; loop++)
  306.         {
  307.         voices[loop].info = malloc(voices[loop].length);
  308.         if (voices[loop].info == NULL)
  309.             {
  310.             fprintf(stderr, "%s: unable to allocate memory\n, command");
  311.             exit(1);
  312.             }
  313.         fread(voices[loop].info, 1, voices[loop].length, fp);
  314.         }
  315.  
  316.     audio = fopen(AUDIO, "w");
  317.     if (audio == NULL)
  318.         {
  319.         fprintf(stderr, "%s: unable to access %s\n", command, AUDIO);
  320.         exit(1);
  321.         }
  322.  
  323.     for (loop = 0; loop < 4; loop++)
  324.         {
  325.         ch[loop].pointer = 0;
  326.         ch[loop].step = 0;
  327.         ch[loop].volume = 0;
  328.         ch[loop].pitch = 0;
  329.         }
  330.  
  331.     printf("\nPosition (%d):", songlength);
  332.     fflush(stdout);
  333.  
  334.     for (pat_num = 0; pat_num < songlength; pat_num++)
  335.         {
  336.         printf("\r\t\t%3d", pat_num);
  337.         fflush(stdout);
  338.         pat = tune[pat_num];
  339.         end_pattern = 0;
  340.         for (notes = 0; notes < 64; notes++)
  341.             {
  342.             for (channel = 0; channel < 4; channel++)
  343.                 {
  344.                 int samp, pitch, cmd, para;
  345.  
  346.                 samp = patterns[pat].sample[notes][channel];
  347.                 pitch = patterns[pat].period[notes][channel];
  348.                 cmd = patterns[pat].effect[notes][channel];
  349.                 para = patterns[pat].params[notes][channel];
  350.                 if (samp)
  351.                     {
  352.                     ch[channel].samp = samp;
  353.                         /* load new instrument */
  354.                     ch[channel].volume = voices[ch[channel].samp].volume;
  355.                     }
  356.                         /* If sample number=0 and no new period */
  357.                         /* continue last note */
  358.                 if (pitch && cmd != 3)
  359.                     {
  360.                     ch[channel].pointer = 0;
  361.                     ch[channel].step = step_table[pitch];
  362.                     ch[channel].pitch = pitch;
  363.                     }
  364.                 ch[channel].doslide = 0;
  365.                 ch[channel].doslidevol = 0;
  366.                 ch[channel].doporta = 0;
  367.                 switch(cmd)  /* Do effects */
  368.                     {
  369.                 case 0xF :
  370.                     speed = para;
  371.                     break;
  372.                 case 0xD :
  373.                     end_pattern = 1;
  374.                     break;
  375.                 case 0xC :
  376.                     ch[channel].volume= MIN(para, 64);
  377.                     ch[channel].volume /= 64;
  378.                     break;
  379.                     /* volume_slide */
  380.         case 0xB :
  381.             pat_num = (para & 0xF) + (10 * (para >> 4));
  382.             break;
  383.                 case 0xA :
  384.                     ch[channel].doslidevol = 1;
  385.                     if (para)
  386.                         {
  387.                         if (para & 15)
  388.                             ch[channel].volslide = - para / 64;
  389.                         else
  390.                             ch[channel].volslide = (para >> 4)/64;
  391.                         }
  392.                     break;
  393.                 case 3   :
  394.                     ch[channel].doporta = 1;
  395.                     if (para)
  396.                         ch[channel].portarate = para;
  397.                     if (pitch)
  398.                         ch[channel].pitchgoal = pitch;
  399.                     break;
  400.                 case 2   :
  401.                     ch[channel].doslide = 1;
  402.                     if (para)
  403.                         ch[channel].slide = para;
  404.                     break;
  405.                 case 1   :
  406.                     ch[channel].doslide = 1;
  407.                     if (para)
  408.                         ch[channel].slide = -para;
  409.                     break;
  410.                 case 0   :
  411.                     break;
  412.                 default  :
  413.                     /* printf(" [%d][%d] ", cmd, para); */
  414.                     break;
  415.                     }
  416.                 }
  417.                 /* 1 vsync = 0.02 sec */
  418.             for (vsync = 0; vsync < speed; vsync++)
  419.                 {
  420.                     /* 160*125uSec = 0.02 */
  421.                 for (bytes = 0; bytes < VSYNC; bytes++)
  422.                     {
  423.                     byte = 0;
  424.                     for (channel = 0; channel < 4; channel++)
  425.                         {
  426.                         if (ch[channel].samp == 0)
  427.                             continue;
  428.                             /* If at end of sample jump to rep_start position */
  429.                         if (voices[ch[channel].samp].rep_end)
  430.                             {
  431.                             if ((ch[channel].pointer >> 16) >=
  432.                                 voices[ch[channel].samp].rep_end)
  433.                                 ch[channel].pointer +=
  434.                                     (voices[ch[channel].samp].rep_start -
  435.                                     voices[ch[channel].samp].length)<< 16;
  436.                             }
  437.                         else
  438.                             if ((ch[channel].pointer >> 16) >=
  439.                                 voices[ch[channel].samp].length)
  440.                                 continue;
  441.                         /* byte = sum of (sample byte * volume) for each */
  442.                         /* of 4 channels which mixes the sounds          */
  443.                         if (ch[channel].pointer >> 16 <
  444.                             voices[ch[channel].samp].length)
  445.                             {
  446.                             byte += (int) ( (voices[ch[channel].samp]
  447.                                 .info[ch[channel].pointer >> 16])
  448.                                 * (ch[channel].volume));
  449.                             ch[channel].pointer += ch[channel].step;
  450.                             }
  451.                         }
  452.                         /* Divide by 4 to get the correct volume */
  453.                     byte /= 4;
  454.                     ulaw = (unsigned char) cvt(byte * 16);/* Convert byte */
  455.                     fputc(ulaw, audio);                /* and play the note */
  456.                     }
  457.                     /* Do end of vsync */
  458.                 if (vsync == 0)
  459.                     continue;
  460.                 for (channel = 0; channel < 4; channel++)
  461.                     {
  462.                     if (ch[channel].doslide)             /* effects */
  463.                         {
  464.                         ch[channel].pitch += ch[channel].slide;
  465.                         ch[channel].pitch = MIN(ch[channel].pitch, 1023);
  466.                         ch[channel].pitch = MAX(ch[channel].pitch, 113);
  467.                         ch[channel].step = step_table[ch[channel].pitch];
  468.                         }
  469.                     if (ch[channel].doslidevol)
  470.                         {
  471.                         ch[channel].volume += ch[channel].volslide;
  472.                         if (ch[channel].volume < 0.0)
  473.                             ch[channel].volume = 0.0;
  474.                         else if (ch[channel].volume >= 1.0)
  475.                             ch[channel].volume = 1.0;
  476.                         }
  477.                     if (ch[channel].doporta)
  478.                         {
  479.                         if (ch[channel].pitch < ch[channel].pitchgoal)
  480.                             {
  481.                             ch[channel].pitch += ch[channel].portarate;
  482.                             if (ch[channel].pitch > ch[channel].pitchgoal)
  483.                                 ch[channel].pitch = ch[channel].pitchgoal;
  484.                             }
  485.                         else if (ch[channel].pitch > ch[channel].pitchgoal)
  486.                             {
  487.                             ch[channel].pitch -= ch[channel].portarate;
  488.                             if (ch[channel].pitch < ch[channel].pitchgoal)
  489.                                 ch[channel].pitch = ch[channel].pitchgoal;
  490.                             }
  491.                         }
  492.                     }
  493.                 }
  494.             if (end_pattern == 1)
  495.                 break;
  496.             }
  497.         }
  498.  
  499.     fclose(audio);
  500.     printf("\n");
  501.     return (0);
  502.     }
  503.  
  504.