home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / MM1 / SOUNDUTILS / mm1_tracker.lzh / TRACKER4.6 / Hpux / 3_audio.c next >
Text File  |  1994-11-24  |  11KB  |  467 lines

  1. /* -*-C-*-
  2.     vi:ts=3 sw=3:
  3. *******************************************************************************
  4. *
  5. * File:        hpux_audio.c
  6. * RCS:        $Header: $
  7. * Description:    HP-UX audio hardware interface for tracker
  8. * Author:    Darryl Okahata (darrylo@sr.hp.com)
  9. * Created:    Thu Dec 16 12:09:53 1993
  10. * Modified:     Mon Dec 20 12:17:02 1993 (Darryl Okahata) darrylo@mina
  11. * Language:    C
  12. * Package:    N/A
  13. * Status:    Experimental
  14. *
  15. * (C) Copyright 1993, Hewlett-Packard, all rights reserved.
  16. *
  17. *******************************************************************************
  18.  
  19.  */
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <errno.h>
  25. #include <sys/socket.h>
  26.  
  27. #include <audio/Alib.h>
  28.  
  29. #include "defs.h"
  30. #include "extern.h"
  31.  
  32.  
  33.  
  34. #define abs(x) ((x) < 0 ? -(x) : (x))
  35.  
  36. #define STEREO_CHANNELS        (ALeftOutputChMask | ARightOutputChMask)
  37.  
  38. extern AGainDB        volume;        /* volume in dB -- in main.c */
  39. extern char        use_speaker;    /* in main.c */
  40.  
  41. LOCAL Audio        *audio;
  42. LOCAL ADataFormat    *available_formats;
  43. LOCAL long        available_formats_len;
  44. LOCAL AOutputChMask    available_channels;
  45. LOCAL AByteOrder    byte_order;
  46. LOCAL AudioAttributes    audio_attributes;
  47. LOCAL AGainEntry    gain_entry[4];
  48. LOCAL SSPlayParams    stream_parameters;
  49. LOCAL ATransID        xid;
  50. LOCAL SStream        audio_stream;
  51. LOCAL int        stream_socket;
  52.  
  53.  
  54. LOCAL int        stereo;
  55. LOCAL int        primary, secondary = 512;
  56. LOCAL ADataFormat    audio_format;
  57. LOCAL int        index, max_index;
  58. LOCAL long        buffer_size;
  59. LOCAL char        *buffer;
  60. LOCAL short        *sbuffer;
  61.  
  62.  
  63. LOCAL int round_sampling_rate(audio, f)
  64. Audio    *audio;
  65. int    f;
  66. {
  67.     int best = 0;
  68.     int i;
  69.  
  70.     for (i = 0; i < audio->n_sampling_rate; i++) {
  71.     if (abs(audio->sampling_rate_list[i] - f) < abs(best - f)) {
  72.         best = audio->sampling_rate_list[i];
  73.     }
  74.     }
  75.     return best;
  76. }
  77.  
  78.  
  79. LOCAL format_available(fmt)
  80. ADataFormat    fmt;
  81. {
  82.     int        i;
  83.  
  84.     for (i = 0; i < available_formats_len; ++i) {
  85.     if (available_formats[i] == fmt) {
  86.         break;
  87.     }
  88.     }
  89.     if (i >= available_formats_len) {
  90.     return (0);
  91.     }
  92.     return (1);
  93. }
  94.  
  95.  
  96. void set_mix(percent)
  97. int percent;
  98. {
  99.     percent *= 256;
  100.     percent /= 100;
  101.     primary = percent;
  102.     secondary = 512 - percent;
  103. }
  104.  
  105.  
  106. /*
  107.  * It would be nice if we could use AGetErrorText(), but this requires that
  108.  * an audio pointer be passed to it, and this pointer could be NULL.
  109.  */
  110. LOCAL void die(msg, error)
  111. char        *msg;
  112. AError        error;
  113. {
  114.     char    *errbuf, buf[1000];    /* memory is cheap, life is short */
  115.  
  116.     if (msg == NULL) {
  117.     msg = "";
  118.     }
  119.     switch (error) {
  120.     case AENoError:
  121.     errbuf = "(No audio error -- huh?  This should never happen!)";
  122.     break;
  123.     case AESystemCall:
  124.     errbuf = "System call error";
  125.     break;
  126.     case AEBadAudio:
  127.     errbuf = "Bad audio";
  128.     break;
  129.     case AEBadValue:
  130.     errbuf = "Bad audio value";
  131.     break;
  132.     case AEHostNotFound:
  133.     errbuf = "Audio host not found";
  134.     break;
  135.     case AENoSuchAudioNumber:
  136.     errbuf = "No such audio number";
  137.     break;
  138.     case AEBadFileFormat:
  139.     errbuf = "Bad audio file format";
  140.     break;
  141.     case AEBadDataFormat:
  142.     errbuf = "Bad audio data format";
  143.     break;
  144.     case AEFileNotFound:
  145.     errbuf = "Audio file not found";
  146.     break;
  147.     case AEBadLinkID:
  148.     errbuf = "Audio bad link ID";
  149.     break;
  150.     case AEBadGainMatrix:
  151.     errbuf = "Bad audio gain matrix";
  152.     break;
  153.     case AEBadFileHdr:
  154.     errbuf = "Bad audio file header";
  155.     break;
  156.     case AEUnrecognizableFormat:
  157.     errbuf = "Unrecognizable audio format";
  158.     break;
  159.     case AEBadAttribute:
  160.     errbuf = "Bad audio attribute";
  161.     break;
  162.     case AEBadOffset:
  163.     errbuf = "Audio bad offset";
  164.     break;
  165.     case AEBadTransactionID:
  166.     errbuf = "Bad audio transaction ID";
  167.     break;
  168.     case AECantDetermineFormat:
  169.     errbuf = "Audio can't determine format";
  170.     break;
  171.     case AEOutOfMemory:
  172.     errbuf = "out of memory (audio)";
  173.     break;
  174.     case AEOpenFailed:
  175.     errbuf = "Audio open failed";
  176.     break;
  177.     case AEBadSamplingRate:
  178.     errbuf = "Bad audio sampling rate";
  179.     break;
  180.     case AEBadSoundBucket:
  181.     errbuf = "Audio bad sound bucket";
  182.     break;
  183.     case AEBadSoundStream:
  184.     errbuf = "Audio bad sound stream";
  185.     break;
  186.     case AETransactionBusy:
  187.     errbuf = "Audio transaction busy";
  188.     break;
  189.     case AEllbdNotStarted:
  190.     errbuf = "llbd daemon not running";
  191.     break;
  192.     case AERPCFailed:
  193.     errbuf = "Audio RPC failed";
  194.     break;
  195.     case AELibraryMismatch:
  196.     errbuf = "Audio library mismatch";
  197.     break;
  198.     default:
  199.     sprintf(buf, "(unknown audio error %d)", (int) error);
  200.     errbuf = buf;
  201.     break;
  202.     }
  203.      notice(msg);
  204.      end_all(errbuf);
  205. }
  206.  
  207.  
  208. int open_audio(freq, stereo_flag)
  209. int freq;
  210. int stereo_flag;
  211. {
  212.     long        status_return;
  213.     AudioAttrMask    valid_attributes;
  214.     char        *speaker;
  215.     int            dsize, i;
  216.  
  217.     stereo = stereo_flag;
  218.  
  219.     if ((audio = AOpenAudio(NULL, &status_return)) == NULL) {
  220.     die("could not open audio: ", status_return);
  221.     }
  222.  
  223.     available_formats = ADataFormats(audio);
  224.     available_formats_len = ANumDataFormats(audio);
  225.     if (format_available(ADFLin16)) {
  226.     audio_format = ADFLin16;
  227.     dsize = 2;        /* for ADFLin16 */
  228.     } else if (format_available(ADFLin8)) {
  229.     audio_format = ADFLin8;
  230.     dsize = 1;        /* for ADFLin8 */
  231.     } else {
  232.      end_all("Neither ADFLin16/ADFLin8 supported by the audio device");
  233.     }
  234.  
  235.     available_channels = AOutputChannels(audio);
  236.  
  237.     valid_attributes = ASDataFormatMask | ASBitsPerSampleMask |
  238.     ASSamplingRateMask | ASChannelsMask;
  239.     audio_attributes = *ABestAudioAttributes(audio);
  240.     audio_attributes.type = ATSampled;
  241.     audio_attributes.attr.sampled_attr.data_format = ADFLin16;
  242.     audio_attributes.attr.sampled_attr.bits_per_sample = 16;
  243.  
  244.     if (freq <= 0) {
  245.     /*
  246.      * Use value closest to CD-quality audio
  247.      */
  248.     freq = 44100;
  249.     }
  250.     freq = round_sampling_rate(audio, freq);
  251.     audio_attributes.attr.sampled_attr.sampling_rate = freq;
  252.  
  253.     audio_attributes.attr.sampled_attr.duration.type = ATTFullLength;
  254.     valid_attributes |= ASDurationMask;
  255.  
  256.     if (stereo &&
  257.     ((available_channels & (STEREO_CHANNELS)) == STEREO_CHANNELS)) {
  258.     audio_attributes.attr.sampled_attr.channels = 2;
  259.     audio_attributes.attr.sampled_attr.interleave = 1;
  260.     valid_attributes |= ASInterleaveMask;
  261.     } else {
  262.     audio_attributes.attr.sampled_attr.channels = 1;
  263.     }
  264.  
  265.     /*
  266.      * Select attributes for playback
  267.      */
  268.     AChoosePlayAttributes(audio, ABestAudioAttributes(audio),
  269.               valid_attributes, &audio_attributes,
  270.               &byte_order, &status_return);
  271.     if (byte_order != AMSBFirst) {
  272.      end_all("Little endian byte ordering not supported");
  273.     }
  274.  
  275.     /*
  276.      * Use the external jack, unless the user overrides this on the
  277.      * command-line, or SPEAKER is set.     (The command line stuff is done in
  278.      * main.c.)
  279.      */
  280.     if ((speaker = getenv( "SPEAKER" )) != NULL) {
  281.     if ((*speaker == 'i') || (*speaker == 'I')) {
  282.         use_speaker = 1;
  283.     }
  284.     }
  285.  
  286.     stream_parameters.priority = APriorityNormal;
  287.  
  288.     switch(audio_attributes.attr.sampled_attr.channels) {
  289.     case 1:
  290.     gain_entry[0].u.o.out_ch = AOCTMono;
  291.     gain_entry[0].gain = volume;
  292.     gain_entry[0].u.o.out_dst =
  293.         (use_speaker) ? AODTMonoIntSpeaker : AODTMonoJack;
  294.     break;
  295.     case 2:
  296.     default:    /* assume no more than 2 channels */
  297.     gain_entry[0].u.o.out_ch = AOCTLeft;
  298.     gain_entry[0].gain = volume;
  299.     gain_entry[0].u.o.out_dst =
  300.         (use_speaker) ? AODTLeftIntSpeaker : AODTLeftJack;
  301.     gain_entry[1].u.o.out_ch = AOCTRight;
  302.     gain_entry[1].gain = volume;
  303.     gain_entry[1].u.o.out_dst =
  304.         (use_speaker) ? AODTRightIntSpeaker : AODTRightJack;
  305.     break;
  306.     }
  307.  
  308.     stream_parameters.gain_matrix.type = AGMTOutput;       /* gain matrix */
  309.     stream_parameters.gain_matrix.num_entries =
  310.     audio_attributes.attr.sampled_attr.channels;
  311.     stream_parameters.gain_matrix.gain_entries = gain_entry;
  312.     stream_parameters.play_volume = AUnityGain;           /* play volume */
  313.     stream_parameters.event_mask = 0;               /* don't solicit any
  314.                                   events */
  315.  
  316.     /*
  317.      * create an audio stream
  318.      */
  319.     xid = APlaySStream(audio, valid_attributes, &audio_attributes,
  320.                &stream_parameters, &audio_stream, NULL);
  321.  
  322.     /*
  323.      * create a stream socket
  324.      */
  325.     stream_socket = socket(AF_INET, SOCK_STREAM, 0);
  326.     if(stream_socket < 0) {
  327.      end_all("Socket creation failed");
  328.     }
  329.  
  330.     /*
  331.      * connect the stream socket to the audio stream port
  332.      */
  333.     status_return = connect(stream_socket,
  334.                 (struct sockaddr *)&audio_stream.tcp_sockaddr,
  335.                 sizeof(struct sockaddr_in));
  336.     if(status_return < 0) {
  337.      end_all("Connect failed");
  338.     }
  339.  
  340.     buffer_size = dsize * audio_attributes.attr.sampled_attr.channels *
  341.     audio_attributes.attr.sampled_attr.sampling_rate;
  342.     buffer = (char *) malloc(buffer_size);
  343.     sbuffer = (short *) buffer;
  344.     if (!buffer) {
  345.      end_all("Unable to allocate memory for buffer");
  346.     }
  347.     switch (audio_format) {
  348.     case ADFLin16:
  349.     max_index = buffer_size / 2 - 1;
  350.     break;
  351.     case ADFLin8:
  352.     max_index = buffer_size - 1;
  353.     break;
  354.     default:
  355.         end_all("Bad");
  356.     break;
  357.     }
  358.     max_index = buffer_size;
  359.  
  360.     return (audio_attributes.attr.sampled_attr.sampling_rate);
  361. }
  362.  
  363.  
  364. void set_synchro(s)
  365. int s;
  366. {
  367.     /* not implemented */
  368. }
  369.  
  370.  
  371. int update_frequency()
  372. {
  373.     /* not implemented */
  374.     return 0;
  375. }
  376.  
  377.  
  378. void flush_buffer()
  379. {
  380.     int        len_written, len_left;
  381.     char    *buf;
  382.  
  383.     len_left = index * 2;
  384.     buf = buffer;
  385.     while (len_left > 0) {
  386.     if((len_written = write(stream_socket, buf, len_left)) < 0) {
  387.         end_all("Write failed");
  388.     }
  389.     len_left -= len_written;
  390.     buf += len_written;
  391.     }
  392.     index = 0;
  393. }
  394.  
  395.  
  396. void output_samples(left, right)
  397. int left, right;
  398. {
  399.     if (index >= max_index) {
  400.     flush_buffer();
  401.     }
  402.     if (stereo) {
  403.     int        r, l;
  404.  
  405.     r = (left * primary + right * secondary) / 256;
  406.     l = (right * primary + left * secondary) / 256;
  407.     switch (audio_format) {
  408.     case ADFLin16:
  409.         sbuffer[index++] = r;
  410.         sbuffer[index++] = l;
  411.         break;
  412.     case ADFLin8:
  413.         buffer[index++] = r / 256 + ((r & 0x80) ? 1 : 0);
  414.         buffer[index++] = l / 256 + ((l & 0x80) ? 1 : 0);
  415.         break;
  416.     default:
  417.         break;
  418.     }
  419.     } else {
  420.     switch (audio_format) {
  421.     case ADFLin16:
  422.         sbuffer[index++] = left + right;
  423.         break;
  424.     case ADFLin8:
  425.         buffer[index++] = left + right;
  426.         break;
  427.     default:
  428.         break;
  429.     }
  430.     }
  431. }
  432.  
  433.  
  434. void discard_buffer()
  435. {
  436.     /* not implemented -- is this needed??? */
  437. }
  438.  
  439.  
  440. void close_audio()
  441. {
  442.     close(stream_socket);
  443.  
  444.     /*
  445.      * set close mode to prevent playback from stopping
  446.      *    when we close audio connection
  447.      */
  448.     ASetCloseDownMode(audio, AKeepTransactions, NULL);
  449.  
  450.     /*
  451.      *    That's all, folks!
  452.      */
  453.     ACloseAudio(audio, NULL);
  454.     audio = NULL;
  455. }
  456.  
  457.  
  458. /*
  459.  * Local Variables:
  460.  * c-indent-level: 4
  461.  * c-continued-statement-offset: 4
  462.  * c-brace-offset: -4
  463.  * c-argdecl-indent: 0
  464.  * c-label-offset: -4
  465.  * End:
  466.  */
  467.