home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / audio / synthia / synthia.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  12.7 KB  |  667 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  * Copyright (C) 1991, Silicon Graphics, Inc.
  19.  * All Rights Reserved.
  20.  */
  21.  
  22.     /*
  23.      *  synthia  -  A MIDI synthesizer program for Hollywood
  24.      *
  25.      *  Jim Bennett
  26.      *  1991
  27.      *
  28.      *  Added test to see of audio port successfully open
  29.      *  (10/30/91, Marvin Kong).
  30.      */
  31.  
  32. #include <limits.h>
  33. #include <sys/types.h>
  34. #include <sys/prctl.h>
  35. #include <sys/schedctl.h>
  36. #include <sys/time.h>
  37.  
  38. #include <audio.h>
  39. #include <math.h>
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <getopt.h>
  43. #include <signal.h>
  44. #include <gl/gl.h>
  45. #include <gl/device.h>
  46. #include "paths.h"
  47. #include "midif.h"
  48. #include "globj.h"
  49.  
  50.     /*
  51.      * Global variables
  52.      */
  53.  
  54. float    current_volume = 0.5;
  55. int    current_voice = -1;
  56.  
  57. int    dographics;
  58. int    maxvoices;
  59. int    tracklist [MAX_TRACKS];
  60. int    instruments [INSTRUMENTS];
  61. float    beat_time;
  62.  
  63. int    keydowns[128] = {0};
  64. int    maxfinger;
  65.  
  66.     /*
  67.      * Local variables
  68.      */
  69.  
  70. static    int    allups[128] = {0};
  71.  
  72. static    struct    s_mfhd    mf_header;
  73.  
  74. static    struct    s_ptrk    *tracks;
  75.  
  76. static    int    toggle_state;
  77.  
  78.     /*
  79.      *  Input status
  80.      */
  81.  
  82. #define    MAX_VOLUME    0.85
  83. #define    MIN_VOLUME    0.1
  84. #define    MSCALE        0.01
  85.  
  86. static    int    change_volume = FALSE;
  87. static    int    lastx = 0;
  88. static    int    lasty = 0;
  89.  
  90.  
  91.     /*
  92.      *  synthia:  Usage: synthia [options] <midifile>
  93.      *
  94.      *  Options:    -n        No graphics
  95.      *        -v #        Number of voices (default 6)
  96.      *        -t <list>    Play specific tracks only
  97.      *        -i <alist>    Assign instruments
  98.      *        -b #        Set beat time (default .5 seconds)
  99.      */
  100.  
  101. main (argc, argv)
  102.  
  103.     int    argc;
  104.     char    *argv[];
  105.  
  106.     {
  107.     int    c;
  108.     long    param;
  109.     double    fparam;
  110.     char    *ptr;
  111.     FILE    *midifile;
  112.     char    *buf;
  113.     char    *path;
  114.     int    frames, resolution, i, n;
  115.     ALconfig    config;
  116.     ALport    audio_out;
  117.     long    parambuf[2];
  118.  
  119.     printf ("Synthia version 1.3\n");
  120.  
  121. /* Process command line arguments    */
  122.  
  123.     dographics = 1;                /* Set defaults        */
  124.     maxvoices = 6;
  125.     for (i=0; i<MAX_TRACKS; i++)
  126.         tracklist[i] = 1;        /* Play all tracks    */
  127.     for (i=0; i<INSTRUMENTS; i++)
  128.         instruments[i] = i;        /* Default instruments    */
  129.     beat_time = 0.5;
  130.  
  131.     while ((c = getopt (argc, argv, "nv:t:i:b:")) != -1)
  132.         {
  133.         switch (c)
  134.             {
  135.             case 'n':
  136.                 dographics = 0;
  137.                 break;
  138.  
  139.             case 'v':
  140.                 param = strtol (optarg, &ptr, 10);
  141.                 if ((ptr == optarg) ||
  142.                     (*ptr && !isspace (*ptr)))
  143.                     {
  144.         printf ("Bad argument for v option\n\n");
  145.                     print_usage ();
  146.                     exit (1);
  147.                     }
  148.                 if ((param < 0) || (param >= MAX_VOICES))
  149.                     {
  150.         printf ("Max voices of range (0-%d)\n\n", MAX_VOICES-1);
  151.                     print_usage ();
  152.                     exit (1);
  153.                     }
  154.                 maxvoices = param;
  155.                 break;
  156.  
  157.             case 't':
  158.                 if (process_tracklist (optarg))
  159.                     {
  160.                     print_usage ();
  161.                     exit (1);
  162.                     }
  163.                 break;
  164.  
  165.             case 'i':
  166.                 if (process_instlist (optarg))
  167.                     {
  168.                     print_usage ();
  169.                     exit (1);
  170.                     }
  171.                 break;
  172.  
  173.             case 'b':
  174.                 fparam = strtod (optarg, &ptr);
  175.                 if ((ptr == optarg) ||
  176.                     (*ptr && !isspace (*ptr)))
  177.                     {
  178.                 printf ("Bad argument for b option\n\n");
  179.                     print_usage ();
  180.                     exit (1);
  181.                     }
  182.                 beat_time = fparam;
  183.                 break;
  184.  
  185.             default:
  186.                 printf ("\n");
  187.                 print_usage ();
  188.                 exit (1);
  189.             }
  190.         }
  191.  
  192. /* The final argument is the MIDI file        */
  193. /* Validate the file and read in the header    */
  194.  
  195.     if (optind != argc-1)
  196.         {
  197.         print_usage ();
  198.         exit (1);
  199.         }
  200.  
  201.     midifile = fopen (argv[optind], "r");
  202.     if ((midifile == NULL) && (*argv[optind] != '/'))
  203.         {
  204.         if (!(path = getenv("SYNTHIA_MIDI_PATH")))
  205.             path = MIDI_PATH;
  206.         buf = (char *)malloc
  207.             (strlen(argv[optind]) + strlen(path) + 2);
  208.         strcpy (buf, path);
  209.         strcat (buf, "/");
  210.         strcat (buf, argv[optind]);
  211.         midifile = fopen (buf, "r");
  212.         }
  213.     if (midifile == NULL)
  214.         {
  215.         fprintf (stderr, "Can't open %s\n", argv[optind]);
  216.         exit (1);
  217.         }
  218.  
  219.     if (mf_read_hd (midifile, &mf_header) < 0)
  220.         {
  221.         fprintf (stderr, "%s is not a valid MIDI file\n",
  222.                 argv[optind]);
  223.         exit (1);
  224.         }
  225.  
  226. /* Put up a window if we are doing graphics    */
  227.  
  228.     if (dographics)
  229.         {
  230.         keepaspect (2, 1);
  231.         fflush (midifile);
  232.                 /* Needed because winopen does a fork,    */
  233.                 /* and new POSIX compliant stdio gets    */
  234.                 /* confused by forks.            */
  235.         winopen ("MIDI synthesizer");
  236.         RGBmode ();
  237.         gconfig ();
  238.         RGBcolor (0, 0, 0);
  239.         clear ();
  240.  
  241.         shademodel (FLAT);
  242.         backface (TRUE);
  243.         zbuffer (TRUE);
  244.         subpixel (TRUE);
  245.  
  246.         def_curs ();
  247.         setcursor (BUSY_BEE_1, 0, 0);
  248.         start_waiting ();
  249.  
  250.         def_kbd ();
  251.         draw_scene (FALSE);
  252.  
  253.         qdevice (WINSHUT);
  254.         qdevice (WINQUIT);
  255.         qdevice (WINCLOSE);
  256.         qdevice (LEFTMOUSE);
  257.         qdevice (MOUSEX); qdevice (MOUSEY);
  258.         }
  259.  
  260. /* File opened, and header is valid, print it out    */
  261.  
  262. #ifdef DEBUG
  263.     printf ("MIDI file header:\n");
  264.     printf ("  format = %d\n", mf_header.format);
  265.     printf ("  ntrks = %d\n", mf_header.ntrks);
  266.     printf ("  division = %d\n", mf_header.division);
  267. #endif
  268.  
  269.     if (mf_header.format != 1)
  270.         {
  271.         fprintf (stderr, "\nOnly format 1 is supported.\n");
  272.         exit (1);
  273.         }
  274.  
  275. /* Compute time resolution    */
  276.  
  277.     if ((mf_header.division & 0x8000) == 0x8000)
  278.         {    /* Real time mode    */
  279.         frames = (mf_header.division >> 8) & 0xff;
  280.         frames = 256 - frames;
  281.         resolution = mf_header.division & 0xff;
  282.         resolution = resolution * frames;
  283.         }
  284.     else
  285.             /* Else is quarter note division        */
  286.         resolution = mf_header.division * (1.0/beat_time);
  287.  
  288. /* Then read in the tracks    */
  289.  
  290.     tracks = (struct s_ptrk *)malloc
  291.             (sizeof(struct s_ptrk) * mf_header.ntrks);
  292.     for (i=0; i<mf_header.ntrks; i++)
  293.         {
  294.         tracks[i].base = (struct s_mfevent *)mf_read_trk
  295.                         (midifile, resolution);
  296.         n = (int)tracks[i].base;
  297.         if (n < 0)
  298.             {
  299.             printf ("Bad MIDI file: error %d\n", n);
  300.             exit (1);
  301.             }
  302.         tracks[i].nfingers = maxfinger;
  303.  
  304.     /* Disable all tracks that aren't selected    */
  305.  
  306.         if (!tracklist[i])
  307.             (tracks[i].base)->time = END_TIME;
  308.         }
  309.  
  310. /* Now the data is in a handy format, try playing the tracks    */
  311.  
  312. /* First initialize waveform tables and audio ports        */
  313.  
  314.     wf_init ();            /* Initialize wave form tables    */
  315.     wl_init ();            /* Initialize wavelength table    */
  316.  
  317.     config = ALnewconfig ();
  318.  
  319.     ALsetwidth (config, AL_SAMPLE_16);
  320.     ALsetqueuesize (config, 2*SAMPLE_BUFSIZE);
  321.     parambuf[0] = AL_OUTPUT_RATE;
  322.     parambuf[1] = SYNTHIA_RATE;
  323.     ALsetparams (AL_DEFAULT_DEVICE, parambuf, 2);
  324.  
  325.     audio_out = ALopenport ("outport", "w", config);
  326.  
  327.     /*  Test if audio port OK. */
  328.     if( audio_out == 0 ) {
  329.         printf("\nERROR:  Could not open audio port.\n");
  330.         exit(0);
  331.     }
  332.  
  333. /* All ready, set up non-degrading priority and get to work    */
  334.  
  335.     if (schedctl (NDPRI, 0, NDPNORMMAX+10) < 0)
  336.         perror ("schedctl");
  337.     stop_waiting ();
  338.     setcursor (0, 0, 0);
  339.  
  340.     playtracks (audio_out, mf_header.ntrks, tracks);
  341.  
  342.     while (ALgetfilled(audio_out) > 0)
  343.         sleep (1);
  344.  
  345.     ALcloseport (audio_out);
  346.     }
  347.  
  348.     /*
  349.      *  process_tracklist  -  Process comma separated list of tracks
  350.      *            to play
  351.      *
  352.      *    Returns 1 if error
  353.      */
  354.  
  355. process_tracklist (list)
  356.  
  357.     char    *list;
  358.  
  359.     {
  360.     int    i;
  361.     char    *ptr;
  362.     long    track, endtrack;
  363.  
  364.     for (i=0; i<MAX_TRACKS; i++)
  365.         tracklist[i] = 0;
  366.     ptr = list;
  367.     while (*list && !isspace(*list))
  368.         {
  369.         track = strtol (list, &ptr, 10);
  370.         if (ptr == list)
  371.             {
  372.             printf ("Bad track list\n\n");
  373.             return (1);
  374.             }
  375.         if (isspace(*ptr) || (*ptr == ',') || (*ptr == 0))
  376.             {
  377.             if ((track < 0) || (track >= MAX_TRACKS))
  378.                 {
  379. printf ("track number out of range (0-%d)\n\n", MAX_TRACKS-1);
  380.                 return (1);
  381.                 }
  382.             tracklist[track] = 1;
  383.             if (*ptr == ',') ptr++;
  384.             }
  385.         else if (*ptr == '-')
  386.             {        /* Handle range of tracks    */
  387.             ptr++;
  388.             list = ptr;
  389.             endtrack = strtol (list, &ptr, 10);
  390.             if (ptr == list)
  391.                 {
  392.                 printf ("Bad track list\n\n");
  393.                 return (1);
  394.                 }
  395.             if (isspace(*ptr) || (*ptr == ',') || (*ptr == 0))
  396.                 {
  397.                 if ((endtrack < 0) || (endtrack >= MAX_TRACKS))
  398.                     {
  399. printf ("track number out of range (0-%d)\n\n", MAX_TRACKS-1);
  400.                     return (1);
  401.                     }
  402.                 for (i=track; i<=endtrack; i++)
  403.                     tracklist[i] = 1;
  404.                 if (*ptr == ',') ptr++;
  405.                 }
  406.             else
  407.                 {
  408.                 printf ("Bad track list\n\n");
  409.                 return (1);
  410.                 }
  411.             }
  412.         else
  413.             {
  414.             printf ("Bad track list\n\n");
  415.             return (1);
  416.             }
  417.         list = ptr;
  418.         }
  419.     return (0);
  420.     }
  421.  
  422.     /*
  423.      *  process_instlist  -  Process comma separated list of instrument
  424.      *            assignments
  425.      *
  426.      *    Returns 1 if error
  427.      */
  428.  
  429. process_instlist (list)
  430.  
  431.     char    *list;
  432.  
  433.     {
  434.     char    *ptr;
  435.     long    inst1, inst2;
  436.  
  437.     ptr = list;
  438.     while (*list && !isspace(*list))
  439.         {
  440.         inst1 = strtol (list, &ptr, 10);
  441.         if ((ptr == list) || (*ptr != '='))
  442.             {
  443.             printf ("Bad instrument assignment\n\n");
  444.             return (1);
  445.             }
  446.         if ((inst1<0) || (inst1 >= INSTRUMENTS))
  447.             {
  448. printf ("instrument number out of range (0-%d)\n\n", INSTRUMENTS-1);
  449.             return (1);
  450.             }
  451.         ptr++;
  452.         list = ptr;
  453.  
  454.         inst2 = strtol (list, &ptr, 10);
  455.         if ((ptr == list) || (*ptr && !isspace(*ptr) && (*ptr != ',')))
  456.             {
  457.             printf ("Bad instrument assignment\n\n");
  458.             return (1);
  459.             }
  460.         if ((inst2<0) || (inst2 >= INSTRUMENTS))
  461.             {
  462. printf ("instrument number out of range (0-%d)\n\n", INSTRUMENTS-1);
  463.             return (1);
  464.             }
  465.  
  466.         instruments[inst1] = inst2;
  467.         if (*ptr == ',') ptr++;
  468.         list = ptr;
  469.         }
  470.     return (0);
  471.     }
  472.  
  473.     /*
  474.      *  print_usage  -  Print out usage message
  475.      */
  476.  
  477. print_usage ()
  478.  
  479.     {
  480.   printf ("Usage: synthia [options] <midifile>\n");
  481.   printf ("Options:  -n          No graphics\n");
  482.   printf ("          -v #        Number of voices (default 6)\n");
  483.   printf ("          -t <list>   Play specific tracks only\n");
  484.   printf ("          -i <alist>  Assign instruments\n");
  485.   printf ("          -b #        Set beat time (default .5 seconds)\n");
  486.     }
  487.  
  488.     /*
  489.      *  check_input  -  Check for input and handle it
  490.      */
  491.  
  492. check_input ()
  493.  
  494.     {
  495.     long    idev;
  496.     short    idata;
  497.     int    do_redraw;
  498.     int    do_slider;
  499.     int    do_buttons;
  500.     int    mx, my, dx, dy;
  501.     int    picked, new_voice;
  502.  
  503.     do_redraw = FALSE;
  504.     do_slider = FALSE;
  505.     do_buttons = FALSE;
  506.     while (qtest ())
  507.         {
  508.         idev = qread (&idata);
  509.         switch (idev)
  510.             {
  511.             case REDRAW:
  512.                 do_redraw = TRUE;
  513.                 break;
  514.  
  515.             case WINQUIT:
  516.             case WINCLOSE:
  517.                 exit (0);
  518.  
  519.             case LEFTMOUSE:
  520.                 if (idata)
  521.                     {
  522.                     picked = check_pick ();
  523.                     if (picked == VPEG)
  524.                         change_volume = TRUE;
  525.                     else
  526.                     if ((picked >= SEL_BUTTON) &&
  527.                         (picked <(SEL_BUTTON+NUM_BUTTONS)))
  528.                         {
  529.                         new_voice = picked-SEL_BUTTON;
  530.                         if (new_voice == current_voice)
  531.                             current_voice = -1;
  532.                         else
  533.                             current_voice = new_voice;
  534.                         do_buttons = TRUE;
  535.                         }
  536.                     restore_projection ();
  537.                     }
  538.                 else
  539.                     change_volume = FALSE;
  540.                 break;
  541.  
  542.             case MOUSEX:
  543.                 mx = idata;
  544.                 my = lasty;
  545.                 goto do_mouse;
  546.  
  547.             case MOUSEY:
  548.                 my = idata;
  549.                 mx = lastx;
  550.  
  551. do_mouse:            if (change_volume && ((my-lasty) != 0))
  552.                     {
  553.                     current_volume += MSCALE * (my-lasty);
  554.                     if (current_volume > MAX_VOLUME)
  555.                         current_volume = MAX_VOLUME;
  556.                     if (current_volume < MIN_VOLUME)
  557.                         current_volume = MIN_VOLUME;
  558.                     do_slider = TRUE;
  559.                     }
  560.  
  561.                 lastx = mx;
  562.                 lasty = my;
  563.                 break;
  564.  
  565.             default:
  566.                 break;
  567.             }
  568.         }
  569.     if (do_redraw)
  570.         draw_scene (FALSE);
  571.     else if (do_slider)
  572.         display_slider (current_volume);
  573.     else if (do_buttons)
  574.         display_buttons (current_voice);
  575.     }
  576.  
  577.     /*
  578.      *  draw_scene  -  Draw complete image
  579.      */
  580.  
  581. draw_scene (in_picking)
  582.  
  583.     int    in_picking;
  584.  
  585.     {
  586.     restore_projection ();
  587.     RGBcolor (BACKGROUND);
  588.     clear ();
  589.     zclear ();
  590.     if (!in_picking) callobj (CASE_OBJ);
  591.     display_slider (current_volume);
  592.     display_buttons (current_voice);
  593.     display_keys (allups);
  594.     }
  595.  
  596.     /*
  597.      *  restore_projection  -  Reset viewport and projection
  598.      */
  599.  
  600. restore_projection ()
  601.  
  602.     {
  603.     reshapeviewport ();
  604.     perspective (150, 2.0, 1.0, 200.0);
  605.     translate (-(CASE_W/2.0), -5.0, -80.0);
  606.     rotate (300, 'x');
  607.     }
  608.  
  609.     /*
  610.      *  start_waiting  -  Enable the busy cursor display
  611.      */
  612.  
  613. start_waiting ()
  614.  
  615.     {
  616.     struct    itimerval    setval;
  617.     void    toggle_cursor ();
  618.  
  619.     toggle_state = FALSE;
  620.     signal (SIGALRM, toggle_cursor);
  621.  
  622.     setval.it_interval.tv_sec = 0;
  623.     setval.it_interval.tv_usec = 250000;
  624.     setval.it_value.tv_sec = 0;
  625.     setval.it_value.tv_usec = 250000;
  626.     setitimer (ITIMER_REAL, &setval, NULL);
  627.     }
  628.  
  629.     /*
  630.      *  stop_waiting  -  Disable the busy cursor display
  631.      */
  632.  
  633. stop_waiting ()
  634.  
  635.     {
  636.     struct    itimerval    setval;
  637.  
  638.     signal (SIGALRM, SIG_IGN);
  639.  
  640.     setval.it_interval.tv_sec = 0;
  641.     setval.it_interval.tv_usec = 0;
  642.     setval.it_value.tv_sec = 0;
  643.     setval.it_value.tv_usec = 0;
  644.     setitimer (ITIMER_REAL, &setval, NULL);
  645.     }
  646.  
  647.     /*
  648.      *  toggle_cursor  -  Toggle the cursor periodically to indicate
  649.      *            a busy state.
  650.      */
  651.  
  652. void toggle_cursor ()
  653.  
  654.     {
  655.     signal (SIGALRM, toggle_cursor);
  656.     if (toggle_state)
  657.         {
  658.         setcursor (BUSY_BEE_1, 0, 0);
  659.         toggle_state = FALSE;
  660.         }
  661.     else
  662.         {
  663.         setcursor (BUSY_BEE_2, 0, 0);
  664.         toggle_state = TRUE;
  665.         }
  666.     }
  667.