2013/01/26

Reverbの自作4 comb filter の並列処理

まずは古典的デジタルリバーブであるManfred R. Schroederのアルゴリズムをなぞるという意味でリバーブの実験をしている。そのメインの部分がこのcomb filterの並列処理。4つのcomb filterをつないで、遅延時間、ゲインを調整することで、リバーブの基本となる後部残響をつくり出す。プログラムはダラダラと長くなってしまったが、そこそこ実現できたと思う。

ブロック図

DIAを使って描いてみたのだが、細かな調整ができない・・・ 次回はinkscapeを使おうかな・・


LADSPA プラグイン

Audacityで表示させたところ。毎回入力する面倒はあるが、あれこれ実験するには悪くはない。


デルタ関数を使って実験

デルタ関数に上記設定を適用してみる。

実験的にゲインをマイナスにしてみた。下の上段がgainプラスで、下段がgainマイナス。


次は、今まで作ったパーツ使って実際の音処理をしてみようと思う。

C LADSPA comb filter 並列処理 ソースコード

/* namagi_comb_parallel.c 2013.01.26
compile
gcc -shared -o namagi_comb_parallel.dll namagi_comb_parallel.c -ID
*/
/***********************************************************/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "ladspa.h"
#define MAX_DELAY       100

#define COMB_CHECKBOX1   0
#define COMB_DELAY1      1
#define COMB_FEEDBACK1   2

#define COMB_CHECKBOX2   3
#define COMB_DELAY2      4
#define COMB_FEEDBACK2   5

#define COMB_CHECKBOX3   6
#define COMB_DELAY3      7
#define COMB_FEEDBACK3   8

#define COMB_CHECKBOX4   9
#define COMB_DELAY4      10
#define COMB_FEEDBACK4   11

#define COMB_INPUT       12
#define COMB_OUTPUT      13
/***********************************************************/
/* Win用設定 */
#ifdef WIN32
int bIsFirstTime = 1; 
void _init();
#endif
#ifdef WIN32
 #define _WINDOWS_DLL_EXPORT_ __declspec(dllexport)
#else
    #define _WINDOWS_DLL_EXPORT_ 
#endif
/***********************************************************/
#define LIMIT_BETWEEN_0_AND_MAX_DELAY(x)  \
(((x) < 0) ? 0 : (((x) > MAX_DELAY) ? MAX_DELAY : (x)))
/***********************************************************/
typedef struct {
  LADSPA_Data m_fSampleRate; 
  LADSPA_Data *m_pfBuffer1;
  LADSPA_Data *m_pfBuffer2;
  LADSPA_Data *m_pfBuffer3;
  LADSPA_Data *m_pfBuffer4;
  unsigned long m_lBufferSize1;
  unsigned long m_lBufferSize2;
  unsigned long m_lBufferSize3;
  unsigned long m_lBufferSize4;
  unsigned long m_lWritePointer1;
  unsigned long m_lWritePointer2;
  unsigned long m_lWritePointer3;
  unsigned long m_lWritePointer4;
  LADSPA_Data *m_pfCheckBox1;
  LADSPA_Data *m_pfCheckBox2;
  LADSPA_Data *m_pfCheckBox3;
  LADSPA_Data *m_pfCheckBox4;
  LADSPA_Data *m_pfDelay1;
  LADSPA_Data *m_pfDelay2;
  LADSPA_Data *m_pfDelay3;
  LADSPA_Data *m_pfDelay4;
  LADSPA_Data *m_pfFeedback1;
  LADSPA_Data *m_pfFeedback2;
  LADSPA_Data *m_pfFeedback3;
  LADSPA_Data *m_pfFeedback4;
  LADSPA_Data *m_pfInput;
  LADSPA_Data *m_pfOutput;
} SimpleDelayLine;
/***********************************************************/
LADSPA_Handle 
instantiateSimpleDelayLine(const LADSPA_Descriptor
      * Descriptor, unsigned long SampleRate){
  unsigned long lMinimumBufferSize;
  SimpleDelayLine * psDelayLine;

  psDelayLine =
    (SimpleDelayLine *)malloc(sizeof(SimpleDelayLine));
  if (psDelayLine == NULL) return NULL;
  
  psDelayLine -> m_fSampleRate =
     (LADSPA_Data)SampleRate;
  lMinimumBufferSize = (LADSPA_Data)SampleRate;
  
  psDelayLine -> m_lBufferSize1 = 1;
  while (psDelayLine ->
    m_lBufferSize1 < lMinimumBufferSize)
    psDelayLine -> m_lBufferSize1 <<= 1;
  psDelayLine -> m_lBufferSize2 = 1;
  while (psDelayLine ->
    m_lBufferSize2 < lMinimumBufferSize)
    psDelayLine -> m_lBufferSize2 <<= 1;
  psDelayLine -> m_lBufferSize3 = 1;
  while (psDelayLine ->
    m_lBufferSize3 < lMinimumBufferSize)
    psDelayLine -> m_lBufferSize3 <<= 1;
  psDelayLine -> m_lBufferSize4 = 1;
  while (psDelayLine ->
    m_lBufferSize4 < lMinimumBufferSize)
    psDelayLine -> m_lBufferSize4 <<= 1;

  psDelayLine -> m_pfBuffer1 = 
    (LADSPA_Data *)calloc(psDelayLine ->
     m_lBufferSize1, sizeof(LADSPA_Data));
  psDelayLine -> m_pfBuffer2 = 
    (LADSPA_Data *)calloc(psDelayLine ->
     m_lBufferSize2, sizeof(LADSPA_Data));
  psDelayLine -> m_pfBuffer3 = 
    (LADSPA_Data *)calloc(psDelayLine ->
     m_lBufferSize3, sizeof(LADSPA_Data));
  psDelayLine -> m_pfBuffer4 = 
    (LADSPA_Data *)calloc(psDelayLine ->
     m_lBufferSize4, sizeof(LADSPA_Data));


  if (psDelayLine -> m_pfBuffer1 == NULL) {
    free(psDelayLine);
    return NULL;
  }
  if (psDelayLine -> m_pfBuffer2 == NULL) {
    free(psDelayLine);
    return NULL;
  }
  if (psDelayLine -> m_pfBuffer3 == NULL) {
    free(psDelayLine);
    return NULL;
  }
  if (psDelayLine -> m_pfBuffer4 == NULL) {
    free(psDelayLine);
    return NULL;
  }

  psDelayLine -> m_lWritePointer1 = 0;
  psDelayLine -> m_lWritePointer2 = 0;
  psDelayLine -> m_lWritePointer3 = 0;
  psDelayLine -> m_lWritePointer4 = 0;
  return psDelayLine;
}
/***********************************************************/
void activateSimpleDelayLine(LADSPA_Handle Instance) {
  SimpleDelayLine *psSimpleDelayLine;
  psSimpleDelayLine = (SimpleDelayLine *)Instance;
  memset(psSimpleDelayLine -> m_pfBuffer1, 0, 
      sizeof(LADSPA_Data) *psSimpleDelayLine ->
      m_lBufferSize1);
  memset(psSimpleDelayLine -> m_pfBuffer2, 0, 
      sizeof(LADSPA_Data) *psSimpleDelayLine ->
      m_lBufferSize2);
  memset(psSimpleDelayLine -> m_pfBuffer3, 0, 
      sizeof(LADSPA_Data) *psSimpleDelayLine ->
      m_lBufferSize3);
  memset(psSimpleDelayLine -> m_pfBuffer4, 0, 
      sizeof(LADSPA_Data) *psSimpleDelayLine ->
      m_lBufferSize4);
}
/***********************************************************/
void connectPortToSimpleDelayLine(LADSPA_Handle Instance,
         unsigned long Port,LADSPA_Data * DataLocation){
  SimpleDelayLine * psSimpleDelayLine;
  psSimpleDelayLine = (SimpleDelayLine *)Instance;
  
  switch (Port) {
  case COMB_CHECKBOX1:
    psSimpleDelayLine -> m_pfCheckBox1 = DataLocation;
    break;
  case COMB_DELAY1:
    psSimpleDelayLine -> m_pfDelay1 = DataLocation;
    break;
  case COMB_FEEDBACK1:
    psSimpleDelayLine -> m_pfFeedback1 = DataLocation;
    break;    
  case COMB_CHECKBOX2:
    psSimpleDelayLine -> m_pfCheckBox2 = DataLocation;
    break;
  case COMB_DELAY2:
    psSimpleDelayLine -> m_pfDelay2 = DataLocation;
    break;  
  case COMB_FEEDBACK2:
    psSimpleDelayLine -> m_pfFeedback2 = DataLocation;
    break;
  case COMB_CHECKBOX3:
    psSimpleDelayLine -> m_pfCheckBox3 = DataLocation;
    break;
  case COMB_DELAY3:
    psSimpleDelayLine -> m_pfDelay3 = DataLocation;
    break;  
  case COMB_FEEDBACK3:
    psSimpleDelayLine -> m_pfFeedback3 = DataLocation;
    break;
  case COMB_CHECKBOX4:
    psSimpleDelayLine -> m_pfCheckBox4 = DataLocation;
    break;
  case COMB_DELAY4:
    psSimpleDelayLine -> m_pfDelay4 = DataLocation;
    break;  
  case COMB_FEEDBACK4:
    psSimpleDelayLine -> m_pfFeedback4 = DataLocation;
    break;
  case COMB_INPUT:
    psSimpleDelayLine -> m_pfInput = DataLocation;
    break;
  case COMB_OUTPUT:
    psSimpleDelayLine -> m_pfOutput = DataLocation;
    break;
  }
}
/***********************************************************/
void runSimpleDelayLine(LADSPA_Handle Instance, 
                    unsigned long SampleCount){
  LADSPA_Data *pfBuffer1;
  LADSPA_Data *pfBuffer2;
  LADSPA_Data *pfBuffer3;
  LADSPA_Data *pfBuffer4;
  LADSPA_Data *pfInput;
  LADSPA_Data *pfOutput;
  LADSPA_Data fInputSample;
  LADSPA_Data fOutputSample1;
  LADSPA_Data fOutputSample2;
  LADSPA_Data fOutputSample3;
  LADSPA_Data fOutputSample4;
  LADSPA_Data fFeedback1;
  LADSPA_Data fFeedback2;
  LADSPA_Data fFeedback3;
  LADSPA_Data fFeedback4;
  LADSPA_Data fCheckBox1;
  LADSPA_Data fCheckBox2;
  LADSPA_Data fCheckBox3;
  LADSPA_Data fCheckBox4;
  SimpleDelayLine *psSimpleDelayLine;
  unsigned long lBufferReadOffset1;
  unsigned long lBufferReadOffset2;
  unsigned long lBufferReadOffset3;
  unsigned long lBufferReadOffset4;
  unsigned long lBufferSizeMinusOne1;
  unsigned long lBufferSizeMinusOne2;
  unsigned long lBufferSizeMinusOne3;
  unsigned long lBufferSizeMinusOne4;
  unsigned long lBufferWriteOffset1;
  unsigned long lBufferWriteOffset2;
  unsigned long lBufferWriteOffset3;
  unsigned long lBufferWriteOffset4;
  unsigned long lDelay1;
  unsigned long lDelay2;
  unsigned long lDelay3;
  unsigned long lDelay4;
  unsigned long lSampleIndex;
  psSimpleDelayLine = (SimpleDelayLine*) Instance;
  
  lBufferSizeMinusOne1 =
     psSimpleDelayLine -> m_lBufferSize1 - 1;
  lBufferSizeMinusOne2 =
     psSimpleDelayLine -> m_lBufferSize2 - 1;
  lBufferSizeMinusOne3 =
     psSimpleDelayLine -> m_lBufferSize3 - 1;
  lBufferSizeMinusOne4 =
     psSimpleDelayLine -> m_lBufferSize4 - 1;

  lDelay1 = (unsigned long)
  (LIMIT_BETWEEN_0_AND_MAX_DELAY(*(psSimpleDelayLine
      -> m_pfDelay1))
     *psSimpleDelayLine -> m_fSampleRate);
  lDelay2 = (unsigned long)
  (LIMIT_BETWEEN_0_AND_MAX_DELAY(*(psSimpleDelayLine
      -> m_pfDelay2))
     *psSimpleDelayLine -> m_fSampleRate);
  lDelay3 = (unsigned long)
  (LIMIT_BETWEEN_0_AND_MAX_DELAY(*(psSimpleDelayLine
      -> m_pfDelay3))
     *psSimpleDelayLine -> m_fSampleRate);
  lDelay4 = (unsigned long)
  (LIMIT_BETWEEN_0_AND_MAX_DELAY(*(psSimpleDelayLine
      -> m_pfDelay4))
     *psSimpleDelayLine -> m_fSampleRate);

  pfInput = psSimpleDelayLine -> m_pfInput;
  pfOutput = psSimpleDelayLine -> m_pfOutput;
  
  pfBuffer1 = psSimpleDelayLine -> m_pfBuffer1;
  pfBuffer2 = psSimpleDelayLine -> m_pfBuffer2;
  pfBuffer3 = psSimpleDelayLine -> m_pfBuffer3;
  pfBuffer4 = psSimpleDelayLine -> m_pfBuffer4;

  lBufferWriteOffset1 = 
     psSimpleDelayLine -> m_lWritePointer1;
  lBufferWriteOffset2 = 
     psSimpleDelayLine -> m_lWritePointer2;
  lBufferWriteOffset3 = 
     psSimpleDelayLine -> m_lWritePointer3;
  lBufferWriteOffset4 = 
     psSimpleDelayLine -> m_lWritePointer4;
  
  lBufferReadOffset1 = 
    lBufferWriteOffset1 + psSimpleDelayLine -> 
    m_lBufferSize1 - (float)lDelay1/1000;
  lBufferReadOffset2 = 
    lBufferWriteOffset2 + psSimpleDelayLine -> 
    m_lBufferSize2 - (float)lDelay2/1000;
  lBufferReadOffset3 = 
    lBufferWriteOffset3 + psSimpleDelayLine -> 
    m_lBufferSize3 - (float)lDelay3/1000;
  lBufferReadOffset4 = 
    lBufferWriteOffset4 + psSimpleDelayLine -> 
    m_lBufferSize4 - (float)lDelay4/1000;

  fFeedback1 = *(psSimpleDelayLine -> m_pfFeedback1);
  fFeedback2 = *(psSimpleDelayLine -> m_pfFeedback2);
  fFeedback3 = *(psSimpleDelayLine -> m_pfFeedback3);
  fFeedback4 = *(psSimpleDelayLine -> m_pfFeedback4);

  fCheckBox1 = *(psSimpleDelayLine -> m_pfCheckBox1);
  fCheckBox2 = *(psSimpleDelayLine -> m_pfCheckBox2);
  fCheckBox3 = *(psSimpleDelayLine -> m_pfCheckBox3);
  fCheckBox4 = *(psSimpleDelayLine -> m_pfCheckBox4); 

  for (lSampleIndex = 0; lSampleIndex < SampleCount;
      lSampleIndex++){
      fInputSample = *(pfInput++);

/* comb 1 */
    if(fCheckBox1 == 1){
    fOutputSample1 = 
   pfBuffer1[((lSampleIndex + lBufferReadOffset1)
      & lBufferSizeMinusOne1)];
   
    pfBuffer1[((lSampleIndex + lBufferWriteOffset1)
      & lBufferSizeMinusOne1)] = 
      (fInputSample +
      fFeedback1 * pfBuffer1[((lSampleIndex +
      lBufferReadOffset1) & lBufferSizeMinusOne1)]);
     }
/* comb 2 */
    if(fCheckBox2 == 1){
    fOutputSample3 = 
   pfBuffer2[((lSampleIndex + lBufferReadOffset2)
      & lBufferSizeMinusOne2)];
   
    pfBuffer2[((lSampleIndex + lBufferWriteOffset2)
      & lBufferSizeMinusOne2)] = 
      (fInputSample +
      fFeedback2 * pfBuffer2[((lSampleIndex +
      lBufferReadOffset2) & lBufferSizeMinusOne2)]);
     }
/* comb 3 */
    if(fCheckBox3 == 1){
    fOutputSample4 = 
   pfBuffer3[((lSampleIndex + lBufferReadOffset3)
      & lBufferSizeMinusOne3)];
   
    pfBuffer3[((lSampleIndex + lBufferWriteOffset3)
      & lBufferSizeMinusOne3)] = 
      (fInputSample +
      fFeedback2 * pfBuffer3[((lSampleIndex +
      lBufferReadOffset3) & lBufferSizeMinusOne3)]);
     }
/* comb 4 */
    if(fCheckBox4 == 1){
    fOutputSample4 = 
   pfBuffer4[((lSampleIndex + lBufferReadOffset4)
      & lBufferSizeMinusOne2)];
   
    pfBuffer4[((lSampleIndex + lBufferWriteOffset4)
      & lBufferSizeMinusOne4)] = 
      (fInputSample +
      fFeedback4 * pfBuffer4[((lSampleIndex +
      lBufferReadOffset4) & lBufferSizeMinusOne4)]);
     }
/*    */
    *(pfOutput++) = fOutputSample1 + fOutputSample2 + 
                    fOutputSample3 + fOutputSample4;

  }
  psSimpleDelayLine -> m_lWritePointer1
    = ((psSimpleDelayLine -> m_lWritePointer1 + SampleCount)
    & lBufferSizeMinusOne1);
  psSimpleDelayLine -> m_lWritePointer2
    = ((psSimpleDelayLine -> m_lWritePointer2 + SampleCount)
    & lBufferSizeMinusOne2);
  psSimpleDelayLine -> m_lWritePointer3
    = ((psSimpleDelayLine -> m_lWritePointer3 + SampleCount)
    & lBufferSizeMinusOne3);
  psSimpleDelayLine -> m_lWritePointer4
    = ((psSimpleDelayLine -> m_lWritePointer4 + SampleCount)
    & lBufferSizeMinusOne4);
}
/***********************************************************/
void cleanupSimpleDelayLine(LADSPA_Handle Instance){
  SimpleDelayLine * psSimpleDelayLine;
  psSimpleDelayLine = (SimpleDelayLine *)Instance;
  free(psSimpleDelayLine -> m_pfBuffer1);
  free(psSimpleDelayLine -> m_pfBuffer2);
  free(psSimpleDelayLine -> m_pfBuffer3);
  free(psSimpleDelayLine -> m_pfBuffer4);
  free(psSimpleDelayLine);
}
/***********************************************************/
LADSPA_Descriptor *g_psDescriptor = NULL;
/***********************************************************/
void _init() {
  char ** pcPortNames;
  LADSPA_PortDescriptor * piPortDescriptors;
  LADSPA_PortRangeHint * psPortRangeHints;
  g_psDescriptor = 
    (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor));
  if (g_psDescriptor) {
    g_psDescriptor->UniqueID = 13;
    g_psDescriptor->Label = 
       strdup("comb parallel");
    g_psDescriptor->Properties = 
       LADSPA_PROPERTY_HARD_RT_CAPABLE;
    g_psDescriptor->Name = 
       strdup("Namagi: comb parallel ver.130126");
    g_psDescriptor->Maker = 
       strdup("Namagi Products");
    g_psDescriptor->Copyright = 
      strdup("None");
      
    g_psDescriptor->PortCount = 14;
    piPortDescriptors = 
      (LADSPA_PortDescriptor *)calloc(14,
       sizeof(LADSPA_PortDescriptor));
    g_psDescriptor -> PortDescriptors = 
      (const LADSPA_PortDescriptor *)piPortDescriptors;
/*comb1*/
    piPortDescriptors[COMB_CHECKBOX1] =
       LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[COMB_DELAY1] =
       LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[COMB_FEEDBACK2] =
       LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
/*comb2*/
    piPortDescriptors[COMB_CHECKBOX2] =
       LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[COMB_DELAY2] =
       LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[COMB_FEEDBACK1] =
       LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
/*comb3*/
    piPortDescriptors[COMB_CHECKBOX3] =
       LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[COMB_DELAY3] =
       LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[COMB_FEEDBACK3] =
       LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
/*comb4*/
    piPortDescriptors[COMB_CHECKBOX4] =
       LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[COMB_DELAY4] =
       LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[COMB_FEEDBACK4] =
       LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
/*IO*/
    piPortDescriptors[COMB_INPUT] =
       LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
    piPortDescriptors[COMB_OUTPUT] =
       LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
       
    pcPortNames = (char **)calloc(14, sizeof(char *));
    g_psDescriptor->PortNames =
       (const char **)pcPortNames;

    pcPortNames[COMB_CHECKBOX1] = strdup("Comb1");
    pcPortNames[COMB_DELAY1] = strdup("DelayTime1(msec)");
    pcPortNames[COMB_FEEDBACK1] = strdup("Feedback1");

    pcPortNames[COMB_CHECKBOX2] = strdup("Comb2");
    pcPortNames[COMB_DELAY2] = strdup("DelayTime2(msec)");
    pcPortNames[COMB_FEEDBACK2] = strdup("Feedback2");

    pcPortNames[COMB_CHECKBOX3] = strdup("Comb3");
    pcPortNames[COMB_DELAY3] = strdup("DelayTime3(msec)");
    pcPortNames[COMB_FEEDBACK3] = strdup("Feedback3");

    pcPortNames[COMB_CHECKBOX4] = strdup("Comb4");
    pcPortNames[COMB_DELAY4] = strdup("DelayTime4(msec)");
    pcPortNames[COMB_FEEDBACK4] = strdup("Feedback4");

    pcPortNames[COMB_INPUT] = strdup("Input");
    pcPortNames[COMB_OUTPUT] = strdup("Output");
    psPortRangeHints  =
       ((LADSPA_PortRangeHint *)calloc(14,
        sizeof(LADSPA_PortRangeHint)));
    g_psDescriptor -> PortRangeHints =
       (const LADSPA_PortRangeHint *)psPortRangeHints;
/* comb1 */
    psPortRangeHints[COMB_CHECKBOX1].HintDescriptor =
  (LADSPA_HINT_TOGGLED |
   LADSPA_HINT_DEFAULT_1);
      
    psPortRangeHints[COMB_DELAY1].HintDescriptor
      = (LADSPA_HINT_BOUNDED_BELOW | 
      LADSPA_HINT_BOUNDED_ABOVE | 
      LADSPA_HINT_DEFAULT_100);
    psPortRangeHints[COMB_DELAY1].LowerBound  = 0;
    psPortRangeHints[COMB_DELAY1].UpperBound  =
       (LADSPA_Data)MAX_DELAY; 

    psPortRangeHints[COMB_FEEDBACK1].HintDescriptor =
      (LADSPA_HINT_BOUNDED_BELOW |
   LADSPA_HINT_BOUNDED_ABOVE | 
   LADSPA_HINT_DEFAULT_HIGH);
    psPortRangeHints[COMB_FEEDBACK1].LowerBound = -1;
    psPortRangeHints[COMB_FEEDBACK1].UpperBound = 1;
/* comb2 */
    psPortRangeHints[COMB_CHECKBOX2].HintDescriptor =
  (LADSPA_HINT_TOGGLED |
   LADSPA_HINT_DEFAULT_1);
      
    psPortRangeHints[COMB_DELAY2].HintDescriptor
      = (LADSPA_HINT_BOUNDED_BELOW | 
      LADSPA_HINT_BOUNDED_ABOVE | 
      LADSPA_HINT_DEFAULT_100);
    psPortRangeHints[COMB_DELAY2].LowerBound  = 0;
    psPortRangeHints[COMB_DELAY2].UpperBound  =
     (LADSPA_Data)MAX_DELAY; 

    psPortRangeHints[COMB_FEEDBACK2].HintDescriptor =
      (LADSPA_HINT_BOUNDED_BELOW |
   LADSPA_HINT_BOUNDED_ABOVE | 
   LADSPA_HINT_DEFAULT_HIGH);
    psPortRangeHints[COMB_FEEDBACK2].LowerBound = -1;
    psPortRangeHints[COMB_FEEDBACK2].UpperBound = 1;
/* comb3 */
    psPortRangeHints[COMB_CHECKBOX3].HintDescriptor =
  (LADSPA_HINT_TOGGLED |
   LADSPA_HINT_DEFAULT_1);
      
    psPortRangeHints[COMB_DELAY3].HintDescriptor
      = (LADSPA_HINT_BOUNDED_BELOW | 
      LADSPA_HINT_BOUNDED_ABOVE | 
      LADSPA_HINT_DEFAULT_100);
    psPortRangeHints[COMB_DELAY3].LowerBound  = 0;
    psPortRangeHints[COMB_DELAY3].UpperBound  =
     (LADSPA_Data)MAX_DELAY; 

    psPortRangeHints[COMB_FEEDBACK3].HintDescriptor =
      (LADSPA_HINT_BOUNDED_BELOW |
   LADSPA_HINT_BOUNDED_ABOVE | 
   LADSPA_HINT_DEFAULT_HIGH);
    psPortRangeHints[COMB_FEEDBACK3].LowerBound = -1;
    psPortRangeHints[COMB_FEEDBACK3].UpperBound = 1;
/* comb4 */
    psPortRangeHints[COMB_CHECKBOX4].HintDescriptor =
  (LADSPA_HINT_TOGGLED |
   LADSPA_HINT_DEFAULT_1);
      
    psPortRangeHints[COMB_DELAY4].HintDescriptor
      = (LADSPA_HINT_BOUNDED_BELOW | 
      LADSPA_HINT_BOUNDED_ABOVE | 
      LADSPA_HINT_DEFAULT_100);
    psPortRangeHints[COMB_DELAY4].LowerBound  = 0;
    psPortRangeHints[COMB_DELAY4].UpperBound  =
     (LADSPA_Data)MAX_DELAY; 

    psPortRangeHints[COMB_FEEDBACK4].HintDescriptor =
      (LADSPA_HINT_BOUNDED_BELOW |
   LADSPA_HINT_BOUNDED_ABOVE | 
   LADSPA_HINT_DEFAULT_HIGH);
    psPortRangeHints[COMB_FEEDBACK4].LowerBound = -1;
    psPortRangeHints[COMB_FEEDBACK4].UpperBound = 1;
/* IO */
    psPortRangeHints[COMB_INPUT].HintDescriptor = 0;
    psPortRangeHints[COMB_OUTPUT].HintDescriptor = 0;

    g_psDescriptor -> instantiate =
       instantiateSimpleDelayLine;
    g_psDescriptor -> connect_port =
       connectPortToSimpleDelayLine;
    g_psDescriptor -> activate =
       activateSimpleDelayLine;
    g_psDescriptor -> run = runSimpleDelayLine;
    g_psDescriptor -> run_adding = NULL;
    g_psDescriptor -> set_run_adding_gain = NULL;
    g_psDescriptor -> deactivate = NULL;
    g_psDescriptor -> cleanup =
       cleanupSimpleDelayLine;
  }
}
/***********************************************************/
void _fini() {
  long lIndex;
  if (g_psDescriptor) {
    free((char *)g_psDescriptor -> Label);
    free((char *)g_psDescriptor -> Name);
    free((char *)g_psDescriptor -> Maker);
    free((char *)g_psDescriptor -> Copyright);
    free((LADSPA_PortDescriptor *)g_psDescriptor -> 
      PortDescriptors);
    for (lIndex = 0; lIndex < g_psDescriptor ->
      PortCount; lIndex++)
      free((char *)(g_psDescriptor ->
      PortNames[lIndex]));
    free((char **)g_psDescriptor -> PortNames);
    free((LADSPA_PortRangeHint *)g_psDescriptor ->
      PortRangeHints);
    free(g_psDescriptor);
  }
}
/***********************************************************/
_WINDOWS_DLL_EXPORT_
const LADSPA_Descriptor * 
     ladspa_descriptor(unsigned long Index) {
 #ifdef WIN32
 if (bIsFirstTime) {
  _init();
  bIsFirstTime = 0;
 }
    #endif
  if (Index == 0)
    return g_psDescriptor;
  else
    return NULL;
}
/***********************************************************/
/* EOF */


sound programming 目次