fluid_dart.c
上传用户:tjmskj2
上传日期:2020-08-17
资源大小:577k
文件大小:8k
源码类别:

midi

开发平台:

C/C++

  1. /* FluidSynth - A Software Synthesizer
  2.  *
  3.  * Copyright (C) 2003  Peter Hanappe and others.
  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 License
  7.  * as published by the Free Software Foundation; either version 2 of
  8.  * the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful, but
  11.  * 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.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  18.  * 02111-1307, USA
  19.  */
  20. /* fluid_dart.c
  21.  *
  22.  * Driver for OS/2 DART
  23.  *
  24.  */
  25. #include "fluid_adriver.h"
  26. #include "fluid_settings.h"
  27. #include "fluid_sys.h"
  28. #if DART_SUPPORT
  29. /* To avoid name conflict */
  30. #undef VERSION
  31. #define INCL_DOS
  32. #include <os2.h>
  33. #define INCL_OS2MM
  34. #include <os2me.h>
  35. #define NUM_MIX_BUFS        2
  36. /** fluid_dart_audio_driver_t
  37.  *
  38.  * This structure should not be accessed directly. Use audio port
  39.  * functions instead.
  40.  */
  41. typedef struct {
  42.     fluid_audio_driver_t driver;
  43.     fluid_synth_t* synth;
  44.     int frame_size;
  45.     USHORT usDeviceID;                          /* Amp Mixer device id     */
  46.     MCI_MIX_BUFFER MixBuffers[NUM_MIX_BUFS];    /* Device buffers          */
  47.     MCI_MIXSETUP_PARMS MixSetupParms;           /* Mixer parameters        */
  48.     MCI_BUFFER_PARMS BufferParms;               /* Device buffer parms     */
  49. } fluid_dart_audio_driver_t;
  50. static HMODULE m_hmodMDM = NULLHANDLE;
  51. static ULONG (APIENTRY *m_pfnmciSendCommand)(USHORT, USHORT, ULONG, PVOID, USHORT) = NULL;
  52. fluid_audio_driver_t* new_fluid_dart_audio_driver(fluid_settings_t* settings,
  53.                           fluid_synth_t* synth);
  54. int delete_fluid_dart_audio_driver(fluid_audio_driver_t* p);
  55. void fluid_dart_audio_driver_settings(fluid_settings_t* settings);
  56. static LONG APIENTRY fluid_dart_audio_run( ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags );
  57. /**************************************************************
  58.  *
  59.  *        DART audio driver
  60.  *
  61.  */
  62. void fluid_dart_audio_driver_settings(fluid_settings_t* settings)
  63. {
  64.     fluid_settings_register_str(settings, "audio.dart.device", "default", 0, NULL, NULL);
  65. }
  66. fluid_audio_driver_t*
  67. new_fluid_dart_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
  68. {
  69.     fluid_dart_audio_driver_t* dev;
  70.     double sample_rate;
  71.     int periods, period_size;
  72.     UCHAR szFailedName[ 256 ];
  73.     MCI_AMP_OPEN_PARMS AmpOpenParms;
  74.     int i;
  75.     ULONG rc;
  76.     dev = FLUID_NEW(fluid_dart_audio_driver_t);
  77.     if (dev == NULL) {
  78.         FLUID_LOG(FLUID_ERR, "Out of memory");
  79.         return NULL;
  80.     }
  81.     FLUID_MEMSET(dev, 0, sizeof(fluid_dart_audio_driver_t));
  82.     fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);
  83.     fluid_settings_getint(settings, "audio.periods", &periods);
  84.     fluid_settings_getint(settings, "audio.period-size", &period_size);
  85.     /* check the format */
  86.     if (!fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) {
  87.         FLUID_LOG(FLUID_ERR, "Unhandled sample format");
  88.         goto error_recovery;
  89.     }
  90.     dev->synth = synth;
  91.     dev->frame_size = 2 * sizeof(short);
  92.     /* Load only once
  93.      */
  94.     if( m_hmodMDM == NULLHANDLE )
  95.     {
  96.         rc = DosLoadModule(szFailedName, sizeof(szFailedName), "MDM", &m_hmodMDM);
  97.         if (rc != 0 ) {
  98.             FLUID_LOG(FLUID_ERR, "Cannot load MDM.DLL for DART due to %s", szFailedName);
  99.             goto error_recovery;
  100.         }
  101.         rc = DosQueryProcAddr(m_hmodMDM, 1, NULL, (PFN *)&m_pfnmciSendCommand);
  102.         if (rc != 0 ) {
  103.             FLUID_LOG(FLUID_ERR, "Cannot find mciSendCommand() in MDM.DLL");
  104.             DosFreeModule(m_hmodMDM);
  105.             m_hmodMDM = NULLHANDLE;
  106.             goto error_recovery;
  107.         }
  108.     }
  109.     /* open the mixer device
  110.      */
  111.     FLUID_MEMSET(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS));
  112.     AmpOpenParms.usDeviceID = (USHORT)0;
  113.     AmpOpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;
  114.     rc = m_pfnmciSendCommand(0, MCI_OPEN,
  115.                              MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
  116.                              (PVOID)&AmpOpenParms, 0);
  117.     if (rc != MCIERR_SUCCESS) {
  118.         FLUID_LOG(FLUID_ERR, "Cannot open DART, rc = %lu", rc);
  119.         goto error_recovery;
  120.     }
  121.     dev->usDeviceID = AmpOpenParms.usDeviceID;
  122.     /* Set the MixSetupParms data structure to match the requirements.
  123.      * This is a global that is used to setup the mixer.
  124.      */
  125.     dev->MixSetupParms.ulBitsPerSample = BPS_16;
  126.     dev->MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM;
  127.     dev->MixSetupParms.ulSamplesPerSec = sample_rate;
  128.     dev->MixSetupParms.ulChannels = 2;
  129.     /* Setup the mixer for playback of wave data
  130.      */
  131.     dev->MixSetupParms.ulFormatMode = MCI_PLAY;
  132.     dev->MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
  133.     dev->MixSetupParms.pmixEvent    = fluid_dart_audio_run;
  134.     rc = m_pfnmciSendCommand(dev->usDeviceID, MCI_MIXSETUP,
  135.                              MCI_WAIT | MCI_MIXSETUP_INIT,
  136.                              (PVOID)&dev->MixSetupParms, 0);
  137.     if (rc != MCIERR_SUCCESS) {
  138.         FLUID_LOG(FLUID_ERR, "Cannot setup DART, rc = %lu", rc);
  139.         goto error_recovery;
  140.     }
  141.     /* Set up the BufferParms data structure and allocate
  142.      * device buffers from the Amp-Mixer
  143.      */
  144.     dev->BufferParms.ulNumBuffers = NUM_MIX_BUFS;
  145.     dev->BufferParms.ulBufferSize = periods * period_size * dev->frame_size;
  146.     dev->BufferParms.pBufList = dev->MixBuffers;
  147.     rc = m_pfnmciSendCommand(dev->usDeviceID, MCI_BUFFER,
  148.                              MCI_WAIT | MCI_ALLOCATE_MEMORY,
  149.                              (PVOID)&dev->BufferParms, 0);
  150.     if ((USHORT)rc != MCIERR_SUCCESS) {
  151.         FLUID_LOG(FLUID_ERR, "Cannot allocate memory for DART, rc = %lu", rc);
  152.         goto error_recovery;
  153.     }
  154.     /* Initialize all device buffers.
  155.      */
  156.     for (i = 0; i < NUM_MIX_BUFS; i++) {
  157.        FLUID_MEMSET(dev->MixBuffers[i].pBuffer, 0, dev->BufferParms.ulBufferSize);
  158.        dev->MixBuffers[i].ulBufferLength = dev->BufferParms.ulBufferSize;
  159.        dev->MixBuffers[i].ulFlags = 0;
  160.        dev->MixBuffers[i].ulUserParm = (ULONG)dev;
  161.        fluid_synth_write_s16(dev->synth, dev->MixBuffers[i].ulBufferLength / dev->frame_size,
  162.                              dev->MixBuffers[i].pBuffer, 0, 2, dev->MixBuffers[i].pBuffer, 1, 2 );
  163.     }
  164.     /* Write buffers to kick off the amp mixer.
  165.      */
  166.     dev->MixSetupParms.pmixWrite(dev->MixSetupParms.ulMixHandle,
  167.                                  dev->MixBuffers,
  168.                                  NUM_MIX_BUFS);
  169.     return (fluid_audio_driver_t*) dev;
  170. error_recovery:
  171.     delete_fluid_dart_audio_driver((fluid_audio_driver_t*) dev);
  172.     return NULL;
  173. }
  174. int delete_fluid_dart_audio_driver(fluid_audio_driver_t* p)
  175. {
  176.     fluid_dart_audio_driver_t* dev = (fluid_dart_audio_driver_t*) p;
  177.     if (dev == NULL) {
  178.         return FLUID_OK;
  179.     }
  180.     if (dev->usDeviceID != 0) {
  181.         MCI_GENERIC_PARMS    GenericParms;
  182.         /* Send message to stop the audio device
  183.          */
  184.         m_pfnmciSendCommand(dev->usDeviceID, MCI_STOP, MCI_WAIT,
  185.                             (PVOID)&GenericParms, 0);
  186.         /* Deallocate device buffers
  187.          */
  188.         m_pfnmciSendCommand(dev->usDeviceID, MCI_BUFFER,
  189.                             MCI_WAIT | MCI_DEALLOCATE_MEMORY,
  190.                             (PVOID)&dev->BufferParms, 0);
  191.         /* Close device the mixer device
  192.          */
  193.         m_pfnmciSendCommand(dev->usDeviceID, MCI_CLOSE, MCI_WAIT,
  194.                             (PVOID)&GenericParms, 0);
  195.     }
  196.     FLUID_FREE(dev);
  197.     return FLUID_OK;
  198. }
  199. static LONG APIENTRY fluid_dart_audio_run( ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags )
  200. {
  201.     fluid_dart_audio_driver_t* dev=(fluid_dart_audio_driver_t*)pBuffer->ulUserParm;
  202.     switch( ulFlags ) {
  203.         case MIX_STREAM_ERROR | MIX_WRITE_COMPLETE: /* error occur in device */
  204.         case MIX_WRITE_COMPLETE:                    /* for playback  */
  205.             FLUID_MEMSET(pBuffer->pBuffer, 0, pBuffer->ulBufferLength);
  206.             fluid_synth_write_s16(dev->synth, pBuffer->ulBufferLength / dev->frame_size,
  207.                                   pBuffer->pBuffer, 0, 2, pBuffer->pBuffer, 1, 2 );
  208.             dev->MixSetupParms.pmixWrite(dev->MixSetupParms.ulMixHandle, pBuffer, 1);
  209.             break;
  210.     }
  211.     return TRUE;
  212. }
  213. #endif /* #if DART_SUPPORT */