2017/08/15

LADSPA 設定ファイル読込みテスト

LADSPAで設定ファイルが読めるかどうかテストしてみた。 結構あっけなく完成。プラグインと同じディレクトリ内に設定ファイルを入れておけば、Applyを押したときに読み込まれて、その設定ファイルに書かれた内容で適用されるというもの。今回のテスト用では設定値はゲインの調整値とした。 また下のようにインターフェイスにスライダーはあるが、完全にダミーで何も機能しない。何かスライダーがないと、メニュー選択と同時に適用されてしまうので、ダミーを付けておいただけ。

内容としてはrun関数で、特定名称のファイルを開き、内容を文字列として取り込み、floatに変換し、パラメーターとして扱った。

プラグインを起動させたまま、設定ファイルの書換えができるので、多くのパラメーターで試行錯誤する開発では便利。リバーブとか、FIRとか、膨大な係数を必要とする場合などね。

設定ファイルリーダー

/* namagi_amp.c
2017.8.15
compile windows
gcc -shared -o namagi_reader.dll namagi_reader.c -ID

compile Ubuntu
gcc -fPIC -DPIC -shared -nostartfiles -o namagi_reader.so namagi_reader.c
*/
/**********************************************************/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include "ladspa.h"
#define AMP_CONTROL1 0
#define AMP_INPUT1   1
#define AMP_OUTPUT1  2
/**********************************************************/
#ifdef WIN32
 int bIsFirstTime = 1;
 void _init();
#endif

#ifdef WIN32
 #define _WINDOWS_DLL_EXPORT_ __declspec(dllexport)
#else
 #define _WINDOWS_DLL_EXPORT_ 
#endif
/**********************************************************/
typedef struct {
 float m_pfControlValue1;
 LADSPA_Data *m_pfInputBuffer1;
 LADSPA_Data *m_pfOutputBuffer1;
} Reader;
/**********************************************************/
LADSPA_Handle instantiateReader(const LADSPA_Descriptor *Descriptor,
                               unsigned long  SampleRate){
               return malloc(sizeof(Reader));
}
/**********************************************************/
void connectPortToReader( LADSPA_Handle Instance,
  unsigned long Port, LADSPA_Data *DataLocation) {
  Reader *psReader;
  psReader = (Reader *)Instance;
  switch (Port){
  case AMP_INPUT1:
    psReader -> m_pfInputBuffer1 = DataLocation;
    break;
  case AMP_OUTPUT1:
    psReader -> m_pfOutputBuffer1 = DataLocation;
    break;
  }
}
/**********************************************************/
void runReader(LADSPA_Handle Instance,
              unsigned long SampleCount){
  LADSPA_Data fGain1;  
  LADSPA_Data *pfInput;
  LADSPA_Data *pfOutput;
  Reader *psReader;
  unsigned long lSampleIndex;
  psReader = (Reader *)Instance;
  fGain1 = psReader -> m_pfControlValue1;
  pfInput = psReader -> m_pfInputBuffer1;
  pfOutput = psReader -> m_pfOutputBuffer1;
               
 FILE *fp;
 char str[128];//
 fp = fopen("reader.ini", "r");
 if (fp != NULL) {
  fgets(str, 128, fp);
  fGain1=  atof(str);
 } 
 fclose(fp);

  for (lSampleIndex = 0; 
       lSampleIndex < SampleCount;
       lSampleIndex++){
     *(pfOutput++) = *(pfInput++) * fGain1;
  }
     printf("%f",fGain1);
}
/**********************************************************/
void cleanupReader(LADSPA_Handle Instance) {
  free(Instance);
}
/**********************************************************/
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
      = 170815;
    g_psDescriptor -> Label
      = strdup("reader");
    g_psDescriptor -> Properties
      = LADSPA_PROPERTY_HARD_RT_CAPABLE;
    g_psDescriptor -> Name 
      = strdup("Namagi: Reader ver.170815");
    g_psDescriptor -> Maker
      = strdup("Namagi Products");
    g_psDescriptor -> Copyright
      = strdup("None");
    g_psDescriptor -> PortCount = 3;
    piPortDescriptors = (LADSPA_PortDescriptor *)calloc(3,
  sizeof(LADSPA_PortDescriptor));
    g_psDescriptor -> PortDescriptors
      = (const LADSPA_PortDescriptor *)piPortDescriptors;

    piPortDescriptors[AMP_CONTROL1]
     = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[AMP_INPUT1]
     = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
    piPortDescriptors[AMP_OUTPUT1]
     = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;

    pcPortNames  = (char **)calloc(3, sizeof(char *));
    g_psDescriptor -> PortNames  = (const char **)pcPortNames;

 pcPortNames[AMP_CONTROL1] = strdup("Dummy");
    pcPortNames[AMP_INPUT1] = strdup("Input");
    pcPortNames[AMP_OUTPUT1] = strdup("Output");

    psPortRangeHints = ((LADSPA_PortRangeHint *)
   calloc(3, sizeof(LADSPA_PortRangeHint)));

    g_psDescriptor -> PortRangeHints
      = (const LADSPA_PortRangeHint *)psPortRangeHints;

    psPortRangeHints[AMP_CONTROL1].HintDescriptor
      = (LADSPA_HINT_BOUNDED_BELOW |
      LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0);
    psPortRangeHints[AMP_CONTROL1].LowerBound =(LADSPA_Data)-1;
    psPortRangeHints[AMP_CONTROL1].UpperBound =(LADSPA_Data)1;

    psPortRangeHints[AMP_INPUT1].HintDescriptor = 0;
    psPortRangeHints[AMP_OUTPUT1].HintDescriptor = 0;

    g_psDescriptor -> instantiate  = instantiateReader;
    g_psDescriptor -> connect_port  = connectPortToReader;
    g_psDescriptor -> activate  = NULL;
    g_psDescriptor -> run   = runReader;
    g_psDescriptor -> run_adding  = NULL;
    g_psDescriptor -> set_run_adding_gain  = NULL;
    g_psDescriptor -> deactivate  = NULL;
    g_psDescriptor -> cleanup  = cleanupReader;
  }
}
/**********************************************************/
void deleteDescriptor(LADSPA_Descriptor * psDescriptor){
  unsigned long lIndex;
  if (psDescriptor){
    free((char *)psDescriptor -> Label);
    free((char *)psDescriptor -> Name);
    free((char *)psDescriptor -> Maker);
    free((char *)psDescriptor -> Copyright);
    free((LADSPA_PortDescriptor *)psDescriptor -> PortDescriptors);

    for (lIndex=0; lIndex < psDescriptor -> PortCount; lIndex++){
      free((char *)(psDescriptor -> PortNames[lIndex]));
    }

    free((char **)psDescriptor -> PortNames);
    free((LADSPA_PortRangeHint *)psDescriptor -> PortRangeHints);
    free(psDescriptor);
  }
}
/**********************************************************/
void _fini(){
  deleteDescriptor(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;
}


今回の設定ファイルは1行だけ数字を入れてたもの。Audacity\Plug-Ins 内に入れておけば読み込める。

設定ファイル reader.ini

0.5

LADSPA Delay Multi-Tap

リバーブの初期反射の予備実験としてマルチタップディレイをプログラミングしてみた。マルチタップディレイは、ディレイラインに対して、任意の位置に複数のタップを作り、信号を取り出し、合成するという仕組み。ブロック図にすると以下のような構造になっている。

リバーブにおける初期反射は、その空間の印象を左右する重要な部分。複雑な反射をシミュレートする必要があるため、通常のFB付のディレイでは初期反射をうまく表現できない。そこでマルチタップの出番となる。

サクサクっと作ってみた。以前作ったディレイの改造なので30分程度で完成。今回は実験なので6タップ、モノラル、FBなしとした。これ以上のタップ数だとパラメーターから1個1個入力するのは現実的ではない。設定ファイルを別に設けた方がよさそうだ。

下がデルタ関数への適用例。設定次第でいろいろな特性を作り出せる。このマルチタップは、プログラムを作ることは簡単だが、使える設定を見つけ出すことは容易ではない。実際の初期反射のデータを分析したり、試行錯誤が必要。また実用とするなら、タップ数は数十は欲しいと思う。しかも左右のチャンネルで欲しいので、その2倍となる。設定項目は100以上となり、狙い通りの音を見つけるのに苦労しそうだ。むやみにやるよりも、理論的に導き出す方がよいと思われる。何か方法論を思いついたら、実用マルチタップにチャレンジしてみようかと思う。


実際に適用した例が以下のサンプル。 まずは何もしていないドライな音。

次にマルチタップを適用した音。6タップでFBもないが、初期反射ぽさは感じられる。LPFや後部残響を組み合わせれば十分使えそうだ。


LADSPA Delay Multi-Tap

/* Namagi delay.c 
2017.08.15
windows compile
gcc -shared -o namagi_delay_multitap.dll namagi_delay_multitap.c -ID

compile Ubuntu
gcc -fPIC -DPIC -shared -nostartfiles 
-o namagi_delay_multitap.so namagi_delay_multitap.c
*/
/***********************************************************/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "ladspa.h"
/***********************************************************/
#define INPUT       0
#define OUTPUT      1
#define DELAY_TIME1  2
#define WET1         3
#define DELAY_TIME2  4
#define WET2         5
#define DELAY_TIME3  6
#define WET3         7
#define DELAY_TIME4  8
#define WET4         9
#define DELAY_TIME5  10
#define WET5         11
#define DELAY_TIME6  12
#define WET6         13
#define DRYCHECK     14
#define DRY          15
/***********************************************************/
/* Win用設定 */
#ifdef WIN32
    int bIsFirstTime = 1;
    void _init();
    #define _WINDOWS_DLL_EXPORT_ __declspec(dllexport)
#else
    #define _WINDOWS_DLL_EXPORT_ 
#endif
/***********************************************************/
typedef struct {
    unsigned long m_lSampleRate;
    unsigned long m_lBufferSize;
    unsigned long m_lWritePointer;
    float *m_pfBuffer;
    float *m_pfDelay1;
    float *m_pfWet1;
    float *m_pfDelay2;
    float *m_pfWet2;
    float *m_pfDelay3;
    float *m_pfWet3;
 float *m_pfDelay4;
    float *m_pfWet4;
 float *m_pfDelay5;
    float *m_pfWet5;
 float *m_pfDelay6;
    float *m_pfWet6;
    float *m_pfDryCheckBox;
    float *m_pfDry;
    float *m_pfInput;
    float *m_pfOutput;
} Delay;
/***********************************************************/
LADSPA_Handle 
instantiateDelay(const LADSPA_Descriptor *Descriptor,
    unsigned long SampleRate){
    
    Delay *psDelay;
    psDelay = (Delay *)malloc(sizeof(Delay));
    if (psDelay == NULL) return NULL;
    
    psDelay -> m_lSampleRate = SampleRate;
    psDelay -> m_lBufferSize = 1;
    while (psDelay -> m_lBufferSize < SampleRate){
        psDelay -> m_lBufferSize <<= 1;
    }
    psDelay -> m_pfBuffer = (float *)calloc(psDelay -> m_lBufferSize, sizeof(float));
    if (psDelay -> m_pfBuffer == NULL) {
        free(psDelay);
        return NULL;
    }
    psDelay -> m_lWritePointer = 0;
    return psDelay;
}
/***********************************************************/
void activateDelay(LADSPA_Handle Instance){
    Delay *psDelay;
    psDelay = (Delay *)Instance;
    memset(psDelay -> m_pfBuffer, 0, sizeof(float) *psDelay -> m_lBufferSize);
}
/***********************************************************/
void connectPortToDelay(LADSPA_Handle Instance,unsigned long Port,float *DataLocation){
    Delay * psDelay;
    psDelay = (Delay *)Instance;
  
    switch (Port) {
        case DELAY_TIME1:
            psDelay -> m_pfDelay1 = DataLocation;
            break;
        case WET1:
            psDelay -> m_pfWet1 = DataLocation;
            break;
        case DELAY_TIME2:
            psDelay -> m_pfDelay2 = DataLocation;
            break;
        case WET2:
            psDelay -> m_pfWet2 = DataLocation;
            break;
     case DELAY_TIME3:
            psDelay -> m_pfDelay3 = DataLocation;
            break;
        case WET3:
            psDelay -> m_pfWet3 = DataLocation;
            break;
     case DELAY_TIME4:
            psDelay -> m_pfDelay4 = DataLocation;
            break;
        case WET4:
            psDelay -> m_pfWet4 = DataLocation;
            break;
     case DELAY_TIME5:
            psDelay -> m_pfDelay5 = DataLocation;
            break;
        case WET5:
            psDelay -> m_pfWet5 = DataLocation;
            break;
     case DELAY_TIME6:
            psDelay -> m_pfDelay6 = DataLocation;
            break;
        case WET6:
            psDelay -> m_pfWet6 = DataLocation;
            break;
        case DRYCHECK:
            psDelay -> m_pfDryCheckBox = DataLocation;
            break;
        case DRY:
            psDelay -> m_pfDry = DataLocation;
            break;
        case INPUT:
            psDelay -> m_pfInput = DataLocation;
            break;
        case OUTPUT:
            psDelay -> m_pfOutput = DataLocation;
            break;
    }
}
/***********************************************************/
void runDelay(LADSPA_Handle Instance,unsigned long SampleCount){

    Delay *psDelay;
    psDelay = (Delay*) Instance;
    
    float *pfInput = psDelay -> m_pfInput;
    float *pfOutput = psDelay -> m_pfOutput;
    float *pfBuffer = psDelay -> m_pfBuffer;
    
    float fInputSample;
    float fWet1 = *(psDelay -> m_pfWet1);
    float fWet2 = *(psDelay -> m_pfWet2);
 float fWet3 = *(psDelay -> m_pfWet3);
 float fWet4 = *(psDelay -> m_pfWet4);
 float fWet5 = *(psDelay -> m_pfWet5);
 float fWet6 = *(psDelay -> m_pfWet6);
    float fDryCheckBox = *(psDelay -> m_pfDryCheckBox);
    float fDry = *(psDelay -> m_pfDry);
    unsigned long lBufferSizeMinusOne = psDelay -> m_lBufferSize - 1;
    unsigned long lDelay1 = *(psDelay -> m_pfDelay1) * psDelay -> m_lSampleRate / 1000;
    unsigned long lDelay2 = *(psDelay -> m_pfDelay2) * psDelay -> m_lSampleRate / 1000;
 unsigned long lDelay3 = *(psDelay -> m_pfDelay3) * psDelay -> m_lSampleRate / 1000;
 unsigned long lDelay4 = *(psDelay -> m_pfDelay4) * psDelay -> m_lSampleRate / 1000;
 unsigned long lDelay5 = *(psDelay -> m_pfDelay5) * psDelay -> m_lSampleRate / 1000;
 unsigned long lDelay6 = *(psDelay -> m_pfDelay6) * psDelay -> m_lSampleRate / 1000;
    unsigned long lBufferWriteOffset = psDelay -> m_lWritePointer;
    unsigned long lBufferReadOffset1 = lBufferWriteOffset + psDelay -> m_lBufferSize - lDelay1;
 unsigned long lBufferReadOffset2 = lBufferWriteOffset + psDelay -> m_lBufferSize - lDelay2;
 unsigned long lBufferReadOffset3 = lBufferWriteOffset + psDelay -> m_lBufferSize - lDelay3;
 unsigned long lBufferReadOffset4 = lBufferWriteOffset + psDelay -> m_lBufferSize - lDelay4;
 unsigned long lBufferReadOffset5 = lBufferWriteOffset + psDelay -> m_lBufferSize - lDelay5;
 unsigned long lBufferReadOffset6 = lBufferWriteOffset + psDelay -> m_lBufferSize - lDelay6;
    unsigned long i;

    for (i=0; i < SampleCount; i++){
        fInputSample = *(pfInput++);
        if(fDryCheckBox == 1){
            *(pfOutput++) = pow(10,fDry/20.0) * fInputSample
            + pow(10,fWet1/20.0) * pfBuffer[(i + lBufferReadOffset1) & lBufferSizeMinusOne]
            + pow(10,fWet2/20.0) * pfBuffer[(i + lBufferReadOffset2) & lBufferSizeMinusOne]
            + pow(10,fWet3/20.0) * pfBuffer[(i + lBufferReadOffset3) & lBufferSizeMinusOne]
            + pow(10,fWet4/20.0) * pfBuffer[(i + lBufferReadOffset4) & lBufferSizeMinusOne]
            + pow(10,fWet5/20.0) * pfBuffer[(i + lBufferReadOffset5) & lBufferSizeMinusOne]
            + pow(10,fWet6/20.0) * pfBuffer[(i + lBufferReadOffset6) & lBufferSizeMinusOne];
        }else{
            *(pfOutput++) = 
            pow(10,fWet1/20.0) * pfBuffer[(i + lBufferReadOffset1) & lBufferSizeMinusOne]
            + pow(10,fWet2/20.0) * pfBuffer[(i + lBufferReadOffset2) & lBufferSizeMinusOne]
            + pow(10,fWet3/20.0) * pfBuffer[(i + lBufferReadOffset3) & lBufferSizeMinusOne]
            + pow(10,fWet4/20.0) * pfBuffer[(i + lBufferReadOffset4) & lBufferSizeMinusOne]
            + pow(10,fWet5/20.0) * pfBuffer[(i + lBufferReadOffset5) & lBufferSizeMinusOne]
            + pow(10,fWet6/20.0) * pfBuffer[(i + lBufferReadOffset6) & lBufferSizeMinusOne];
        }
        pfBuffer[(i + lBufferWriteOffset) & lBufferSizeMinusOne] 
        = fInputSample;
    }
    psDelay -> m_lWritePointer =
    ((psDelay -> m_lWritePointer + SampleCount) &lBufferSizeMinusOne);
}
/***********************************************************/
void cleanupDelay(LADSPA_Handle Instance){
    Delay * psDelay;
    psDelay = (Delay *)Instance;
    free(psDelay);
}
/***********************************************************/
LADSPA_Descriptor *g_psDescriptor = NULL;
/***********************************************************/
void _init() {
    char ** pcPortNames;
    LADSPA_PortDescriptor * piPortDescriptors;
    LADSPA_PortRangeHint * psPortRangeHints;
    int ports = 16;
    
    g_psDescriptor = (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor));

    if (g_psDescriptor) {
    g_psDescriptor->UniqueID = 0;
    g_psDescriptor->Label = strdup("Delay Multi-Tap");
    g_psDescriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
    g_psDescriptor->Name = strdup("Namagi: Delay Multi-Tap ver.170815");
    g_psDescriptor->Maker = strdup("Namagi Products");
    g_psDescriptor->Copyright = strdup("None");
    g_psDescriptor->PortCount = ports;
    
    /* メモリ*/
    piPortDescriptors =
    (LADSPA_PortDescriptor *)calloc(ports,sizeof(LADSPA_PortDescriptor));
    g_psDescriptor -> PortDescriptors =
    (const LADSPA_PortDescriptor *)piPortDescriptors;
       
    /* ポート */
    piPortDescriptors[DELAY_TIME1] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[WET1] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[DELAY_TIME2] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[WET2] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[DELAY_TIME3] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[WET3] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[DELAY_TIME4] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[WET4] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[DELAY_TIME5] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[WET5] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[DELAY_TIME6] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[WET6] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[DRYCHECK] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[DRY] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
    piPortDescriptors[INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
    piPortDescriptors[OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;

    pcPortNames = (char **)calloc(ports, sizeof(char *));
    g_psDescriptor->PortNames = (const char **)pcPortNames;

    pcPortNames[DELAY_TIME1] = strdup("delay1 (msec)");
    pcPortNames[WET1] = strdup("wet1 (dB)");
    pcPortNames[DELAY_TIME2] = strdup("delay2 (msec)");
    pcPortNames[WET2] = strdup("wet2 (dB)");
    pcPortNames[DELAY_TIME3] = strdup("delay3 (msec)");
    pcPortNames[WET3] = strdup("wet3 (dB)");
    pcPortNames[DELAY_TIME4] = strdup("delay4 (msec)");
    pcPortNames[WET4] = strdup("wet4 (dB)");
    pcPortNames[DELAY_TIME5] = strdup("delay5 (msec)");
    pcPortNames[WET5] = strdup("wet5 (dB)");
    pcPortNames[DELAY_TIME6] = strdup("delay6 (msec)");
    pcPortNames[WET6] = strdup("wet6 (dB)");
    pcPortNames[DRYCHECK] = strdup("dry on/off");
    pcPortNames[DRY] = strdup("dry (dB)");
    pcPortNames[INPUT] = strdup("input");
    pcPortNames[OUTPUT] = strdup("output");
    
    /*  */
    psPortRangeHints =
    ((LADSPA_PortRangeHint *)calloc(ports, sizeof(LADSPA_PortRangeHint)));
    g_psDescriptor -> PortRangeHints =
    (const LADSPA_PortRangeHint *)psPortRangeHints;

    /* 1 */
    psPortRangeHints[DELAY_TIME1].HintDescriptor = (LADSPA_HINT_BOUNDED_BELOW | 
      LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW);
    psPortRangeHints[DELAY_TIME1].LowerBound = 0;
    psPortRangeHints[DELAY_TIME1].UpperBound = 1000.0; 
    psPortRangeHints[WET1].HintDescriptor = (LADSPA_HINT_BOUNDED_BELOW 
      | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0);
    psPortRangeHints[WET1].LowerBound = -120;
    psPortRangeHints[WET1].UpperBound = 0;
    
 /* 2 */
    psPortRangeHints[DELAY_TIME2].HintDescriptor = (LADSPA_HINT_BOUNDED_BELOW | 
      LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW);
    psPortRangeHints[DELAY_TIME2].LowerBound = 0;
    psPortRangeHints[DELAY_TIME2].UpperBound = 1000.0; 
    psPortRangeHints[WET2].HintDescriptor = (LADSPA_HINT_BOUNDED_BELOW 
      | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0);
    psPortRangeHints[WET2].LowerBound = -120;
    psPortRangeHints[WET2].UpperBound = 0;
    
 /* 3 */
    psPortRangeHints[DELAY_TIME3].HintDescriptor = (LADSPA_HINT_BOUNDED_BELOW | 
      LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW);
    psPortRangeHints[DELAY_TIME3].LowerBound = 0;
    psPortRangeHints[DELAY_TIME3].UpperBound = 1000.0; 
    psPortRangeHints[WET3].HintDescriptor = (LADSPA_HINT_BOUNDED_BELOW 
      | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0);
    psPortRangeHints[WET3].LowerBound = -120;
    psPortRangeHints[WET3].UpperBound = 0;

 /* 4 */
    psPortRangeHints[DELAY_TIME4].HintDescriptor = (LADSPA_HINT_BOUNDED_BELOW | 
      LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW);
    psPortRangeHints[DELAY_TIME4].LowerBound = 0;
    psPortRangeHints[DELAY_TIME4].UpperBound = 1000.0; 
    psPortRangeHints[WET4].HintDescriptor = (LADSPA_HINT_BOUNDED_BELOW 
      | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0);
    psPortRangeHints[WET4].LowerBound = -120;
    psPortRangeHints[WET4].UpperBound = 0;

 /* 5 */
    psPortRangeHints[DELAY_TIME5].HintDescriptor = (LADSPA_HINT_BOUNDED_BELOW | 
      LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW);
    psPortRangeHints[DELAY_TIME5].LowerBound = 0;
    psPortRangeHints[DELAY_TIME5].UpperBound = 1000.0; 
    psPortRangeHints[WET5].HintDescriptor = (LADSPA_HINT_BOUNDED_BELOW 
      | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0);
 psPortRangeHints[WET5].LowerBound = -120;
    psPortRangeHints[WET5].UpperBound = 0;
     
    /* 6 */
    psPortRangeHints[DELAY_TIME6].HintDescriptor = (LADSPA_HINT_BOUNDED_BELOW | 
      LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW);
    psPortRangeHints[DELAY_TIME6].LowerBound = 0;
    psPortRangeHints[DELAY_TIME6].UpperBound = 1000.0; 
    psPortRangeHints[WET6].HintDescriptor = (LADSPA_HINT_BOUNDED_BELOW 
      | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0);
    psPortRangeHints[WET6].LowerBound = -120;
    psPortRangeHints[WET6].UpperBound = 0;
    
    psPortRangeHints[DRYCHECK].HintDescriptor = 
      (LADSPA_HINT_TOGGLED | LADSPA_HINT_DEFAULT_0);

    psPortRangeHints[DRY].HintDescriptor = (LADSPA_HINT_BOUNDED_BELOW 
      | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0);
    psPortRangeHints[DRY].LowerBound = -120;
    psPortRangeHints[DRY].UpperBound = 0;

    psPortRangeHints[INPUT].HintDescriptor = 0;
    psPortRangeHints[OUTPUT].HintDescriptor = 0;

    g_psDescriptor -> instantiate = instantiateDelay;
    g_psDescriptor -> connect_port =  connectPortToDelay;
    g_psDescriptor -> activate = activateDelay;
    g_psDescriptor -> run = runDelay;
    g_psDescriptor -> run_adding = NULL;
    g_psDescriptor -> set_run_adding_gain = NULL;
    g_psDescriptor -> deactivate = NULL;
    g_psDescriptor -> cleanup = cleanupDelay;
    }
}
/***********************************************************/
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;
}


sound programming 目次はこちら

2017/08/14

ベース + キーボード練習 2017年 3回目

古い電子ピアノも直したので、それを使って録音でもしようと思うが、早くも1ヶ月経ってしまった。 さらに前回の練習からすでに2ヶ月近い。

気を取り直して・・・
今回は、ひたすらベースパターンを繰り返すようなフレーズをやってみたくなったので、YMOの東風の中間部だけ、ちょい音を変えて弾いてみた。フワッフワッというところを省く。 ピアノは改造したYAMAHA CLP-100、音色ピアノ1を使用。録音後に自作エフェクタで加工してみた。ちょっと細工するだけで十分使える音に思えたよ。 ドラムは、いつものHydrogenを使用。すぐにパターンが作れるのでお気に入り。そのドラムパターンをwavに落としたら、Audacityで多重録音していくだけ。

下が録音したものだが、結局練習せず、1回弾いて録音しただけで終わってしまった。ベースパターンは以前耳コピしたときに練習も兼ねていたので、まぁささっと弾けたわけだ。ピアノは白玉x2で、しかもシンプルなコードにしたので、こちらも練習は必要なかった。
結局、目的である練習をしていないので、反省すべきだ。実績として録音しているのだが、1回だけ弾いて終わっていては上達の見込みはない・・・



このベースパターンは、実は弾くのが結構大変で、左手小指を酷使する。ローポジションでひたすら押さえ続けるので、数分も連続で弾いていると、結構手が辛いのだ。以前から同じ箇所で弾き続けるのは辛いと感じていたので、これからはローポジションで耐え続ける練習に力を入れてみるかな。