2013/01/19

C言語 LADSPA アンプ dB

LADSPAのプラグインの学習ということで音量調整だけのシンプルなアンプを作ってみた。サンプルを改造して作ったのだが、ゲインをコントロールする単位をdB(-12から+12dB)にしてみた。後はモノラル専用にしたぐらい。シンプルなソースにして、どういう流れで処理しているのかを追ってみた。ヘッダファイルのladspa.hも合わせて見ていく必要があるのだが、なかなか時間のかかる作業だわ。やっぱり100%自作の方が個人的には楽かもしれない。

アンプ プラグイン

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

compile Ubuntu
gcc -fPIC -DPIC -shared -nostartfiles -o namagi_amp.so namagi_amp.c
*/
/**********************************************************/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include "ladspa.h"
#define MIN_GAIN1 -12.0
#define MAX_GAIN1 12.0
#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 {
  LADSPA_Data *m_pfControlValue1;
  LADSPA_Data *m_pfInputBuffer1;
  LADSPA_Data *m_pfOutputBuffer1;
} Amplifier;
/**********************************************************/
LADSPA_Handle instantiateAmplifier(
         const LADSPA_Descriptor *Descriptor, 
         unsigned long  SampleRate){
               return malloc(sizeof(Amplifier));
}
/**********************************************************/
void connectPortToAmplifier(
               LADSPA_Handle Instance,
         unsigned long Port,
         LADSPA_Data *DataLocation) {
  Amplifier *psAmplifier;
  psAmplifier = (Amplifier *)Instance;

  switch (Port){
  case AMP_CONTROL1:
    psAmplifier -> m_pfControlValue1 = DataLocation;
    break;  
  case AMP_INPUT1:
    psAmplifier -> m_pfInputBuffer1 = DataLocation;
    break;
  case AMP_OUTPUT1:
    psAmplifier -> m_pfOutputBuffer1 = DataLocation;
    break;
  }
}
/**********************************************************/
void runAmplifier(LADSPA_Handle Instance,
              unsigned long SampleCount){
  LADSPA_Data fGain1;  
  LADSPA_Data *pfInput;
  LADSPA_Data *pfOutput;
  Amplifier *psAmplifier;
  unsigned long lSampleIndex;
  psAmplifier = (Amplifier *)Instance;
  fGain1 = *(psAmplifier -> m_pfControlValue1);
  pfInput = psAmplifier -> m_pfInputBuffer1;
  pfOutput = psAmplifier -> m_pfOutputBuffer1;

  for (lSampleIndex = 0; 
       lSampleIndex < SampleCount;
       lSampleIndex++){
     *(pfOutput++) =
       *(pfInput++) * pow(10,fGain1/20.0);
  }
}
/**********************************************************/
void cleanupAmplifier(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
      = 3;
    g_psDescriptor -> Label
      = strdup("amplifier");
    g_psDescriptor -> Properties
      = LADSPA_PROPERTY_HARD_RT_CAPABLE;
    g_psDescriptor -> Name 
      = strdup("Namagi: Amplifier ver.130119");
    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("Gain(dB)");
    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)MIN_GAIN1;
    psPortRangeHints[AMP_CONTROL1].UpperBound
                                     =(LADSPA_Data)MAX_GAIN1;
    psPortRangeHints[AMP_INPUT1].HintDescriptor      = 0;
    psPortRangeHints[AMP_OUTPUT1].HintDescriptor     = 0;

    g_psDescriptor -> instantiate  = instantiateAmplifier;
    g_psDescriptor -> connect_port  = connectPortToAmplifier;
    g_psDescriptor -> activate  = NULL;
    g_psDescriptor -> run   = runAmplifier;
    g_psDescriptor -> run_adding  = NULL;
    g_psDescriptor -> set_run_adding_gain  = NULL;
    g_psDescriptor -> deactivate  = NULL;
    g_psDescriptor -> cleanup  = cleanupAmplifier;
  }
}
/**********************************************************/
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;
}
/**********************************************************/
/* EOF */


コンパイルは以下のコマンドを使った。
gcc -shared -o namagi_amp.dll namagi_amp.c -ID


Audacityで実行すると以下のウィンドウが表示される。ゲインをdBで調整することができる。

sound programming 目次
C言語 ANSI C89 Meadow & MinGW GCC 目次