home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / Apps / SoundApps / TimeWarp / Source / DACPlayer.h < prev    next >
Encoding:
Text File  |  1995-06-12  |  7.0 KB  |  237 lines

  1. /*
  2.  * DACPlayer.h
  3.  * Implementation of an object to play sound over the soundout device (DACs).
  4.  * 
  5.  * You may freely copy, distribute, and reuse the code in this example.
  6.  * NeXT disclaims any warranty of any kind, expressed or  implied, as to its
  7.  * fitness for any particular use.
  8.  *
  9.  * Written by: Robert Poor
  10.  * Created: Sep/92
  11.  */
  12.  
  13. #import <sound/sounddriver.h>
  14. #import <sound/soundstruct.h>
  15.  
  16. /* Tag for DMA messages going to sndout */
  17. #define WRITE_TAG    2
  18.  
  19. #define HIGH_WATER    ((512+256)*1024)
  20. #define LOW_WATER    (512 * 1024)
  21. #define READ_BUF_SIZE    (vm_page_size / sizeof(short))
  22.  
  23. /* The states that the recorder can be in. */
  24. typedef enum {
  25.   PLA_STOPPED,        /* stopped, ports & resources freed */
  26.   PLA_PAUSED,        /* ports allocated, awaiting DMA size from host */
  27.   PLA_RUNNING,        /* running... */
  28.   PLA_STOPPING,        /* draining remaining regions before stopping */
  29.   N_PLA_STATES
  30.   } Pla_state_t;
  31.   
  32. /*
  33.  * values for dacPlayerFlags
  34.  */
  35. typedef struct {
  36.   unsigned int willPlay:1;    /* does delegate respond to willPlay? */
  37.   unsigned int didPlay:1;    /* ... */
  38.   unsigned int playData:1;
  39.   unsigned int didChangeState:1;
  40.   } dacplayer_flags_t;
  41.  
  42.  
  43. @interface DACPlayer:Object
  44. {
  45.   Pla_state_t playerState;    /* current state of the player object */
  46.   int regionsQueued;        /* # of regions currently queued */
  47.   int bytesPlayed;
  48.   int bytesQueued;
  49.  
  50.   id    delegate;        /* the target of notification messages */
  51.   int    samplingRate;        /* sampling rate 44100 or 22050 */
  52.   int    regionSize;        /* # of bytes per call to playData */
  53.   int    regionCount;        /* # of regions to be queued in advance */
  54.   /*
  55.    * It's not necessarily safe to update parameters while the DAC is
  56.    * running, so we squirrel away the user-settable parameters and update
  57.    * from them only when it's safe...
  58.    */
  59.   int    newSamplingRate, newRegionSize, newRegionCount;
  60.  
  61.   port_t devicePort;
  62.   port_t ownerPort;
  63.   port_t streamPort;
  64.   port_t replyPort;
  65.   dacplayer_flags_t flags;    /* various bits */
  66. }
  67.  
  68. - init;
  69. - free;
  70.  
  71. /*
  72.  * METHODS THAT CONTROL DACPLAYER
  73.  */
  74.  
  75. - prepare;
  76. /*
  77.  * Prepares the DACPlayer object for playing.
  78.  * 
  79.  * Upon entry, if the DACPlayer is running, we stop it first with a call
  80.  * to [dacPlayer stop].  The prepare method then acquires all the resources
  81.  * it needs (ports, soundout, etc), and calls [delegate willPlay:self].
  82.  * Even though the stream is left in a "paused" state, the delegate method
  83.  * [delegate playData:::] will be called regionCount times to fill up the
  84.  * region queue.  The DACPlayer state is set to PLA_PAUSED.
  85.  *
  86.  * Returns nil if some resource couldn't be acquired.
  87.  */
  88.  
  89. - run;
  90. /*
  91.  * Starts (or resumes) the DACPlayer.  If the state is PLA_STOPPED, then
  92.  * the run method first calls [self prepare] to set up the stream.  Otherwise,
  93.  * if the state is anything but PLA_PAUSED, run simply returns nil.
  94.  *
  95.  * Otherwise, the stream is "unpaused" and the DACPlayer will start sending
  96.  * data to the DACs.  The DACPlayer will start calling he delegate method
  97.  * [delegate playData:::] to fetch the data to be played.
  98.  *
  99.  * The DACPlayer state is set to PLA_RUNNING.
  100.  */
  101.  
  102. - pause;
  103. /*
  104.  * Upon entry, if the DACPlayer state is PLA_STOPPED, the pause method
  105.  * simply returns [self prepare].  If the state is anything else besides
  106.  * PLA_RUNNING, the pause method returns nil.
  107.  *
  108.  * Suspend output to the DACs.  This merely pauses the sound stream, so it
  109.  * stops making requests of [delegate playData:::].  Note that any buffers
  110.  * of data that have been queued won't get played until the stream is run
  111.  * again.
  112.  *
  113.  * The DACPlayer state is set to PLA_PAUSED.
  114.  */
  115.  
  116. - stop;
  117. /*
  118.  * Stop playing immediately.
  119.  * If the DACPlayer state is PLA_STOPPED, then this method simply returns.
  120.  * Otherwise, it frees all the resources acquired in -setup, calls
  121.  * [delegate didPlay:] and sets the state to PLA_STOPPED.
  122.  */
  123.  
  124. - finish;
  125. /*
  126.  * Do a graceful shutdown of the DACPlayer.
  127.  * If the DACPlayer state is PLA_RUNNING, then the DACPlayer will stop
  128.  * enqueuing new regions (and will stop calling playData:::) and will set
  129.  * the state to PLA_STOPPING.  When the last available buffer has been played
  130.  * by the sound driver, then the DACPlayer will call [self stop].  This all
  131.  * means that any sound that has been queued up will get played before the
  132.  * DACPlayer shuts down.
  133.  */
  134.  
  135. /*
  136.  * METHODS THAT CONFIGURE DACPLAYER
  137.  */
  138.  
  139. - delegate;
  140. - setDelegate:anObject;
  141. /*
  142.  * get/set the delegate for the dacPlayer.  Strictly speaking, you don't need
  143.  * a delegate in order to use dacPlayer, but the delegate is responsible
  144.  * for doing something interesting with the data buffers (via the didPlay:::
  145.  * method) before the buffers are sent to the DACs.  So you will always
  146.  * supply a delegate with a didPlay::: method unless you want to send streams
  147.  * of zeros to the DACs.
  148.  */
  149.  
  150. - (int)regionSize;
  151. - (int)regionCount;
  152. - setRegionSize:(int)bytes andCount:(int)count;
  153. /*
  154.  * Sets (or gets) the size of each sound region and the number of regions 
  155.  * that we keep queued up for the sound driver.
  156.  */
  157.  
  158. - (int)samplingRate;
  159. - setSamplingRate:(int)aRate;
  160. /*
  161.  * get/set the sampling rate for the DACs.  aRate must be either 44100 (the
  162.  * default) or 22050.  Sampling rate changes won't take effect until the
  163.  * next call to -prepare
  164.  */
  165.  
  166. /*
  167.  * METHODS THAT QUERY DACPLAYER
  168.  */
  169.  
  170. - (Pla_state_t)playerState;
  171. /*
  172.  * gets the current state of the dac player, one of:
  173.  *    PLA_STOPPED    stopped and idle, no resources allocated
  174.  *    PLA_PAUSED    no sound playing, DAC resources allocated
  175.  *    PLA_RUNNING    sound actively playing, DAC resources allocated
  176.  *    PLA_STOPPING    sound actively playing, but will stop soon
  177.  */
  178.  
  179. - (int)bytesPlayed;
  180. - (int)samplesPlayed;
  181. - (int)framesPlayed;
  182. - (double)secondsPlayed;
  183. /*
  184.  * These methods return how many bytes, samples, sample frames have actually
  185.  * been sent to the DACs since the most recent call to -prepare.  (NB: two
  186.  * stereo samples make up one sample frame).
  187.  */
  188.  
  189. - (int)bytesQueued;
  190. - (int)samplesQueued;
  191. - (int)framesQueued;
  192. - (double)secondsQueued;
  193. /*
  194.  * These methods return how many bytes, samples, sample frames have been
  195.  * queued up for playing (and possible played).
  196.  */
  197.  
  198. @end
  199.  
  200. /***
  201.  *** DELEGATE METHODS
  202.  ***
  203.  *** Description of the Player's delegate methods
  204.  ***/
  205.  
  206. @interface PlayerDelegate:Object
  207.  
  208. - willPlay :player;
  209. /*
  210.  * Called by the player when going from a stopped to a paused state.  Called
  211.  * after all the resources have been allocated but before any regions get
  212.  * queued.  The various dacPlayer configuration parameters MAY be set from
  213.  * a willPlay: method.
  214.  */
  215.  
  216. - didPlay :player;
  217. /*
  218.  * Called when the player goes into a stopped state (either from a stop or
  219.  * abort message) after all the sound resources have been freed.
  220.  */
  221.  
  222. - playData :player :(char *)data :(int)nbytes;
  223. /*
  224.  * Called whenever the player wants more sound data.  player is the dacPlayer
  225.  * requesting the data, data is a buffer of length nbytes.  The buffer is
  226.  * guaranteed to be zero'd out.  The dacPlayer requires that the samples you
  227.  * write are stereo 16 bit samples.  The samples will be played at whatever
  228.  * sampling rate you established in a call to setSamplingRate:
  229.  */
  230.  
  231. - didChangeState :player from:(Pla_state_t)oldState to:(Pla_state_t)newState;
  232. /*
  233.  * Called whenever the player changes state.
  234.  */
  235.  
  236. @end
  237.