home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wvis0626.zip / warpvision_20020626.zip / audio / dart.c < prev    next >
C/C++ Source or Header  |  2002-06-21  |  14KB  |  582 lines

  1. /*
  2.     Direct Audio Interface library for OS/2
  3.     Copyright (C) 1998 by Andrew Zabolotny <bit@eltech.ru>
  4.  
  5.     This library is free software; you can redistribute it and/or
  6.     modify it under the terms of the GNU Library General Public
  7.     License as published by the Free Software Foundation; either
  8.     version 2 of the License, or (at your option) any later version.
  9.  
  10.     This library is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.     Library General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU Library General Public
  16.     License along with this library; if not, write to the Free
  17.     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19.     Modified by Alex Strelnikov
  20. */
  21.  
  22. #define INCL_OS2MM
  23.  
  24. #ifdef MAIN_DEBUG
  25.  
  26. #define INCL_KBD
  27. #define INCL_DOSPROCESS
  28.  
  29. #endif
  30.  
  31. #include <os2.h>
  32. #include <os2me.h>
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <stddef.h>
  37.  
  38. #include "dart.h"
  39.  
  40.  
  41. DartStruct DART;
  42.  
  43.  
  44. int dart_error(APIRET rc)
  45. {
  46.     if (rc)
  47.     {
  48.         mciGetErrorString(rc,
  49.                           (PSZ)DART.ErrorCode,
  50.                           sizeof(DART.ErrorCode));
  51.  
  52.         fprintf(stdout, "\nDART error:%s\n", DART.ErrorCode);
  53.  
  54.         return TRUE;
  55.     }
  56.     else
  57.     {
  58.         DART.ErrorCode[0] = 0;
  59.  
  60.         return FALSE;
  61.     }
  62. }
  63.  
  64.  
  65. void dart_stop(void)
  66. {
  67.     MCI_GENERIC_PARMS GenericParms;
  68.  
  69.     if (DART.DeviceID)
  70.     {
  71.         GenericParms.hwndCallback = 0;
  72.  
  73.         mciSendCommand(DART.DeviceID,
  74.                        MCI_STOP,
  75.                        MCI_WAIT,
  76.                        (PVOID)&GenericParms,
  77.                        0);
  78.     }
  79.  
  80.     return;
  81. }
  82.  
  83.  
  84. int dart_fill_buffer(PMCI_MIX_BUFFER pBuffer)
  85. {
  86.     size_t top = 0;
  87.  
  88.     memset (pBuffer->pBuffer, 0x80, pBuffer->ulBufferLength);
  89.  
  90.     if (DART.InputCallback && DART.WaitStreamEnd != TRUE)
  91.         top = DART.InputCallback(pBuffer->pBuffer, DART.BufferParms.ulBufferSize);
  92.  
  93.     if (top < DART.BufferParms.ulBufferSize)
  94.     {
  95.         pBuffer->ulFlags = MIX_BUFFER_EOS;
  96.         DART.WaitStreamEnd = TRUE;
  97.     }
  98.     else
  99.         pBuffer->ulFlags = 0;
  100.  
  101.     pBuffer->ulBufferLength = top;
  102.  
  103.     return top;
  104. }
  105.  
  106.  
  107. void dart_free_buffers(void)
  108. {
  109.     APIRET rc;
  110.     int i;
  111.  
  112.     if (DART.MixBuffers == NULL)
  113.         return;
  114.  
  115.     // restore original buffer sizes -- just in case
  116.     for (i = 0; i < DART.BufferCount; i++)
  117.         DART.MixBuffers[i].ulBufferLength = DART.BufferParms.ulBufferSize;
  118.  
  119.     rc = mciSendCommand (DART.DeviceID,
  120.                          MCI_BUFFER,
  121.                          MCI_WAIT | MCI_DEALLOCATE_MEMORY,
  122.                          (PVOID)&DART.BufferParms, 0);
  123.     if (DART.MixBuffers)
  124.         free(DART.MixBuffers);
  125.  
  126.     DART.MixBuffers = NULL;
  127.  
  128.     dart_error(rc);
  129. }
  130.  
  131.  
  132. long MixHandler (ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags)
  133. {
  134.     if (DART.Stopped == TRUE || DART.Paused == TRUE)
  135.         return TRUE;
  136.  
  137.     switch (ulFlags)
  138.     {
  139.         case MIX_STREAM_ERROR | MIX_WRITE_COMPLETE:
  140.             // on error, fill next buffer and continue
  141.         case MIX_WRITE_COMPLETE:
  142.             DART.BytesPlayed += pBuffer->ulBufferLength;
  143.  
  144.             // If this is the last buffer, stop
  145.             if (pBuffer->ulFlags & MIX_BUFFER_EOS)
  146.                 DART.Stopped = TRUE;
  147.             else
  148.             {
  149.                 // Transfer buffer to DART
  150.                 if (dart_fill_buffer(pBuffer) == 0)
  151.                 {
  152.                     // if user callback failed to fill the buffer,
  153.                     // we should fill it with silence to avoid annoying
  154.                     // clicks that happens on some soundcards
  155.  
  156.                     pBuffer->ulBufferLength = DART.BufferParms.ulBufferSize;
  157.                     memset (pBuffer->pBuffer, 0x80, pBuffer->ulBufferLength);
  158.                 }
  159.  
  160.                 DART.MixSetupParms.pmixWrite(DART.MixSetupParms.ulMixHandle, pBuffer, 1);
  161.             }
  162.  
  163.         break;
  164.     }
  165.  
  166.     return TRUE;
  167. }
  168.  
  169.  
  170. int dart_init(int DeviceIndex, int BitsPerSample, int SamplingRate,
  171.               int DataFormat, int Channels, int Buffers,
  172.               dartInputCallback Callback)
  173. {
  174.     APIRET rc;
  175.     LONG dart_fl;
  176.     MCI_AMP_OPEN_PARMS MciOpenParms;
  177.     MCI_GENERIC_PARMS GenericParms;
  178.  
  179.     DART.DeviceID = 0;
  180.     DART.MixBuffers = NULL;
  181.     DART.InputCallback = NULL;
  182.  
  183.     if (DART.Shareable)
  184.     {
  185.         dart_fl = MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE;
  186.         printf("DART: open in SHARE mode\n");
  187.     }
  188.     else
  189.     {
  190.         dart_fl = MCI_WAIT | MCI_OPEN_TYPE_ID;
  191.         printf("DART: open in EXCLUSIVE mode\n");
  192.     }
  193.  
  194.     fflush(stdout);
  195.  
  196.     memset(&MciOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS));
  197.   
  198.     MciOpenParms.usDeviceID = 0;
  199.     MciOpenParms.pszDeviceType = (PSZ) (MCI_DEVTYPE_AUDIO_AMPMIX |
  200.                                        (DeviceIndex << 16));
  201.     rc = mciSendCommand (0,
  202.                          MCI_OPEN,
  203.                          dart_fl,
  204.                          (PVOID) &MciOpenParms,
  205.                          0);
  206.     if (dart_error(rc))
  207.         return FALSE;
  208.  
  209.     DART.DeviceID = MciOpenParms.usDeviceID;
  210.  
  211.     if (!DART.Shareable)
  212.     {
  213.         // Grab exclusive rights to device instance (NOT entire device)
  214.         GenericParms.hwndCallback = 0;
  215.         rc = mciSendCommand (DART.DeviceID,
  216.                              MCI_ACQUIREDEVICE,
  217.                              MCI_EXCLUSIVE_INSTANCE,
  218.                              (PVOID)&GenericParms,
  219.                              0);
  220.     }
  221.  
  222.     if (dart_error(rc))
  223.         return FALSE;
  224.  
  225.     // Allocate mixer buffers
  226.     DART.MixBuffers = (MCI_MIX_BUFFER *)malloc(sizeof(MCI_MIX_BUFFER)*Buffers);
  227.  
  228.     // Setup the mixer for playback of wave data
  229.     memset (&DART.MixSetupParms, 0, sizeof (MCI_MIXSETUP_PARMS));
  230.  
  231.     DART.MixSetupParms.ulBitsPerSample = BitsPerSample;
  232.     DART.MixSetupParms.ulSamplesPerSec = SamplingRate;
  233.     DART.MixSetupParms.ulFormatTag = DataFormat;
  234.     DART.MixSetupParms.ulChannels = Channels;
  235.     DART.MixSetupParms.ulFormatMode = MCI_PLAY;
  236.     DART.MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
  237.     DART.MixSetupParms.pmixEvent = (MIXEREVENT*)MixHandler;
  238.  
  239.     rc = mciSendCommand(DART.DeviceID,
  240.                         MCI_MIXSETUP,
  241.                         MCI_WAIT | MCI_MIXSETUP_INIT,
  242.                         (PVOID)&DART.MixSetupParms,
  243.                         0);
  244.  
  245.     if (dart_error(rc))
  246.         return FALSE;
  247.  
  248.     // Use the suggested buffer size provide by the mixer device
  249.     // Set up the BufferParms data structure and allocate device buffers
  250.     // from the Amp-Mixer
  251.  
  252.     DART.BufferParms.ulStructLength = sizeof(MCI_BUFFER_PARMS);
  253.     DART.BufferParms.ulNumBuffers = Buffers;
  254.     DART.BufferParms.ulBufferSize = DART.MixSetupParms.ulBufferSize;
  255.     DART.BufferParms.pBufList = DART.MixBuffers;
  256.  
  257.     DART.BufLen = DART.MixSetupParms.ulBufferSize;
  258.  
  259.     rc = mciSendCommand(DART.DeviceID,
  260.                         MCI_BUFFER,
  261.                         MCI_WAIT | MCI_ALLOCATE_MEMORY,
  262.                         (PVOID)&DART.BufferParms,
  263.                         0);
  264.     if (dart_error (rc))
  265.         return FALSE;
  266.  
  267.     // The mixer possibly changed these values
  268.     DART.BufferCount = DART.BufferParms.ulNumBuffers;
  269.  
  270.     DART.SeekPosition = 0;
  271.     DART.InputCallback = Callback;
  272.  
  273.     return TRUE;
  274. }
  275.  
  276.  
  277. int dart_close(void)
  278. {
  279.     MCI_GENERIC_PARMS GenericParms;
  280.     APIRET rc;
  281.  
  282.     if (DART.DeviceID != 0)
  283.     {
  284.         dart_stop();
  285.         dart_free_buffers();
  286.  
  287.         GenericParms.hwndCallback = 0;
  288.  
  289.         if (!DART.Shareable)
  290.         {
  291.             // Release exclusive rights to device instance (NOT entire device)
  292.  
  293.             rc = mciSendCommand (DART.DeviceID,
  294.                                  MCI_ACQUIREDEVICE,
  295.                                  MCI_RELEASEDEVICE,
  296.                                  (PVOID)&GenericParms,
  297.                                  0);
  298.         }
  299.  
  300.         rc = mciSendCommand(DART.DeviceID,
  301.                             MCI_CLOSE,
  302.                             MCI_WAIT,
  303.                             (PVOID)&GenericParms,
  304.                             0);
  305.         dart_error(rc);
  306.     }
  307.  
  308.     return 0;
  309. }
  310.  
  311.  
  312. int dart_play(void)
  313. {
  314.     int buffcount, outsize;
  315.  
  316.     DART.Stopped = DART.WaitStreamEnd = FALSE;
  317.  
  318.     DART.BytesPlayed = 0;
  319.  
  320.     for (buffcount = 0; buffcount < DART.BufferCount; buffcount++)
  321.     {
  322.         outsize = dart_fill_buffer(&DART.MixBuffers[buffcount]);
  323.  
  324.         if (outsize != DART.BufLen)
  325.             break;
  326.     }
  327.  
  328.     if (buffcount == 0)
  329.         DART.Stopped = DART.WaitStreamEnd = TRUE;
  330.     else
  331.     {
  332.         APIRET rc = DART.MixSetupParms.pmixWrite(DART.MixSetupParms.ulMixHandle,
  333.                                                  &DART.MixBuffers[0], buffcount);
  334.         dart_error(rc);
  335.     }
  336.  
  337.     return TRUE;
  338. }
  339.  
  340.  
  341. void dart_pause(void)
  342. {
  343.     if (DART.DeviceID)
  344.     {
  345.         MCI_GENERIC_PARMS GenericParms;
  346.  
  347.         mciSendCommand(DART.DeviceID,
  348.                        MCI_PAUSE,
  349.                        MCI_WAIT,
  350.                        (PVOID)&GenericParms,
  351.                        0);
  352.     }
  353.  
  354.     DART.Paused = TRUE;
  355. }
  356.  
  357.  
  358. void dart_resume(void)
  359. {
  360.     if (DART.DeviceID)
  361.     {
  362.         MCI_GENERIC_PARMS GenericParms;
  363.  
  364.         mciSendCommand(DART.DeviceID,
  365.                        MCI_RESUME,
  366.                        MCI_WAIT,
  367.                        (PVOID)&GenericParms,
  368.                        0);
  369.     }
  370.  
  371.     DART.Paused = FALSE;
  372. }
  373.  
  374.  
  375. ULONG dart_get_pos(void)
  376. {
  377.     MCI_STATUS_PARMS statParms;
  378.  
  379.     memset(&statParms, 0, sizeof(MCI_STATUS_PARMS));
  380.     statParms.ulItem = MCI_STATUS_POSITION;
  381.  
  382.     mciSendCommand(DART.DeviceID,
  383.                    MCI_STATUS,
  384.                    MCI_WAIT | MCI_STATUS_ITEM,
  385.                    (PVOID)&statParms,
  386.                    0);
  387.  
  388.     return statParms.ulReturn + DART.SeekPosition;
  389. }
  390.  
  391.  
  392. void dart_set_pos(ULONG new_position)
  393. {
  394.     DART.SeekPosition = 0;
  395.  
  396.     DART.SeekPosition = new_position - dart_get_pos();
  397.  
  398. /*
  399.     int rc;
  400.     MCI_SEEK_PARMS mciSeekParm;
  401.  
  402.     mciSeekParm.hwndCallback = 0;
  403.     mciSeekParm.ulTo = Position;
  404.  
  405.     rc = mciSendCommand(DART.DeviceID,
  406.                         MCI_SEEK,
  407.                         MCI_WAIT | MCI_TO,
  408.                         (PVOID)&mciSeekParm,
  409.                         0);
  410.     dart_error(rc);
  411. */
  412.     return;
  413. }
  414.  
  415.  
  416. void dart_set_sound_state(BOOL state)
  417. {
  418.     USHORT        usDeviceID;
  419.     MCI_SET_PARMS msp;
  420.     USHORT        ushSt;
  421.  
  422.     if (DART.DeviceID)
  423.     {
  424.         if (state == FALSE)
  425.             ushSt = MCI_SET_ON;
  426.         else
  427.             ushSt = MCI_SET_OFF;
  428.  
  429.         msp.ulAudio = MCI_SET_AUDIO_ALL;
  430.  
  431.         mciSendCommand(DART.DeviceID,
  432.                        MCI_SET,
  433.                        MCI_WAIT | MCI_SET_AUDIO | ushSt,
  434.                        (PVOID)&msp, 0);
  435.     }
  436.  
  437.     return;
  438. }
  439.  
  440.  
  441. void dart_set_volume(ULONG vol)
  442. {
  443.     USHORT        usDeviceID;
  444.     MCI_SET_PARMS msp;
  445.  
  446.     if (DART.DeviceID)
  447.     {
  448.         msp.ulLevel = vol;
  449.         msp.ulAudio = MCI_SET_AUDIO_ALL;
  450.         mciSendCommand(DART.DeviceID,
  451.                        MCI_SET,
  452.                        MCI_WAIT | MCI_SET_AUDIO |
  453.                        MCI_SET_VOLUME,
  454.                        (PVOID)&msp, 0);
  455.     }
  456.  
  457.     return;
  458. }
  459.  
  460.  
  461. USHORT dart_get_volume(void)
  462. {
  463.     ULONG  ulError;
  464.     BOOL   disc_loaded;
  465.     USHORT vol;
  466.  
  467.     MCI_STATUS_PARMS mstatusp;
  468.     memset(&mstatusp, 0, sizeof (MCI_STATUS_PARMS));
  469.     mstatusp.ulItem = MCI_STATUS_VOLUME;
  470.  
  471.     if (DART.DeviceID)
  472.     {
  473.         ulError = mciSendCommand(DART.DeviceID,
  474.                                  MCI_STATUS,
  475.                                  MCI_WAIT | MCI_STATUS_ITEM,
  476.                                  (PVOID)&mstatusp,
  477.                                  0);
  478.  
  479.         if (!(ulError & 0xffff))
  480.         {
  481.             vol = LOUSHORT(mstatusp.ulReturn);
  482.         } 
  483.         else 
  484.             vol = 0;
  485.     }
  486.  
  487.     return vol;
  488. }
  489.  
  490.  
  491. #ifdef MAIN_DEBUG
  492.  
  493. #include <io.h>
  494. #include <fcntl.h>
  495. #include <conio.h>
  496.  
  497. int input_handle;
  498. int switch_sign = FALSE;
  499.  
  500. size_t dartCallback (void *Buffer, size_t BufferSize)
  501. {
  502.   size_t bytesread = 1, count = 0;
  503.   while ((bytesread) && (count < BufferSize))
  504.   {
  505.     bytesread = read (input_handle, &((char *)Buffer) [count], BufferSize - count);
  506.     if ((int)bytesread == -1)
  507.       break;
  508.     count += bytesread;
  509.   }
  510.   if (switch_sign)
  511.   {
  512.     char *sample = (char *)Buffer;
  513.     char *lastsample = ((char *)Buffer) + count;
  514.     while (sample < lastsample)
  515.     {
  516.       sample++;
  517.       *sample ^= 0x80;
  518.       sample++;
  519.     } /* endwhile */
  520.   } /* endif */
  521.  
  522.   return count;
  523. }
  524.  
  525. int read_key(void)
  526. {
  527.     static ULONG time = 0;
  528.     KBDKEYINFO Char;
  529.  
  530.     KbdCharIn(&Char, IO_NOWAIT, 0);
  531.  
  532.     if (time == Char.time)
  533.         return 0;
  534.  
  535.     time = Char.time;
  536.  
  537.     return Char.chChar;
  538. }
  539.  
  540. int main()
  541. {
  542.     APIRET rc;
  543.     int key;
  544.  
  545.     input_handle = open("debug.wav", O_RDONLY | O_BINARY);
  546.  
  547.     rc = dart_init(0, BPS_16, 44100, MCI_WAVE_FORMAT_PCM, 2, 2, dartCallback);
  548.     dart_play();
  549.  
  550.     while(DART.Stopped == FALSE)
  551.     {
  552.         key = read_key();
  553.  
  554.         if (key == 27)
  555.             break;
  556.  
  557.         if (key == 113)
  558.             dart_stop();
  559.  
  560.         if (key == 119)
  561.             dart_play();
  562.  
  563.         if (key == 101)
  564.             dart_pause();
  565.  
  566.         if (key == 114)
  567.             dart_resume();
  568.  
  569.         if (key == 99)
  570.             dart_set_pos(14000L);
  571.  
  572.         fprintf(stdout, "Played: %ld %d \r", dart_get_pos(), key);
  573.         fflush(stdout);
  574.         DosSleep(200);
  575.     }
  576.  
  577.     dart_close();
  578.  
  579.     return 0;
  580. }
  581.  
  582. #endif