/* -*- mode: c++; c-file-style: "bsd"; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* $Id$ */ //////////////////////////////////////////////////////////////////////////////////////////////////// // Automatic Gain Control //////////////////////////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include "ladspa.h" // This module contains only one signal processing block, whose descriptor is g_descriptor0 static LADSPA_Descriptor* g_descriptor0 = 0; // Ports of the block, see below Instance_data struct #define PORT_I1 0 #define PORT_O1 1 #define PORTCOUNT 2 //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// // Data for ONE instance of the signal processing block, (datatype LADSPA_Data = float) typedef struct { unsigned long fs; // Sampling frecuency LADSPA_Data* port_i1; // Input LADSPA_Data* port_o1; // Output LADSPA_Data g; } Instance_data; //////////////////////////////////////////////////////////////////////////////////////////////////// // Dinamyc library (*.dll or *.so) initialization/finalization funcions void my_init(); void my_fini(); // Plug-in functions called by host static LADSPA_Handle my_instantiate (const LADSPA_Descriptor *des, unsigned long s_rate); static void my_cleanup (LADSPA_Handle hnd); void my_activate (LADSPA_Handle hnd); void my_deactivate (LADSPA_Handle hnd); static void my_connect (LADSPA_Handle hnd, unsigned long port, LADSPA_Data *data); static void my_run (LADSPA_Handle hnd, unsigned long sample_count); //////////////////////////////////////////////////////////////////////////////////////////////////// // Initialization/Finalization functions differ in UNIX and Windows #ifdef WIN32 #include BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch( ul_reason_for_call ) { case DLL_PROCESS_ATTACH: my_init(); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: my_fini(); break; } return TRUE; } #elif LINUX void __attribute__ ((constructor)) init() { my_init(); } void __attribute__ ((destructor)) fini() { my_fini(); } #endif //////////////////////////////////////////////////////////////////////////////////////////////////// // This funcion is executed when DLL is loaded into memory. Initializes LADSPA_Descriptor structure // this plug-in has only one signal processing block so It has only one LADSPA_Description structure void my_init() { char** port_name; LADSPA_PortDescriptor* port_prop; LADSPA_PortRangeHint* port_rang; g_descriptor0 = (LADSPA_Descriptor*) malloc(sizeof(LADSPA_Descriptor)); if (g_descriptor0) { // Simplify notation LADSPA_Descriptor* p = g_descriptor0; p->UniqueID = 1000; p->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; p->Label = "agc"; p->Name = "Automatic Gain Control"; p->Maker = "Javier Valcarce García "; p->Copyright = "GPL"; p->PortCount = PORTCOUNT; port_prop = (LADSPA_PortDescriptor*) calloc(PORTCOUNT, sizeof(LADSPA_PortDescriptor)); port_rang = (LADSPA_PortRangeHint*) calloc(PORTCOUNT, sizeof(LADSPA_PortRangeHint)); port_name = (char**) calloc(PORTCOUNT, sizeof(char*)); p->PortDescriptors = (const LADSPA_PortDescriptor *) port_prop; p->PortRangeHints = (const LADSPA_PortRangeHint *) port_rang; p->PortNames = (const char **) port_name; //PORT_I1 port_name[PORT_I1] = "Input"; port_prop[PORT_I1] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO; //PORT_O1 port_name[PORT_O1] = "Output"; port_prop[PORT_O1] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; // Pointers to functions called by host p->instantiate = my_instantiate; p->connect_port = my_connect; p->activate = my_activate; p->deactivate = my_deactivate; p->cleanup = my_cleanup; p->run = my_run; p->run_adding = 0; p->set_run_adding_gain = 0; } } //////////////////////////////////////////////////////////////////////////////////////////////////// // This function is executed when DLL is unloaded from memory void my_fini() { if (g_descriptor0) { free((char**) g_descriptor0->PortNames ); free((LADSPA_PortDescriptor*) g_descriptor0->PortDescriptors ); free((LADSPA_PortRangeHint*) g_descriptor0->PortRangeHints ); free(g_descriptor0); } } //////////////////////////////////////////////////////////////////////////////////////////////////// // The only Entry Point in this shared object EXPORT const LADSPA_Descriptor* ladspa_descriptor(unsigned long index) { switch (index) { case 0: return g_descriptor0; default: return NULL; } } //////////////////////////////////////////////////////////////////////////////////////////////////// // Allocate memory for one instance of the block, ie, creates a new instance static LADSPA_Handle my_instantiate(const LADSPA_Descriptor *des, unsigned long s_rate) { if (des != g_descriptor0) { // Error, there is only one block in this module return NULL; } Instance_data* ins = (Instance_data*) malloc(sizeof(Instance_data)); memset(ins, 0, sizeof(Instance_data)); // Sampling frecuency ins->fs = s_rate; return (LADSPA_Handle) ins; } //////////////////////////////////////////////////////////////////////////////////////////////////// // The opposite of instantiate, destroy instance static void my_cleanup(LADSPA_Handle hnd) { Instance_data* ins = (Instance_data*) hnd; free(ins); } //////////////////////////////////////////////////////////////////////////////////////////////////// // Initializes instance data. It must be called AFTER connect_ports() void my_activate(LADSPA_Handle hnd) { Instance_data* ins = (Instance_data*) hnd; ins->g = 1.0f; } //////////////////////////////////////////////////////////////////////////////////////////////////// // The opposite of activate() void my_deactivate(LADSPA_Handle hnd) { } //////////////////////////////////////////////////////////////////////////////////////////////////// // Connect block'ports to data buffers provided by host static void my_connect(LADSPA_Handle hnd, unsigned long port, LADSPA_Data *data) { Instance_data* ins = (Instance_data*) hnd; switch (port) { case PORT_I1: ins->port_i1 = data; break; case PORT_O1: ins->port_o1 = data; break; default: assert(0); } } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// // PROCESS blocks of sample_count samples. This is the KERNEL of the plug-in static void my_run(LADSPA_Handle hnd, unsigned long sample_count) { Instance_data* ins = (Instance_data*) hnd; LADSPA_Data* x = ins->port_i1; LADSPA_Data* y = ins->port_o1; unsigned long i; for (i = 0; i < sample_count; i++) { y[i] = x[i] * ins->g; ins->g = ins->g - 0.1 * (y[i]*y[i] - 0.002); } //printf("g = %f\n", ins->g); } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////