home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / irix / playEngine / demo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  13.1 KB  |  454 lines

  1. /*
  2.  * Copyright (C) 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.  * Demonstration program for using the routines in PlayEngine.c.
  19.  *----------------------------------------------------------------------*/
  20.  
  21. /*----------------------------------------------------------------------
  22.  *  III   N   N   CCC   L     U   U  DDDD   EEEEE   SSS
  23.  *   I    NN  N  C   C  L     U   U  D   D  E      S   S
  24.  *   I    NN  N  C      L     U   U  D   D  E      S
  25.  *   I    N N N  C      L     U   U  D   D  EEE     SSS
  26.  *   I    N  NN  C      L     U   U  D   D  E          S
  27.  *   I    N  NN  C   C  L     U   U  D   D  E      S   S
  28.  *  III   N   N   CCC   LLLL   UUU   DDDD   EEEEE   SSS
  29.  *----------------------------------------------------------------------*/
  30.  
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <errno.h>
  35. #include <sys/types.h>
  36. #include <sys/prctl.h>
  37. #include <sys/time.h>
  38. #include <sys/schedctl.h>
  39. #include <sys/resource.h>
  40. #include <malloc.h>
  41.  
  42. #include <fcntl.h>
  43.  
  44. #include <audio.h>
  45. #include <audiofile.h>
  46.  
  47. /*------------------------------------------------------------------------
  48.  * DDDD   EEEEE  FFFFF   III   N   N  EEEEE   SSS
  49.  * D   D  E      F        I    NN  N  E      S   S
  50.  * D   D  E      F        I    NN  N  E      S
  51.  * D   D  EEE    FFF      I    N N N  EEE     SSS
  52.  * D   D  E      F        I    N  NN  E          S
  53.  * D   D  E      F        I    N  NN  E      S   S
  54.  * DDDD   EEEEE  F       III   N   N  EEEEE   SSS
  55.  *------------------------------------------------------------------------*/
  56.  
  57. static char    *ProgName;
  58. static int    samps_per_frame;    /* frame size */
  59. static int    bytes_per_samp;        /* sample width */
  60. static int    bytes_per_buf;        /* bytes / sample buffer */
  61. static int    frames_per_buf;        /* frames / sample buffer */
  62. static double    secs_per_buf;        /* time to play one sample buffer */
  63. static char    *sampbuf;        /* sample buffer */
  64. static double    secs_per_frame;        /* time to play one audio frame */
  65. static double    file_rate;        /* audio file sample rate */
  66. static long    compression;        /* audio data compression type */
  67. static long    filefmt;        /* input file format */
  68. static int    samps_per_buf;        /* samples / sample buffer */
  69. static long    bits_per_samp;        /* sample resolution */
  70. static int    frames_per_sec;        /* sample rate */
  71.  
  72. AFfilehandle    afHandle;
  73. ALport        audio_port;
  74.  
  75. int        ndPriority = NDPHIMAX;
  76. int        ProcessPriority = PRIO_MIN;
  77. int        PGPriority = PRIO_MIN;
  78. int        UserPriority = PRIO_MIN;
  79.  
  80. /*------------------------------------------------------------------------
  81.  * afError
  82.  *    Routine to handle audio file errors.
  83.  *------------------------------------------------------------------------*/
  84.  
  85. static void afError (long code, const char *desc)
  86. {
  87.     fprintf(stderr, "%s: (Audio File Library error %d): %s\n", ProgName,
  88.         code, desc);
  89. }
  90.  
  91. /*------------------------------------------------------------------------
  92.  * play_engine_thread
  93.  *    The routine that will be called to play audio data.
  94.  *------------------------------------------------------------------------*/
  95.  
  96. void play_engine_thread (void)
  97. {
  98.     int num_bufs;
  99.     int leftover_bytes;
  100.     int leftover_samps;
  101.     int leftover_frames;
  102.     int samp_count;
  103.     int frame_count;
  104.     double sec_count;
  105.     int i;
  106.     int bytes_read;
  107.     int samples_read;
  108.     int frames_read;
  109.     int done;
  110.     int total_frames;   
  111.     int total_samps;
  112.     int total_samp_bytes;
  113.     float file_playingtime;
  114.     char compressionname[10];
  115.     float fileplayingtime;
  116.  
  117.     sec_count = 0.0;
  118.     
  119.     /*
  120.      * figure out how many reads we have to do
  121.      */
  122.     total_frames    =  AFgetframecnt(afHandle, AF_DEFAULT_TRACK);
  123.     if (total_frames > 0) {
  124.     total_samps      =  total_frames * samps_per_frame;
  125.     total_samp_bytes =  total_samps * bytes_per_samp;
  126.     num_bufs         = total_samp_bytes / bytes_per_buf;
  127.     leftover_bytes   = total_samp_bytes % bytes_per_buf;
  128.     leftover_samps   = leftover_bytes / bytes_per_samp;
  129.     leftover_frames  = leftover_samps / samps_per_frame;
  130.     } else {
  131.     /* this could be an undertermined length raw file, or mpeg file */
  132.     num_bufs = -1;
  133.     }
  134.  
  135.     /*
  136.      * move the fileptr to the beginning of the sample data
  137.      */
  138.     AFseekframe(afHandle, AF_DEFAULT_TRACK, 0);
  139.     
  140.     /*
  141.      * note that there may be some pad bytes following the valid samples -
  142.      * for example, the sample data area may be padded so that the valid 
  143.      * samples begin on a block boundary and the sample area ends on a block
  144.      * boundary (where blocksize is specified by the user)
  145.      */
  146.     done        = 0;
  147.     samp_count  = 0;
  148.     frame_count = 0; 
  149.     sec_count   = 0.0;
  150.     
  151.     for (i=0; num_bufs<0 || i<num_bufs; i++)
  152.     {
  153.         samp_count  += samps_per_buf;
  154.         frame_count += frames_per_buf;
  155.         sec_count   += secs_per_buf;
  156.         
  157.         if ((frames_read 
  158.              = AFreadframes(afHandle, AF_DEFAULT_TRACK, 
  159.                             sampbuf, frames_per_buf)) < frames_per_buf)
  160.         {
  161.             done++;
  162.         }
  163.         samples_read = frames_read * samps_per_frame;
  164.         ALwritesamps(audio_port, sampbuf, samples_read);
  165.         if (done)
  166.         {
  167.             /*
  168.              * allow the audio buffer to drain
  169.              */
  170.             while(ALgetfilled(audio_port) > 0) {
  171.                 sginap(1);
  172.             }
  173.             sginap(10);
  174.             return;
  175.         }
  176.     }
  177.     /*
  178.      * play the leftovers
  179.      */
  180.     samp_count  += leftover_samps;
  181.     frame_count += leftover_frames;
  182.     sec_count   += ((double)leftover_frames) * secs_per_frame;
  183.     frames_read = AFreadframes(afHandle, AF_DEFAULT_TRACK, sampbuf, 
  184.                    leftover_frames);
  185.     samples_read = frames_read * samps_per_frame;
  186.     ALwritesamps(audio_port, sampbuf, samples_read);
  187.     
  188.     /*
  189.      * allow the audio buffer to drain
  190.      */
  191.     while(ALgetfilled(audio_port) > 0) {
  192.         sginap(1);
  193.     }
  194.     sginap(10);
  195.     return;
  196. }
  197.  
  198. /* ******************************************************************
  199.  *  GetInputRate:    return Audio Hardware input sampling rate
  200.  * ****************************************************************** */
  201.     int
  202. GetInputRate()
  203. {
  204. long buf[6];
  205.  
  206. buf[0] = AL_INPUT_RATE;
  207. buf[2] = AL_INPUT_SOURCE;
  208. buf[4] = AL_DIGITAL_INPUT_RATE;
  209. ALgetparams(AL_DEFAULT_DEVICE, buf, 6);
  210.  
  211. /* we are clocked off digital input. find real input rate, if possible. */
  212. if    ((buf[1] == AL_RATE_AES_1)||(buf[3] == AL_INPUT_DIGITAL)) 
  213.     {
  214.     if (ALgetdefault(AL_DEFAULT_DEVICE, AL_DIGITAL_INPUT_RATE) >= 0) 
  215.     return (buf[5]);
  216.     }
  217. /* input rate is Hz and we're using an analog input */
  218. else if (buf[1] > 0) 
  219.     return (buf[1]);
  220.  
  221. return (AL_RATE_UNDEFINED);
  222. } /* --------------------- end GetInputRate() --------------- */
  223.  
  224. /* ******************************************************************
  225.  *  GetOutputRate:    return Audio Hardware output sampling rate
  226.  * ****************************************************************** */
  227.     int
  228. GetOutputRate()
  229. {
  230. long buf[4];
  231.  
  232. buf[0] = AL_OUTPUT_RATE;
  233. buf[2] = AL_DIGITAL_INPUT_RATE;
  234. ALgetparams(AL_DEFAULT_DEVICE, buf, 4);
  235.  
  236. /* output rate is in Hz -- return it */
  237. if (buf[1] > 0) 
  238.     return (buf[1]);
  239.  
  240. /* output rate is logical -- track down what it means */
  241. else 
  242.     {
  243.     if        (buf[1] == AL_RATE_AES_1) 
  244.     {
  245.     /* we are clocked off of digital input. find
  246.      * real input rate, if system supports this ability.
  247.      * Otherwise, return AL_RATE_UNDEFINED */
  248.     if (ALgetdefault(AL_DEFAULT_DEVICE,AL_DIGITAL_INPUT_RATE) >= 0) 
  249.         return (buf[3]);
  250.     }
  251.     else if (buf[1] == AL_RATE_INPUTRATE) 
  252.     return (GetInputRate());
  253.     return (AL_RATE_UNDEFINED);
  254.     }
  255. } /* --------------------- end GetOutputRate() --------------- */
  256.  
  257. /* ******************************************************************
  258.  *  InitAudio():    initialize audio port and global state of IRIS Audio 
  259.  *            Hardware
  260.  * ****************************************************************** */
  261.     static int 
  262. InitAudio(AFfilehandle audio_file, ALport *audio_port)
  263. {
  264.     ALconfig audio_port_config;
  265.     long pvbuf[4];
  266.     long audio_rate, output_rate;
  267.     long samp_type;
  268.     long samp_wordsize;    
  269.     long vers;
  270.     int err;
  271.     
  272.     samps_per_frame   = AFgetchannels(audio_file, AF_DEFAULT_TRACK);
  273.     file_rate         = AFgetrate(audio_file, AF_DEFAULT_TRACK);
  274.     compression       = AFgetcompression(audio_file, AF_DEFAULT_TRACK);
  275.     filefmt           = AFgetfilefmt(audio_file, &vers);
  276.     
  277.     AFgetsampfmt(audio_file, AF_DEFAULT_TRACK, &samp_type, &bits_per_samp);
  278.     
  279.     /*
  280.      * need to determine whether audio is in use. if not, then we
  281.      * can just go ahead and be "rude."
  282.      */
  283.     pvbuf[0] = AL_OUTPUT_COUNT;
  284.     pvbuf[2] = AL_MONITOR_CTL;
  285.     if (ALgetparams(AL_DEFAULT_DEVICE, pvbuf, 4) < 0) {
  286.     if (oserror() == AL_BAD_DEVICE_ACCESS) {
  287.         fprintf(stderr,"%s: Can't play -- could not access audio "
  288.             "hardware.\n",ProgName);
  289.         return -1;
  290.     }
  291.     }
  292.  
  293.     
  294.     /* 
  295.      * decide on output rate for the audio hardware
  296.      */
  297.     audio_rate = frames_per_sec = (long) file_rate;
  298.     
  299.     
  300.     /*
  301.      * determine current output rate
  302.      */
  303.     output_rate = GetOutputRate();
  304.  
  305.     /*
  306.      * if the rates are the same, all is well. if not, then we need to proceed
  307.      * in a either a "rude" or "polite" manner.
  308.      */
  309.     
  310.     if (output_rate != audio_rate)
  311.     {
  312.         /*
  313.          *  we set the rate to our value in Hz.  ALsetparams will set
  314.      *  the hardware to the closest rate to audio_rate which the
  315.      *  hardware supports.
  316.          */
  317.  
  318.     output_rate = audio_rate;
  319.     pvbuf[0] = AL_OUTPUT_RATE;
  320.     pvbuf[1] = output_rate;
  321.     ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 2);
  322.     }
  323.     
  324.     
  325.     /*
  326.      * decide what size blocks of samples we should read from the
  327.      * input file and pass to ALwritesamps
  328.      */
  329.     if (bits_per_samp <= 8)
  330.     {
  331.         bytes_per_samp = 1;
  332.         samp_wordsize  = AL_SAMPLE_8;
  333.     }
  334.     else if (bits_per_samp <= 16)
  335.     {
  336.         bytes_per_samp = 2;
  337.         samp_wordsize  = AL_SAMPLE_16;
  338.     }
  339.     else if (bits_per_samp <= 24)
  340.     {
  341.         bytes_per_samp = 4;
  342.         samp_wordsize  = AL_SAMPLE_24;
  343.     }
  344.     else
  345.     {
  346.         return(-1);
  347.     }
  348.     
  349.     if ((samps_per_frame != 1)&&(samps_per_frame!= 2)&&(samps_per_frame!=4))
  350.     {
  351.         return(-1);
  352.     }
  353.     
  354.     /*
  355.      * make the buffer large enough to hold 1/2 sec of audio frames
  356.      * we add one to frames_per_sec before we divide in order to
  357.      * correctly handle the 11025 case
  358.      */
  359.     secs_per_frame = 1.0 / ((double)frames_per_sec);
  360.     frames_per_buf = (frames_per_sec+1)/2;
  361.     
  362.     samps_per_buf = frames_per_buf * samps_per_frame;
  363.     bytes_per_buf = samps_per_buf * bytes_per_samp;
  364.     secs_per_buf  = secs_per_frame * frames_per_buf;
  365.     
  366.     sampbuf = malloc(bytes_per_buf);
  367.     
  368.     /*
  369.      * configure and open audio port
  370.      */
  371.     audio_port_config = ALnewconfig();
  372.     ALsetwidth(audio_port_config, samp_wordsize);
  373.     ALsetchannels(audio_port_config, samps_per_frame);
  374.     
  375.     /*
  376.      * make the ring buffer large enough to hold 1 sec of audio samples
  377.      */
  378.     ALsetqueuesize(audio_port_config, samps_per_buf*2);
  379.     *audio_port = ALopenport(ProgName, "w", audio_port_config);
  380.     if (*audio_port == 0) {
  381.     err = oserror();
  382.     if (err == AL_BAD_NO_PORTS) {
  383.         fprintf(stderr,"%s: Can't play -- no audio ports available at the moment\n",ProgName);
  384.     }
  385.     else if (err == AL_BAD_OUT_OF_MEM) {
  386.         fprintf(stderr,"%s: Can't play -- not enough memory to open audio port\n",ProgName);
  387.     }
  388.     return -1;
  389.     }
  390. } /* --------------------- end InitAudio() --------------- */
  391.  
  392. /*========================================================================
  393.  * MAIN
  394.  *========================================================================*/
  395.  
  396. main (int argc, char *argv[])
  397. {
  398.     int fd;
  399.  
  400.     ProgName = strrchr (argv[0], '/');
  401.     if (ProgName)
  402.     ProgName++;
  403.     else
  404.     ProgName = argv[0];
  405.  
  406.     if (argc < 2)
  407.     {
  408.     fprintf (stderr, "Usage: %s <audio-file>\n", ProgName);
  409.     exit (0);
  410.     }
  411.  
  412.     AFseterrorhandler (afError);
  413.  
  414. #if 1
  415.     if ((fd = open (argv[1], O_RDONLY)) < 0)
  416.     {
  417.     fprintf (stderr, "%s: Error opening file %s\n", ProgName, argv[1]);
  418.     exit (1);
  419.     }
  420.     else if (AFidentifyfd (fd) < 0)
  421.     {
  422.     fprintf (stderr, "%s: %s is not an AIFF-C or AIFF file.\n", ProgName,
  423.          argv[1]);
  424.     exit (1);
  425.     }
  426.  
  427.     afHandle = AFopenfd (fd, "r", AF_NULL_FILESETUP);
  428. #else
  429.     afHandle = AFopenfile (argv[1], "r", AF_NULL_FILESETUP);
  430. #endif
  431.     if (afHandle == AF_NULL_FILEHANDLE)
  432.     {
  433.     fprintf (stderr, "%s: Unable to open file %s for reading.\n",
  434.          ProgName, argv[1]);
  435.     exit (1);
  436.     }
  437.  
  438.     if (InitAudio (afHandle, &audio_port) < 0)
  439.     {
  440.     fprintf (stderr, "%s: Problem initializing audio.\n", ProgName);
  441.     exit (2);
  442.     }
  443.  
  444.     CreateSubProcess ();
  445.  
  446.     StartSubProcess ();
  447.  
  448.     WaitForSubProcess ();
  449.  
  450.     DestroySubProcess ();
  451.  
  452.     AFclosefile (afHandle);
  453. }
  454.