home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.lbl.gov / 2014.05.ftp.ee.lbl.gov.tar / ftp.ee.lbl.gov / sst.tar.Z / sst.tar / sst / libsst.c < prev    next >
C/C++ Source or Header  |  1990-01-10  |  10KB  |  480 lines

  1. /* libsst.c - SPARC sound tools library
  2. **
  3. ** Copyright (C) 1989 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include <stdio.h>
  14. #include <fcntl.h>
  15. #include "libsst.h"
  16.  
  17. #define AUDBUF 1024
  18.  
  19. int
  20. sst_open( )
  21.     {
  22.     int fd, i, play_level, record_level, gr, ger, gx;
  23.     struct audio_ioctl ai;
  24.     char *getenv(), *ep;
  25.  
  26.     fd = open( "/dev/audio", O_RDWR );
  27.     if ( fd < 0 )
  28.     {
  29.     perror( "sst_open: open /dev/audio" );
  30.     exit( 1 );
  31.     }
  32.  
  33.     /* Shrink audio device's queue size, to cut down time delay. */
  34.     i = AUDBUF;
  35.     if ( ioctl( fd, AUDIOSETQSIZE, &i ) < 0 )
  36.     {
  37.     perror( "sst_open: SETQSIZE" );
  38.     exit( 1 );
  39.     }
  40.  
  41.     /* Set gains.  -10 <= ger <= 18,  -18 <= gr <= 12,  -18 <= gx <= 12. */
  42.     play_level = 75;
  43.     record_level = 75;
  44.     if ( (ep = getenv( "SST_PLAY" )) != NULL )
  45.     {
  46.     play_level = atoi( ep );
  47.     if ( play_level < 0 || play_level > 99 )
  48.         {
  49.         fprintf( stderr, "sst_open: SST_PLAY must be between 0 and 99\n" );
  50.         exit( 1 );
  51.         }
  52.     }
  53.     if ( (ep = getenv( "SST_RECORD" )) != NULL )
  54.     {
  55.     record_level = atoi( ep );
  56.     if ( record_level < 0 || record_level > 99 )
  57.         {
  58.         fprintf( stderr, "sst_open: SST_RECORD must be between 0 and 99\n" );
  59.         exit( 1 );
  60.         }
  61.     }
  62.  
  63.     play_level = play_level * 59 / 100 - 28;
  64.     ger = play_level / 2;
  65.     gr = play_level - ger;
  66.     if ( ger < -10 )
  67.     {
  68.     ger = -10;
  69.     gr = play_level - ger;
  70.     }
  71.     if ( gr > 12 )
  72.     {
  73.     gr = 12;
  74.     ger = play_level - gr;
  75.     }
  76.     gx = record_level * 31 / 100 - 18;
  77.     sst_set_gr( fd, gr );
  78.     sst_set_ger( fd, ger );
  79.     sst_set_gx( fd, gx );
  80.  
  81.     /*  Initialize the MMR2 register to send the output to either
  82.     **  the speaker or the earphone jack, depending on SST_EARPHONES.
  83.     */
  84.     ai.control = AUDIO_MAP_MMR2;
  85.     if ( ioctl( fd, AUDIOGETREG, &ai ) < 0 )
  86.     {
  87.     perror( "sst_open: GETREG MMR2" );
  88.     exit( 1 );
  89.     }
  90.     if ( (ep = getenv( "SST_EARPHONES" )) != NULL )
  91.     ai.data[0] &= ~AUDIO_MMR2_BITS_LS;
  92.     else
  93.     ai.data[0] |= AUDIO_MMR2_BITS_LS;
  94.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  95.     {
  96.     perror( "sst_open: SETREG MMR2" );
  97.     exit( 1 );
  98.     }
  99.  
  100.     return fd;
  101.     }
  102.  
  103. void
  104. sst_close( fd )
  105. int fd;
  106.     {
  107.     struct audio_ioctl ai;
  108.  
  109.     ai.control = AUDIO_MAP_MMR1;
  110.     ai.data[0] = 0;
  111.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  112.     {
  113.     perror( "sst_close: SETREG MMR1" );
  114.     exit( 1 );
  115.     }
  116.     ai.control = AUDIO_MAP_MMR2;
  117.     ai.data[0] = 0;
  118.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  119.     {
  120.     perror( "sst_close: SETREG MMR2" );
  121.     exit( 1 );
  122.     }
  123.     close( fd );
  124.     }
  125.  
  126. /* These are tables of values to be loaded into various gain registers.
  127. */
  128.  
  129. static unsigned char ger_table[][2] = {
  130.     0xaa,    0xaa,    /* -10db */
  131.     0x79,    0xac,
  132.     0x41,    0x99,
  133.     0x9c,    0xde,
  134.     0x74,    0x9c,    /* -6db */
  135.     0x6a,    0xae,
  136.     0xab,    0xdf,
  137.     0x64,    0xab,
  138.     0x2a,    0xbd,
  139.     0x5c,    0xce,
  140.     0x00,    0x99,    /* 0db */
  141.     0x43,    0xdd,
  142.     0x52,    0xef,
  143.     0x55,    0x42,
  144.     0x31,    0xdd,
  145.     0x43,    0x1f,
  146.     0x40,    0xdd,    /* 6db */
  147.     0x44,    0x0f,
  148.     0x31,    0x1f,
  149.     0x10,    0xdd,
  150.     0x41,    0x0f,
  151.     0x60,    0x0b,
  152.     0x42,    0x10,    /* 12db */
  153.     0x11,    0x0f,
  154.     0x72,    0x00,
  155.     0x21,    0x10,
  156.     0x22,    0x00,
  157.     0x00,    0x0b,
  158.     0x00,    0x0f,    /* 18db */
  159.     };
  160.  
  161.  
  162. static unsigned char gr_gx_table[][2] = {
  163.     0x8b,    0x7c,    /* -18db */
  164.     0x8b,    0x35,
  165.     0x8b,    0x24,
  166.     0x91,    0x23,
  167.     0x91,    0x2a,
  168.     0x91,    0x3b,
  169.     0x91,    0xf9,    /* -12db */
  170.     0x91,    0xb6,
  171.     0x91,    0xa4,
  172.     0x92,    0x32,
  173.     0x92,    0xaa,
  174.     0x93,    0xb3,
  175.     0x9f,    0x91,    /* -6db */
  176.     0x9b,    0xf9,
  177.     0x9a,    0x4a,
  178.     0xa2,    0xa2,
  179.     0xaa,    0xa3,
  180.     0xbb,    0x52,
  181.     0x08,    0x08,    /* 0db */
  182.     0x3d,    0xac,
  183.     0x25,    0x33,
  184.     0x21,    0x22,
  185.     0x12,    0xa2,
  186.     0x11,    0x3b,
  187.     0x10,    0xf2,    /* 6db */
  188.     0x02,    0xca,
  189.     0x01,    0x5a,
  190.     0x01,    0x12,
  191.     0x00,    0x32,
  192.     0x00,    0x13,
  193.     0x00,    0x0e,    /* 12db */
  194.     };
  195.  
  196. void
  197. sst_set_ger( fd, value )
  198. int fd, value;
  199.     {
  200.     struct audio_ioctl ai;
  201.  
  202.     if ( ( value < -10 ) || ( value > 18 ) )
  203.     {
  204.     fprintf( stderr, "sst_set_ger: GER %d out of range\n", value );
  205.     return;
  206.     }
  207.  
  208.     /*  Add 10 to the value to get the index into the table.  */
  209.     ai.control = AUDIO_MAP_GER;
  210.     ai.data[0] = ger_table[value + 10][1];
  211.     ai.data[1] = ger_table[value + 10][0];
  212.  
  213.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  214.     {
  215.     perror( "sst_set_ger: SETREG GER" );
  216.     exit( 1 );
  217.     }
  218.  
  219.     ai.control = AUDIO_MAP_MMR1;
  220.     if ( ioctl( fd, AUDIOGETREG, &ai ) < 0 )
  221.     {
  222.     perror( "sst_set_ger: GETREG MMR1" );
  223.     exit( 1 );
  224.     }
  225.     ai.data[0] |= AUDIO_MMR1_BITS_LOAD_GER;
  226.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  227.     {
  228.     perror( "sst_set_ger: SETREG MMR1" );
  229.     exit( 1 );
  230.     }
  231.     }
  232.  
  233. void
  234. sst_set_gr( fd, value )
  235. int fd, value;
  236.     {
  237.     struct audio_ioctl ai;
  238.  
  239.     if ( ( value < -18 ) || ( value > 12 ) )
  240.     {
  241.     fprintf( stderr, "sst_set_gr: GR %d out of range\n", value );
  242.     return;
  243.     }
  244.  
  245.     ai.control = AUDIO_MAP_GR;
  246.     ai.data[0] = gr_gx_table[value + 18][1];
  247.     ai.data[1] = gr_gx_table[value + 18][0];
  248.  
  249.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  250.     {
  251.     perror( "sst_set_gr: SETREG GR" );
  252.     exit( 1 );
  253.     }
  254.  
  255.     ai.control = AUDIO_MAP_MMR1;
  256.     if ( ioctl( fd, AUDIOGETREG, &ai ) < 0 )
  257.     {
  258.     perror( "sst_set_gr: GETREG MMR1" );
  259.     exit( 1 );
  260.     }
  261.     ai.data[0] |= AUDIO_MMR1_BITS_LOAD_GR;
  262.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  263.     {
  264.     perror( "sst_set_gr: SETREG MMR1" );
  265.     exit( 1 );
  266.     }
  267.     }
  268.  
  269. void
  270. sst_set_gx( fd, value )
  271. int fd, value;
  272.     {
  273.     struct audio_ioctl ai;
  274.  
  275.     if ( ( value < -18 ) || ( value > 12 ) )
  276.     {
  277.     fprintf( stderr, "sst_set_gx: GX %d out of range\n", value );
  278.     return;
  279.     }
  280.  
  281.     /*  We add 18 to get the index into the table, since entry 0 represents
  282.     *  -18db.
  283.     */
  284.     ai.control = AUDIO_MAP_GX;
  285.     ai.data[0] = gr_gx_table[value + 18][1];
  286.     ai.data[1] = gr_gx_table[value + 18][0];
  287.  
  288.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  289.     {
  290.     perror( "sst_set_gx: SETREG GX" );
  291.     exit( 1 );
  292.     }
  293.  
  294.     ai.control = AUDIO_MAP_MMR1;
  295.     if ( ioctl( fd, AUDIOGETREG, &ai ) < 0 )
  296.     {
  297.     perror( "sst_set_gx: GETREG MMR1" );
  298.     exit( 1 );
  299.     }
  300.     ai.data[0] |= AUDIO_MMR1_BITS_LOAD_GX;
  301.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  302.     {
  303.     perror( "sst_set_gx: SETREG MMR1" );
  304.     exit( 1 );
  305.     }
  306.     }
  307.  
  308. void
  309. sst_tones( fd, dhz1, dhz2, thz, rhz, usec )
  310. int fd, dhz1, dhz2, thz, rhz, usec;
  311.     {
  312.     struct audio_ioctl ai;
  313.     int dval1, dval2, tval, rval;
  314.     unsigned char oldmmr2, newmmr2;
  315.  
  316.     if ( dhz1 == 0 )
  317.     dval1 = 0;
  318.     else
  319.     {
  320.     dval1 = ( dhz1 * 128 + 63 ) / 1000;
  321.     if ( ( dval1 < 1 ) || ( dval1 > 255 ) )
  322.         {
  323.         fprintf(stderr, "sst_tones: dhz1 %d out of range\n", dhz1 );
  324.         return;
  325.         }
  326.     }
  327.  
  328.     if ( dhz2 == 0 )
  329.     dval2 = 0;
  330.     else
  331.     {
  332.     dval2 = ( dhz2 * 128 + 63 ) / 1000;
  333.     if ( ( dval2 < 1 ) || ( dval2 > 255 ) )
  334.         {
  335.         fprintf(stderr, "sst_tones: dhz2 %d out of range\n", dhz2 );
  336.         return;
  337.         }
  338.     }
  339.  
  340.     if ( thz == 0 )
  341.     tval = 0;
  342.     else
  343.     {
  344.     tval = ( thz * 128 + 63 ) / 2000;
  345.     if ( ( tval < 1 ) || ( tval > 255 ) )
  346.         {
  347.         fprintf(stderr, "sst_tones: thz %d out of range\n", thz );
  348.         return;
  349.         }
  350.     }
  351.  
  352.     if ( rhz == 0 )
  353.     rval = 0;
  354.     else
  355.     {
  356.     rval = ( rhz * 128 + 63 ) / 2000;
  357.     if ( ( rval < 1 ) || ( rval > 255 ) )
  358.         {
  359.         fprintf(stderr, "sst_tones: rhz %d out of range\n", dhz2 );
  360.         return;
  361.         }
  362.     }
  363.  
  364.     if ( ( dval1 != 0 || dval2 != 0 ) && ( tval != 0 || rval != 0 ) )
  365.     {
  366.     fprintf(stderr, "sst_tones: cannot use DTMF and TONE or RINGER at the same time\n", dhz2 );
  367.     return;
  368.     }
  369.  
  370.     if ( tval != 0 && rval != 0 )
  371.     {
  372.     fprintf(stderr, "sst_tones: cannot use TONE and RINGER at the same time\n", dhz2 );
  373.     return;
  374.     }
  375.  
  376.     ai.control = AUDIO_MAP_MMR2;
  377.     if ( ioctl( fd, AUDIOGETREG, &ai ) < 0 )
  378.     {
  379.     perror( "sst_tones: GETREG MMR2" );
  380.     exit( 1 );
  381.     }
  382.     oldmmr2 = newmmr2 = ai.data[0];
  383.  
  384.     if ( dval1 != 0 || dval2 != 0 )
  385.     {
  386.     newmmr2 |= AUDIO_MMR2_BITS_DTMF;
  387.     ai.control = AUDIO_MAP_FTGR;
  388.     ai.data[0] = dval1;
  389.     ai.data[1] = dval2;
  390.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  391.         {
  392.         perror( "sst_tones: SETREG FTGR" );
  393.         exit( 1 );
  394.         }
  395.     }
  396.  
  397.     if ( tval != 0 )
  398.     {
  399.     newmmr2 |= AUDIO_MMR2_BITS_TONE;
  400.     ai.control = AUDIO_MAP_FTGR;
  401.     ai.data[0] = tval;
  402.     ai.data[1] = 0;
  403.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  404.         {
  405.         perror( "sst_tones: SETREG FTGR" );
  406.         exit( 1 );
  407.         }
  408.     }
  409.  
  410.     if ( rval != 0 )
  411.     {
  412.     newmmr2 |= AUDIO_MMR2_BITS_RINGER;
  413.     ai.control = AUDIO_MAP_FTGR;
  414.     ai.data[0] = rval;
  415.     ai.data[1] = 0;
  416.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  417.         {
  418.         perror( "sst_tones: SETREG FTGR" );
  419.         exit( 1 );
  420.         }
  421.     }
  422.  
  423.     ai.control = AUDIO_MAP_MMR2;
  424.     ai.data[0] = newmmr2;
  425.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  426.     {
  427.     perror( "sst_tones: SETREG MMR2" );
  428.     exit( 1 );
  429.     }
  430.  
  431.     usleep( usec );
  432.  
  433.     ai.data[0] = oldmmr2;
  434.     if ( ioctl( fd, AUDIOSETREG, &ai ) < 0 )
  435.     {
  436.     perror( "sst_tones: SETREG MMR2" );
  437.     exit( 1 );
  438.     }
  439.     }
  440.  
  441. void
  442. sst_dtmf( fd, dial, usecper, usecpause )
  443. int fd, usecper, usecpause;
  444. char *dial;
  445.     {
  446.     char *cp;
  447.  
  448.     for ( cp = dial; *cp != '\0'; cp++ )
  449.     {
  450.     switch ( *cp )
  451.         {
  452.         case '1': sst_tones( fd, 703, 1211, 0, 0, usecper ); break;
  453.         case '2': sst_tones( fd, 703, 1336, 0, 0, usecper ); break;
  454.         case '3': sst_tones( fd, 703, 1492, 0, 0, usecper ); break;
  455.         case 'A': sst_tones( fd, 703, 1648, 0, 0, usecper ); break;
  456.         case '4': sst_tones( fd, 773, 1211, 0, 0, usecper ); break;
  457.         case '5': sst_tones( fd, 773, 1336, 0, 0, usecper ); break;
  458.         case '6': sst_tones( fd, 773, 1492, 0, 0, usecper ); break;
  459.         case 'B': sst_tones( fd, 773, 1648, 0, 0, usecper ); break;
  460.         case '7': sst_tones( fd, 859, 1211, 0, 0, usecper ); break;
  461.         case '8': sst_tones( fd, 859, 1336, 0, 0, usecper ); break;
  462.         case '9': sst_tones( fd, 859, 1492, 0, 0, usecper ); break;
  463.         case 'C': sst_tones( fd, 859, 1648, 0, 0, usecper ); break;
  464.         case '*': sst_tones( fd, 945, 1211, 0, 0, usecper ); break;
  465.         case '0': sst_tones( fd, 945, 1336, 0, 0, usecper ); break;
  466.         case '#': sst_tones( fd, 945, 1492, 0, 0, usecper ); break;
  467.         case 'D': sst_tones( fd, 945, 1648, 0, 0, usecper ); break;
  468.  
  469.         case ' ': case '-': case '(': case ')': case '+':
  470.         continue;    /* ignore */
  471.  
  472.         case ',': usleep( usecper ); break;    /* big pause */
  473.  
  474.         default:
  475.         fprintf( stderr, "sst_dtmf: unknown dialing code '%c'\n", *cp );
  476.         }
  477.     usleep( usecpause );
  478.     }
  479.     }
  480.