home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / code / c_play.sit < prev    next >
Encoding:
Text File  |  1988-06-20  |  11.5 KB  |  371 lines

  1. 18-Jun-88 14:51:42-MDT,6055;000000000001
  2. Return-Path: <u-lchoqu%sunset@cs.utah.edu>
  3. Received: from cs.utah.edu by SIMTEL20.ARPA with TCP; Sat, 18 Jun 88 14:51:34 MDT
  4. Received: by cs.utah.edu (5.54/utah-2.0-cs)
  5.     id AA22810; Sat, 18 Jun 88 14:51:32 MDT
  6. Received: by sunset.utah.edu (5.54/utah-2.0-leaf)
  7.     id AA24890; Sat, 18 Jun 88 14:51:30 MDT
  8. Date: Sat, 18 Jun 88 14:51:30 MDT
  9. From: u-lchoqu%sunset@cs.utah.edu (Lee Choquette)
  10. Message-Id: <8806182051.AA24890@sunset.utah.edu>
  11. To: rthum@simtel20.arpa
  12. Subject: play.c
  13.  
  14. /*
  15.  *  play.c - use the mac II sound chip to play a sampled sound in chunks.
  16.  *  The eventual purpose is to do some animation in synch with the music.
  17.  *  Written in MPW C by Dwight Hare, March, 1988.
  18.  */
  19.  
  20. /* The following defines and data structures are used from sound.h:
  21.  *
  22.  *  #define callBackCmd         13
  23.  *  #define bufferCmd           81
  24.  *  #define initMono            0x80
  25.  *  
  26.  *  typedef struct SndCommand {
  27.  *      unsigned short          cmd;
  28.  *      short                   param1;
  29.  *      long                    param2;
  30.  *  } SndCommand;
  31.  *  
  32.  *  typedef struct SndChannel {
  33.  *      struct SndChannel       *nextChan;
  34.  *      ModifierStubPtr         firstMod;
  35.  *      ProcPtr                 callBack;
  36.  *      long                    userInfo;
  37.  *      Time                    wait;
  38.  *      SndCommand              cmdInProgress;
  39.  *      short                   flags;
  40.  *      short                   qLength;
  41.  *      short                   qHead;
  42.  *      short                   qTail;
  43.  *      SndCommand              queue[stdQLength];
  44.  *  } SndChannel, *SndChannelPtr;
  45.  *  
  46.  *  typedef struct SoundHeader {
  47.  *      char                * samplePtr;
  48.  *      unsigned long       length;
  49.  *      Fixed               sampleRate;
  50.  *      unsigned long       loopStart;
  51.  *      unsigned long       loopEnd;
  52.  *      short               baseNote;
  53.  *      char                sampleArea[0];
  54.  *  } SoundHeader, *SoundHeaderPtr;
  55.  */
  56.  
  57.  
  58. #define __ALLNU__       /* needed to get new sound stuff in Sound.h */
  59. #include <memory.h>
  60. #include <sound.h>
  61. #include <toolutils.h>
  62.  
  63. #define NIL (Ptr)0
  64.  
  65. /*  
  66.  *  This callback routine is used to indicate when a sound has finished
  67.  *  (I haven't found any other way to do it).
  68.  */
  69. pascal void
  70. snd_done(chan, cmd)
  71. SndChannelPtr chan;
  72. SndCommand *cmd;
  73. {
  74.     chan->userInfo = 1;
  75. }
  76.  
  77. /*
  78.  *  play plays the given sound in "sample" of length "len" at the sampled
  79.  *  rate "rate" (typically 22255 for a Soundwave sample at the highest
  80.  *  rate) and plays the sound in "incr" chunks (22255 would play in
  81.  *  one second chunks at the rate of 22255).
  82.  */
  83. OSErr
  84. play(sample, len, rate, incr)
  85. unsigned char *sample;
  86. long len, rate, incr;
  87. {
  88.     unsigned char *Sp;
  89.     SndChannelPtr sndp = NIL;
  90.     SndCommand playcmd, callcmd;
  91.     SoundHeaderPtr playbuf, playbuf1, playbuf2;
  92.     long i;
  93.     OSErr err;
  94.  
  95.     /*
  96.      *  We need two buffers for the bufferCmd since the first one
  97.      *  isn't quite finished when we set up the second one.
  98.      */
  99.     playbuf1 = (SoundHeaderPtr)NewPtr(sizeof(SoundHeader));
  100.     playbuf2 = (SoundHeaderPtr)NewPtr(sizeof(SoundHeader));
  101.     if (playbuf1 == NIL || playbuf2 == NIL) {
  102.         return(-1);
  103.     }
  104.     /*
  105.      *  The loopStart, loopEnd, and baseNote are for playing the
  106.      *  sampled sounds as notes, we are not using that feature.
  107.      */
  108.     playbuf1->sampleRate = FixRatio(rate, 1);
  109.     playbuf2->sampleRate = FixRatio(rate, 1);
  110.     playbuf1->loopStart = 0;
  111.     playbuf2->loopStart = 0;
  112.     playbuf1->loopEnd = 0;
  113.     playbuf2->loopEnd = 0;
  114.     playbuf1->baseNote = 60;
  115.     playbuf2->baseNote = 60;
  116.  
  117.     /*
  118.      *  Create a new sound channel using the sampled synthesizer played
  119.      *  in mono.  The callback routine will be used below to determine
  120.      *  the end of the sound.
  121.      */
  122.     if ((err = SndNewChannel(&sndp, sampledSynth, initMono, snd_done))
  123.             != noErr) {
  124.         return(err);
  125.     }
  126.     
  127.     /*
  128.      *  The playcmd is used in a SndDoCommand.  The bufferCmd plays the
  129.      *  buffer pointed to by param2 (set below).
  130.      */
  131.     playcmd.cmd = bufferCmd;
  132.     playcmd.param1 = 0;
  133.     
  134.     /*
  135.      *  The callcmd is used in a SndDoCommand.  The callBackCmd calls
  136.      *  the callback routine (snd_done) specified in the SndNewChannel
  137.      *  call.  This callback will be put after each play cmd to indicate
  138.      *  when a sound has (almost) finished.
  139.      */
  140.     callcmd.cmd = callBackCmd;
  141.     callcmd.param1 = 0;
  142.     callcmd.param2 = 0;
  143.     
  144.     /* We start with the first playbuf */
  145.     playbuf = playbuf1;
  146.  
  147.     for (i = len, Sp = sample; i > 0; i -= incr, Sp += incr) {
  148.             /* change buffers */
  149.         if (playbuf == playbuf1)
  150.             playbuf = playbuf2;
  151.         else playbuf = playbuf1;
  152.             /* set the buffer length to either the increment or
  153.                the rest of the sample */
  154.         playbuf->length = i < incr? i : incr;
  155.             /* Set the pointer to the sound to be played */
  156.         playbuf->samplePtr = Sp;
  157.         /*
  158.          *  Set the bufferCmd pointer to this buffer.  This command
  159.          *  buffer is copied by the SndDoCommand so we don't need
  160.          *  two of them
  161.          */
  162.         playcmd.param2 = (long)playbuf;
  163.             /* set the flag we use in snd_done to indicate the finish */
  164.         sndp->userInfo = 0;
  165.             /* Play the buffer */
  166.         if ((err = SndDoCommand(sndp, &playcmd, true)) != noErr) {
  167.             return(err);
  168.         }
  169.             /* Put the callback in the queue after the sound */
  170.         if ((err = SndDoCommand(sndp, &callcmd, true)) != noErr) {
  171.             return(err);
  172.         }
  173.             /* Now wait for the sound to finish (later we'll do some
  174.                animation) */
  175.         while(sndp->userInfo != 1);
  176.     }
  177.     /*
  178.      *  Cleanup
  179.      */
  180.     if ((err = SndDisposeChannel(sndp, false)) != noErr) {
  181.             return(err);
  182.     }
  183.     DisposPtr(playbuf1); DisposPtr(playbuf2);
  184.     return(noErr);
  185. }
  186. 18-Jun-88 14:51:42-MDT,6055;000000000001
  187. Return-Path: <u-lchoqu%sunset@cs.utah.edu>
  188. Received: from cs.utah.edu by SIMTEL20.ARPA with TCP; Sat, 18 Jun 88 14:51:34 MDT
  189. Received: by cs.utah.edu (5.54/utah-2.0-cs)
  190.     id AA22810; Sat, 18 Jun 88 14:51:32 MDT
  191. Received: by sunset.utah.edu (5.54/utah-2.0-leaf)
  192.     id AA24890; Sat, 18 Jun 88 14:51:30 MDT
  193. Date: Sat, 18 Jun 88 14:51:30 MDT
  194. From: u-lchoqu%sunset@cs.utah.edu (Lee Choquette)
  195. Message-Id: <8806182051.AA24890@sunset.utah.edu>
  196. To: rthum@simtel20.arpa
  197. Subject: play.c
  198.  
  199. /*
  200.  *  play.c - use the mac II sound chip to play a sampled sound in chunks.
  201.  *  The eventual purpose is to do some animation in synch with the music.
  202.  *  Written in MPW C by Dwight Hare, March, 1988.
  203.  */
  204.  
  205. /* The following defines and data structures are used from sound.h:
  206.  *
  207.  *  #define callBackCmd         13
  208.  *  #define bufferCmd           81
  209.  *  #define initMono            0x80
  210.  *  
  211.  *  typedef struct SndCommand {
  212.  *      unsigned short          cmd;
  213.  *      short                   param1;
  214.  *      long                    param2;
  215.  *  } SndCommand;
  216.  *  
  217.  *  typedef struct SndChannel {
  218.  *      struct SndChannel       *nextChan;
  219.  *      ModifierStubPtr         firstMod;
  220.  *      ProcPtr                 callBack;
  221.  *      long                    userInfo;
  222.  *      Time                    wait;
  223.  *      SndCommand              cmdInProgress;
  224.  *      short                   flags;
  225.  *      short                   qLength;
  226.  *      short                   qHead;
  227.  *      short                   qTail;
  228.  *      SndCommand              queue[stdQLength];
  229.  *  } SndChannel, *SndChannelPtr;
  230.  *  
  231.  *  typedef struct SoundHeader {
  232.  *      char                * samplePtr;
  233.  *      unsigned long       length;
  234.  *      Fixed               sampleRate;
  235.  *      unsigned long       loopStart;
  236.  *      unsigned long       loopEnd;
  237.  *      short               baseNote;
  238.  *      char                sampleArea[0];
  239.  *  } SoundHeader, *SoundHeaderPtr;
  240.  */
  241.  
  242.  
  243. #define __ALLNU__       /* needed to get new sound stuff in Sound.h */
  244. #include <memory.h>
  245. #include <sound.h>
  246. #include <toolutils.h>
  247.  
  248. #define NIL (Ptr)0
  249.  
  250. /*  
  251.  *  This callback routine is used to indicate when a sound has finished
  252.  *  (I haven't found any other way to do it).
  253.  */
  254. pascal void
  255. snd_done(chan, cmd)
  256. SndChannelPtr chan;
  257. SndCommand *cmd;
  258. {
  259.     chan->userInfo = 1;
  260. }
  261.  
  262. /*
  263.  *  play plays the given sound in "sample" of length "len" at the sampled
  264.  *  rate "rate" (typically 22255 for a Soundwave sample at the highest
  265.  *  rate) and plays the sound in "incr" chunks (22255 would play in
  266.  *  one second chunks at the rate of 22255).
  267.  */
  268. OSErr
  269. play(sample, len, rate, incr)
  270. unsigned char *sample;
  271. long len, rate, incr;
  272. {
  273.     unsigned char *Sp;
  274.     SndChannelPtr sndp = NIL;
  275.     SndCommand playcmd, callcmd;
  276.     SoundHeaderPtr playbuf, playbuf1, playbuf2;
  277.     long i;
  278.     OSErr err;
  279.  
  280.     /*
  281.      *  We need two buffers for the bufferCmd since the first one
  282.      *  isn't quite finished when we set up the second one.
  283.      */
  284.     playbuf1 = (SoundHeaderPtr)NewPtr(sizeof(SoundHeader));
  285.     playbuf2 = (SoundHeaderPtr)NewPtr(sizeof(SoundHeader));
  286.     if (playbuf1 == NIL || playbuf2 == NIL) {
  287.         return(-1);
  288.     }
  289.     /*
  290.      *  The loopStart, loopEnd, and baseNote are for playing the
  291.      *  sampled sounds as notes, we are not using that feature.
  292.      */
  293.     playbuf1->sampleRate = FixRatio(rate, 1);
  294.     playbuf2->sampleRate = FixRatio(rate, 1);
  295.     playbuf1->loopStart = 0;
  296.     playbuf2->loopStart = 0;
  297.     playbuf1->loopEnd = 0;
  298.     playbuf2->loopEnd = 0;
  299.     playbuf1->baseNote = 60;
  300.     playbuf2->baseNote = 60;
  301.  
  302.     /*
  303.      *  Create a new sound channel using the sampled synthesizer played
  304.      *  in mono.  The callback routine will be used below to determine
  305.      *  the end of the sound.
  306.      */
  307.     if ((err = SndNewChannel(&sndp, sampledSynth, initMono, snd_done))
  308.             != noErr) {
  309.         return(err);
  310.     }
  311.     
  312.     /*
  313.      *  The playcmd is used in a SndDoCommand.  The bufferCmd plays the
  314.      *  buffer pointed to by param2 (set below).
  315.      */
  316.     playcmd.cmd = bufferCmd;
  317.     playcmd.param1 = 0;
  318.     
  319.     /*
  320.      *  The callcmd is used in a SndDoCommand.  The callBackCmd calls
  321.      *  the callback routine (snd_done) specified in the SndNewChannel
  322.      *  call.  This callback will be put after each play cmd to indicate
  323.      *  when a sound has (almost) finished.
  324.      */
  325.     callcmd.cmd = callBackCmd;
  326.     callcmd.param1 = 0;
  327.     callcmd.param2 = 0;
  328.     
  329.     /* We start with the first playbuf */
  330.     playbuf = playbuf1;
  331.  
  332.     for (i = len, Sp = sample; i > 0; i -= incr, Sp += incr) {
  333.             /* change buffers */
  334.         if (playbuf == playbuf1)
  335.             playbuf = playbuf2;
  336.         else playbuf = playbuf1;
  337.             /* set the buffer length to either the increment or
  338.                the rest of the sample */
  339.         playbuf->length = i < incr? i : incr;
  340.             /* Set the pointer to the sound to be played */
  341.         playbuf->samplePtr = Sp;
  342.         /*
  343.          *  Set the bufferCmd pointer to this buffer.  This command
  344.          *  buffer is copied by the SndDoCommand so we don't need
  345.          *  two of them
  346.          */
  347.         playcmd.param2 = (long)playbuf;
  348.             /* set the flag we use in snd_done to indicate the finish */
  349.         sndp->userInfo = 0;
  350.             /* Play the buffer */
  351.         if ((err = SndDoCommand(sndp, &playcmd, true)) != noErr) {
  352.             return(err);
  353.         }
  354.             /* Put the callback in the queue after the sound */
  355.         if ((err = SndDoCommand(sndp, &callcmd, true)) != noErr) {
  356.             return(err);
  357.         }
  358.             /* Now wait for the sound to finish (later we'll do some
  359.                animation) */
  360.         while(sndp->userInfo != 1);
  361.     }
  362.     /*
  363.      *  Cleanup
  364.      */
  365.     if ((err = SndDisposeChannel(sndp, false)) != noErr) {
  366.             return(err);
  367.     }
  368.     DisposPtr(playbuf1); DisposPtr(playbuf2);
  369.     return(noErr);
  370. }
  371.