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

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_sndmgr.c
  21.  *
  22.  * Driver for MacOS Classic
  23.  */
  24. #if SNDMAN_SUPPORT
  25. #include "fluid_synth.h"
  26. #include "fluid_adriver.h"
  27. #include "fluid_settings.h"
  28. #include <Sound.h>
  29. typedef struct {
  30.   fluid_audio_driver_t driver;
  31.   SndDoubleBufferHeader2* doubleHeader;
  32.   SndDoubleBackUPP doubleCallbackProc;
  33.   SndChannelPtr channel;
  34.   int callback_is_audio_func;
  35.   void* data;
  36.   fluid_audio_func_t callback;
  37.   float* convbuffers[2];
  38.   int bufferByteSize;
  39.   int bufferFrameSize;
  40. } fluid_sndmgr_audio_driver_t;
  41. fluid_audio_driver_t* new_fluid_sndmgr_audio_driver(fluid_settings_t* settings,
  42.     fluid_synth_t* synth);
  43. fluid_audio_driver_t* new_fluid_sndmgr_audio_driver2(fluid_settings_t* settings,
  44.      fluid_audio_func_t func,
  45.      void* data);
  46. int delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t* p);
  47. void  pascal fluid_sndmgr_callback(SndChannelPtr chan, SndDoubleBufferPtr doubleBuffer);
  48. Fixed fluid_sndmgr_double_to_fix(long double theLD);
  49. /*
  50.  * generic new : returns error
  51.  */
  52. int
  53. start_fluid_sndmgr_audio_driver(fluid_settings_t* settings,
  54. fluid_sndmgr_audio_driver_t* dev,
  55. int buffer_size)
  56. {
  57.   int i;
  58.   SndDoubleBufferHeader2* doubleHeader = NULL;
  59.   SndDoubleBufferPtr doubleBuffer = NULL;
  60.   OSErr err;
  61.   SndChannelPtr channel = NULL;
  62.   double sample_rate;
  63.   fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);
  64.   dev->doubleCallbackProc = NewSndDoubleBackProc(fluid_sndmgr_callback);
  65.   /* the channel */
  66.   FLUID_LOG(FLUID_DBG, "FLUID-SndManager@2");
  67.   err = SndNewChannel(&channel, sampledSynth, initStereo, NULL);
  68.   if ((err != noErr) || (channel == NULL)) {
  69.     FLUID_LOG(FLUID_ERR, "Failed to allocate a sound channel (error %i)", err);
  70.     return err;
  71.   }
  72.   /* the double buffer struct */
  73.   FLUID_LOG(FLUID_DBG, "FLUID-SndManager@3");
  74.   doubleHeader = FLUID_NEW(SndDoubleBufferHeader2);
  75.   if (doubleHeader == NULL) {
  76.     FLUID_LOG(FLUID_PANIC, "Out of memory");
  77.     return -1;
  78.   }
  79.   doubleHeader->dbhBufferPtr[0] = NULL;
  80.   doubleHeader->dbhBufferPtr[1] = NULL;
  81.   doubleHeader->dbhNumChannels = 2;
  82.   doubleHeader->dbhSampleSize = 16;
  83.   doubleHeader->dbhCompressionID = 0;
  84.   doubleHeader->dbhPacketSize = 0;
  85.   doubleHeader->dbhSampleRate = fluid_sndmgr_double_to_fix((long double) sample_rate);
  86.   doubleHeader->dbhDoubleBack = dev->doubleCallbackProc;
  87.   doubleHeader->dbhFormat = 0;
  88.   /* prepare dev */
  89.   FLUID_LOG(FLUID_DBG, "FLUID-SndManager@4");
  90.   dev->doubleHeader = doubleHeader;
  91.   dev->channel = channel;
  92.   dev->bufferFrameSize = buffer_size;
  93.   dev->bufferByteSize = buffer_size * 2 * 2;
  94.   /* the 2 doublebuffers */
  95.   FLUID_LOG(FLUID_DBG, "FLUID-SndManager@5");
  96.   for (i = 0; i < 2; i++) {
  97.     doubleBuffer = (SndDoubleBufferPtr) FLUID_MALLOC(sizeof(SndDoubleBuffer)
  98.      + dev->bufferByteSize);
  99.     if (doubleBuffer == NULL) {
  100.       FLUID_LOG(FLUID_PANIC, "Out of memory");
  101.       return -1;
  102.     }
  103.     doubleBuffer->dbNumFrames = 0;
  104.     doubleBuffer->dbFlags = 0;
  105.     doubleBuffer->dbUserInfo[0] = (long) dev;
  106.     doubleHeader->dbhBufferPtr[i] = doubleBuffer;
  107.     CallSndDoubleBackProc(doubleHeader->dbhDoubleBack, channel, doubleBuffer);
  108.   }
  109.   /* start */
  110.   FLUID_LOG(FLUID_DBG, "FLUID-SndManager@6");
  111.   err = SndPlayDoubleBuffer(channel, (SndDoubleBufferHeader *)doubleHeader);
  112.   if (err != noErr) {
  113.     FLUID_LOG(FLUID_ERR, "Failed to start the sound driver (error %i)", err);
  114.     return err;
  115.   }
  116.   FLUID_LOG(FLUID_DBG, "FLUID-SndManager@7");
  117.   return 0;
  118. }
  119. /*
  120.  * new_fluid_sndmgr_audio_driver
  121.  * This implementation used the 16bit format.
  122.  */
  123. fluid_audio_driver_t*
  124. new_fluid_sndmgr_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
  125. {
  126.   fluid_sndmgr_audio_driver_t* dev = NULL;
  127.   int period_size, periods, buffer_size;
  128.   /* check the format */
  129.   if (!fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) {
  130.     FLUID_LOG(FLUID_ERR, "Unhandled sample format");
  131.     return NULL;
  132.   }
  133.   /* compute buffer size */
  134.   fluid_settings_getint(settings, "audio.period-size", &period_size);
  135.   fluid_settings_getint(settings, "audio.periods", &periods);
  136.   buffer_size = period_size*periods;
  137.   /* allocated dev */
  138.   dev = FLUID_NEW(fluid_sndmgr_audio_driver_t);
  139.   if (dev == NULL) {
  140.     FLUID_LOG(FLUID_PANIC, "Out of memory");
  141.     return NULL;
  142.   }
  143.   FLUID_MEMSET(dev, 0, sizeof(fluid_sndmgr_audio_driver_t));
  144.   dev->callback_is_audio_func = false;
  145.   dev->data = (void *)synth;
  146.   dev->callback = NULL;
  147.   if (start_fluid_sndmgr_audio_driver(settings, dev, buffer_size) != 0) {
  148.     delete_fluid_sndmgr_audio_driver((fluid_audio_driver_t*)dev);
  149.     return NULL;
  150.   }
  151.   return (fluid_audio_driver_t*)dev;
  152. }
  153. /*
  154.  * new_fluid_sndmgr_audio_driver2
  155.  *
  156.  * This implementation used the audio_func float format, with
  157.  * conversion from float to 16bits in the driver.
  158.  */
  159. fluid_audio_driver_t*
  160. new_fluid_sndmgr_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data)
  161. {
  162.   fluid_sndmgr_audio_driver_t* dev = NULL;
  163.   int period_size, periods, buffer_size;
  164.   /* compute buffer size */
  165.   fluid_settings_getint(settings, "audio.period-size", &period_size);
  166.   fluid_settings_getint(settings, "audio.periods", &periods);
  167.   buffer_size = period_size*periods;
  168.   /* allocated dev */
  169.   dev = FLUID_NEW(fluid_sndmgr_audio_driver_t);
  170.   if (dev == NULL) {
  171.     FLUID_LOG(FLUID_PANIC, "Out of memory");
  172.     return NULL;
  173.   }
  174.   FLUID_MEMSET(dev, 0, sizeof(fluid_sndmgr_audio_driver_t));
  175.   /* allocate the conversion buffers */
  176.   dev->convbuffers[0] = FLUID_ARRAY(float, buffer_size);
  177.   dev->convbuffers[1] = FLUID_ARRAY(float, buffer_size);
  178.   if ((dev->convbuffers[0] == NULL) || (dev->convbuffers[1] == NULL)) {
  179.     FLUID_LOG(FLUID_PANIC, "Out of memory");
  180.     goto error_recovery;
  181.   }
  182.   dev->callback_is_audio_func = true;
  183.   dev->data = data;
  184.   dev->callback = func;
  185.   if (start_fluid_sndmgr_audio_driver(settings, dev, buffer_size) != 0) {
  186.     goto error_recovery;
  187.   }
  188.   return (fluid_audio_driver_t*)dev;
  189.  error_recovery:
  190.   delete_fluid_sndmgr_audio_driver((fluid_audio_driver_t*)dev);
  191.   return NULL;
  192. }
  193. /*
  194.  * delete_fluid_sndmgr_audio_driver
  195.  */
  196. int delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t* p)
  197. {
  198.   fluid_sndmgr_audio_driver_t* dev = (fluid_sndmgr_audio_driver_t*) p;
  199.   if (dev != NULL) {
  200.     if (dev->channel != NULL) {
  201.       SndDisposeChannel(dev->channel, 1);
  202.     }
  203.     if (dev->doubleCallbackProc != NULL) {
  204.       DisposeRoutineDescriptor(dev->doubleCallbackProc);
  205.     }
  206.     if (dev->doubleHeader != NULL) {
  207.       if(dev->doubleHeader->dbhBufferPtr[0] != NULL) {
  208. FLUID_FREE(dev->doubleHeader->dbhBufferPtr[0]);
  209.       }
  210.       if (dev->doubleHeader->dbhBufferPtr[1] != NULL) {
  211. FLUID_FREE(dev->doubleHeader->dbhBufferPtr[1]);
  212.       }
  213.       FLUID_FREE(dev->doubleHeader);
  214.     }
  215.     if (dev->convbuffers[0] != NULL) {
  216.       FLUID_FREE(dev->convbuffers[0]);
  217.     }
  218.     if (dev->convbuffers[1] != NULL) {
  219.       FLUID_FREE(dev->convbuffers[1]);
  220.     }
  221.     FLUID_FREE(dev);
  222.   }
  223.   return 0;
  224. }
  225. /*
  226.  * fluid_sndmgr_callback
  227.  *
  228.  */
  229. void  pascal fluid_sndmgr_callback(SndChannelPtr chan, SndDoubleBufferPtr doubleBuffer)
  230. {
  231.   fluid_sndmgr_audio_driver_t* dev;
  232.   signed short* buf;
  233.   float* left;
  234.   float* right;
  235.   float v;
  236.   int i, k, buffer_size;
  237.   dev = (fluid_sndmgr_audio_driver_t*) doubleBuffer->dbUserInfo[0];
  238.   buf = (signed short*)doubleBuffer->dbSoundData;
  239.   buffer_size = dev->bufferFrameSize;
  240.   if (dev->callback_is_audio_func) {
  241.     /* float API : conversion to signed short */
  242.     left = dev->convbuffers[0];
  243.     right = dev->convbuffers[1];
  244.     (*dev->callback)(dev->data, buffer_size, 0, NULL, 2, dev->convbuffers);
  245.     for (i = 0, k = 0; i < buffer_size; i++) {
  246.       v = 32767.0f * left[i];
  247.       fluid_clip(v, -32768.0f, 32767.0f);
  248.       buf[k++] = (signed short) v;
  249.       v = 32767.0f * right[i];
  250.       fluid_clip(v, -32768.0f, 32767.0f);
  251.       buf[k++] = (signed short) v;
  252.     }
  253.   } else {
  254.     /* let the synth do the convertion */
  255.     fluid_synth_write_s16((fluid_synth_t*)dev->data, buffer_size, buf, 0, 2, buf, 1, 2);
  256.   }
  257.   doubleBuffer->dbFlags = doubleBuffer->dbFlags | dbBufferReady;
  258.   doubleBuffer->dbNumFrames = buffer_size;
  259. }
  260. /*
  261.  * fluid_sndmgr_double_to_fix
  262.  *
  263.  * A Fixed number is of the type 12345.67890.  It is 32 bits in size with the
  264.  * high order bits representing the significant value (that before the point)
  265.  * and the lower 16 bits representing the fractional part of the number.
  266.  * The Sound Manager further complicates matters by using Fixed numbers, but
  267.  * needing to represent numbers larger than what the Fixed is capable of.
  268.  * To do this the Sound Manager treats the sign bit as having the value 32768
  269.  * which will cause any number greater or equal to 32768 to look like it is
  270.  * negative.
  271.  * This routine is designed to "do the right thing" and convert any long double
  272.  * into the Fixed number it represents.
  273.  * long double is the input type because AIFF files use extended80 numbers and
  274.  * there are routines that will convert from an extended80 to a long double.
  275.  * A long double has far greater precision than a Fixed, so any number whose
  276.  * significant or fraction is larger than 65535 will not convert correctly.
  277.  */
  278. #define _MAX_VALUE     65535
  279. #define _BITS_PER_BYTE 8
  280. Fixed fluid_sndmgr_double_to_fix(long double theLD) {
  281.   unsigned long theResult = 0;
  282.   unsigned short theSignificant = 0, theFraction = 0;
  283.   if (theLD < _MAX_VALUE) {
  284.     theSignificant = theLD;
  285.     theFraction = theLD - theSignificant;
  286.     if (theFraction > _MAX_VALUE) {
  287.       /* Won't be able to convert */
  288.       theSignificant = 0;
  289.       theFraction = 0;
  290.     }
  291.   }
  292.   theResult |= theSignificant;
  293.   theResult = theResult << (sizeof (unsigned short) * _BITS_PER_BYTE);
  294.   theResult |= theFraction;
  295.   return theResult;
  296. }
  297. #endif