home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / tracker-4.13.lha / tracker / Arch / Hpux / alib_audio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-08  |  8.2 KB  |  365 lines

  1. /* hpalib_audio.c 
  2.     vi:ts=3 sw=3:
  3.  */
  4.  
  5. /* port to hp using the Alib library */
  6. /* $Id: alib_audio.c,v 1.1 1995/02/01 16:43:47 espie Exp $
  7.  * $Log: alib_audio.c,v $
  8.  * Revision 1.1  1995/02/01  16:43:47  espie
  9.  * Initial revision
  10.  *
  11.  * Revision 1.1  1995/02/01  16:43:47  espie
  12.  * Initial revision
  13.  *
  14.  * Revision 1.2  1993/12/04  16:12:50  espie
  15.  * BOOL -> boolean.
  16.  *
  17.  * Revision 1.1  1993/07/14  16:33:41  espie
  18.  * Initial revision
  19.  *
  20.  */
  21.  
  22. #include "defs.h"
  23. #include "extern.h"
  24. #include <audio/Alib.h>
  25. #include <sys/socket.h>
  26. #include <netinet/in.h>
  27. #include <netinet/tcp.h>
  28.  
  29. ID("$Id: alib_audio.c,v 1.1 1995/02/01 16:43:47 espie Exp $")
  30.  
  31.  
  32. Audio    *audio;        /* AUDIO connection for Alib, like DISPLAY for Xlib */
  33.  
  34. LOCAL int stereo;        /* are we playing stereo or not? */
  35. LOCAL int freq;            /* which frequency do we want? */
  36.  
  37. LOCAL int primary, secondary;    /* 256th of primary/secondary source for */
  38.                 /* that side. */
  39. AErrorHandler    prevHandler;    /* pointer to previous handler */    
  40.  
  41. LOCAL int    audioPaused = True;
  42. LOCAL int    streamSocket = 0;
  43. LOCAL int    pauseCount;
  44.  
  45. LOCAL short    *inBuf = NULL, *bufBase = NULL;
  46. LOCAL int    inBufIndex = 0;
  47. LOCAL long    inLen;
  48.  
  49. LOCAL ATransID    xid;
  50.  
  51. LOCAL AConvertParams    *convert_params;
  52.  
  53. LOCAL AudioAttrMask    AttribsMask = 0, PlayAttribsMask = 0, ignoredMask = 0;
  54. LOCAL AudioAttributes    Attribs, PlayAttribs;
  55. LOCAL AGainEntry    gainEntry[4];    /* Need to be global since */
  56.                     /* PlayAttribs is global and it */
  57.                     /* contains a pointer to gainEntry */
  58. LOCAL SSPlayParams    streamParams;
  59.  
  60.  
  61.  
  62. long myErrorHandler(audio, err_event)
  63.     Audio        *audio;
  64.     AErrorEvent    *err_event;
  65. {
  66.     char    errorbuf[132];
  67.  
  68.     AGetErrorText(audio, err_event->error_code, errorbuf, 131);
  69.      end_all(errorbuf);
  70. }
  71.  
  72.  
  73. void set_mix(percent)
  74. int percent;
  75. {
  76.     percent = (percent * 256) / 100;
  77.     primary = percent;
  78.     secondary = 512 - percent;
  79. }
  80.  
  81.  
  82. void create_playstream()
  83. {
  84.     LOCAL SStream    audioStream;
  85.  
  86.     /*
  87.      * Initiate transaction.
  88.      */
  89.     xid = APlaySStream(audio, ~0, &PlayAttribs, &streamParams,
  90.                &audioStream, NULL);
  91.  
  92.     /*
  93.      * Create a stream socket.
  94.      */
  95.     streamSocket = socket(AF_INET, SOCK_STREAM, 0);
  96.     if(streamSocket < 0) {
  97.      end_all("Socket creation failed");
  98.     }
  99.   
  100.     /*
  101.      * Connect the stream socket to the audio stream port.
  102.      */
  103.     if (connect(streamSocket,
  104.         (struct sockaddr *)&audioStream.tcp_sockaddr,
  105.         sizeof(struct sockaddr_in)) < 0) {
  106.         end_all("Connect failed");
  107.     }
  108. }  
  109.  
  110.  
  111. int open_audio(f, s)
  112. int f;
  113. int s;
  114. {
  115.     char        *pSpeaker;
  116.     int            useIntSpeaker;
  117.     int            seekOffset, data_length;
  118.     AByteOrder        play_byte_order, byte_order;
  119.  
  120.  
  121.     audio = AOpenAudio(NULL, NULL);
  122.  
  123.     if (!audio) {
  124.         end_all("Error opening audio device");
  125.     }
  126.  
  127.     /* replace default error handler */
  128.     prevHandler = ASetErrorHandler(myErrorHandler);
  129.  
  130.     stereo = s;
  131.     if (stereo) {
  132.         Attribs.attr.sampled_attr.channels = 2;
  133.         AttribsMask |= (AttribsMask | ASChannelsMask);
  134.     }
  135.  
  136.     /*
  137.      * Get the best attributes from the server?
  138.      */
  139.     if (f <= 0) {
  140.     AudioAttributes    *bestAttr;
  141.  
  142.     bestAttr = ABestAudioAttributes(audio);
  143.     freq = bestAttr->attr.sampled_attr.sampling_rate;
  144.     } else
  145.     freq = f;
  146.  
  147.     PlayAttribs.attr.sampled_attr.sampling_rate = freq;
  148.     PlayAttribsMask |= ASSamplingRateMask;
  149.  
  150.     Attribs.attr.sampled_attr.sampling_rate = freq;
  151.     AttribsMask |= ASSamplingRateMask;
  152.  
  153.     AChooseSourceAttributes(audio, NULL, NULL, AFFRawLin16,
  154.                 AttribsMask, &Attribs, &seekOffset,
  155.                 &data_length, &byte_order, NULL);
  156.  
  157.     AChoosePlayAttributes(audio, &Attribs, PlayAttribsMask,
  158.               &PlayAttribs, &play_byte_order, NULL);
  159.  
  160.     /*
  161.      * Prepare for conversion.
  162.      * Must remember to free convert_params by calling AEndConversion.
  163.      */
  164.     convert_params = ASetupConversion(audio, &Attribs, &byte_order,
  165.                       &PlayAttribs, &play_byte_order, NULL);
  166.  
  167.     pSpeaker = getenv("SPEAKER");    /* get user speaker preference */
  168.     if (pSpeaker) {
  169.     useIntSpeaker = (*pSpeaker == 'i' || *pSpeaker == 'I');
  170.     } else {
  171.     /*
  172.      * SPEAKER env.var not found - use internal speaker.
  173.      */  
  174.     useIntSpeaker = 1;
  175.     }
  176.  
  177.     switch (PlayAttribs.attr.sampled_attr.channels) {
  178.  
  179.     case 1:    /* Mono */
  180.     gainEntry[0].u.o.out_ch = AOCTMono;
  181.     gainEntry[0].gain = AUnityGain;
  182.     gainEntry[0].u.o.out_dst
  183.         = (useIntSpeaker) ? AODTMonoIntSpeaker : AODTMonoJack;
  184.     break;
  185.  
  186.     case 2:    /* Stereo */
  187.     default:
  188.     gainEntry[0].u.o.out_ch = AOCTLeft;
  189.     gainEntry[0].gain = AUnityGain;
  190.     gainEntry[0].u.o.out_dst
  191.         = (useIntSpeaker) ? AODTLeftIntSpeaker : AODTLeftJack;
  192.     gainEntry[1].u.o.out_ch = AOCTRight;
  193.     gainEntry[1].gain = AUnityGain;
  194.     gainEntry[1].u.o.out_dst
  195.         = (useIntSpeaker) ? AODTRightIntSpeaker : AODTRightJack;
  196.     break;
  197.     }
  198.     streamParams.gain_matrix.type = AGMTOutput;    /* gain matrix */
  199.     streamParams.gain_matrix.num_entries
  200.     = PlayAttribs.attr.sampled_attr.channels;
  201.     streamParams.gain_matrix.gain_entries = gainEntry;
  202.     streamParams.play_volume = AUnityGain;    /* play volume */
  203.     streamParams.priority = APriorityNormal;    /* normal priority */
  204.     streamParams.event_mask = 0;        /* don't solicit any events */
  205.  
  206.     /*
  207.      * Create an audio stream.
  208.      */
  209.     create_playstream();
  210.  
  211.     /*
  212.      * Calculate the required buffer size for the data prior to conversion
  213.      * and allocate memory for the pre-converted data.
  214.      */
  215.     inLen = ACalculateLength(audio, audio->block_size,
  216.                  &PlayAttribs, &Attribs, NULL); 
  217.     inBuf = malloc(inLen);
  218.     inBufIndex = 0;
  219.  
  220.     /*
  221.      * Allocate a buffer for the converted data.
  222.      */
  223.     bufBase = malloc(inLen);
  224.  
  225.     /*
  226.      * Start stream paused so we can transfer enough data (3 seconds worth)
  227.      * before playing starts to prevent stream from running out.
  228.      */
  229.     APauseAudio(audio, xid, NULL, NULL);
  230.     pauseCount = 3
  231.         * PlayAttribs.attr.sampled_attr.channels
  232.         * PlayAttribs.attr.sampled_attr.sampling_rate
  233.         * (PlayAttribs.attr.sampled_attr.bits_per_sample >> 3);
  234.     audioPaused = True;
  235.  
  236.     freq = PlayAttribs.attr.sampled_attr.sampling_rate;
  237.  
  238.     if (freq != f)
  239.         {
  240.         static char buf[50];
  241.         sprintf(buf, "Frequency used is %d\n", freq);
  242.         notice(buf);
  243.         }
  244.  
  245.     set_mix(30);
  246.  
  247.     return freq;
  248. }
  249.  
  250.  
  251. void output_samples(left, right)
  252. int left, right;
  253. {
  254.     if (inBufIndex > inLen - 2)
  255.     flush_buffer();
  256.  
  257.     if (stereo) {
  258.         inBuf[inBufIndex++] = (left * primary + right * secondary) / 256;
  259.         inBuf[inBufIndex++] = (right * primary + left * secondary) / 256;
  260.     } else {
  261.         inBuf[inBufIndex++] = left + right;
  262.     }
  263. }
  264.  
  265.  
  266. void discard_buffer()
  267. {
  268.     /*
  269.      * Destroy old playstream.
  270.      */
  271.     AStopAudio(audio, xid, ASMThisTrans, NULL, NULL);
  272.     close(streamSocket);
  273.     streamSocket = 0;
  274.  
  275.     /*
  276.      * Recreate new playstream.
  277.      */
  278.     create_playstream();
  279.     inBufIndex = 0;
  280. }
  281.  
  282.  
  283. void flush_buffer()
  284. {
  285.     int        len_written = 0, len, bytes_written, bytes_read;
  286.     short    *buf = inBuf;
  287.  
  288.     /*
  289.      * Convert buffer
  290.      */
  291.     AConvertBuffer(audio, convert_params, inBuf, inBufIndex * sizeof(short),
  292.            bufBase, inLen, &bytes_read, &bytes_written, NULL);
  293.     len = bytes_written;
  294.     buf = bufBase;    
  295.  
  296.     /*
  297.      * Write the converted data to the stream socket
  298.      */
  299.     while (len) {
  300.         /*
  301.      * write converted data to stream socket until we have emptied buffer
  302.      */
  303.     if ((len_written = write(streamSocket, buf, len)) < 0) {
  304.         end_all("Write failed");
  305.         }
  306.     buf += len_written;
  307.     len -= len_written;
  308.  
  309.     if (audioPaused) {
  310.         pauseCount -= len_written;
  311.         if (len_written == 0 || pauseCount <= 0) {
  312.         AResumeAudio(audio, xid, NULL, NULL);
  313.         audioPaused = False;
  314.         }
  315.     }
  316.     }
  317.     inBufIndex = 0;
  318. }
  319.  
  320.  
  321. void close_audio()
  322. {
  323.     int        bytes_written;
  324.  
  325.  
  326.     if (audioPaused) {
  327.     AResumeAudio(audio, xid, NULL, NULL);
  328.     }
  329.     /*
  330.      * Free the convert_params structure and flush out
  331.      * the conversion pipeline
  332.      */
  333.     AEndConversion(audio, convert_params, bufBase,
  334.            audio->block_size, &bytes_written, NULL);
  335.  
  336.     ASetCloseDownMode(audio, AKeepTransactions, NULL);
  337.     ASetErrorHandler(prevHandler);
  338.     ACloseAudio(audio, NULL);
  339.  
  340.     if (streamSocket)    close(streamSocket);
  341.     if (inBuf)        free(inBuf);
  342.     if (bufBase)    free(bufBase);
  343.  
  344.     end_all(0);
  345. }
  346.  
  347.  
  348. int update_frequency()
  349. {
  350.     /* not implemented */
  351.     return 0;
  352. }
  353.  
  354.  
  355. void set_synchro(sync)
  356. int sync;
  357. {
  358.     if (streamSocket) {
  359.     if (sync)
  360.         setsockopt(streamSocket, SOL_SOCKET, TCP_NODELAY, 1);
  361.     else
  362.         setsockopt(streamSocket, SOL_SOCKET, TCP_NODELAY, 0);
  363.     }
  364. }
  365.