📄 af_ladspa.c
字号:
af_msg(AF_MSG_ERROR, MSGTR_AF_LADSPA_ErrControlBelow, setup->myname, i, hint.LowerBound); return AF_ERROR; } if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor) && val > hint.UpperBound) { af_msg(AF_MSG_ERROR, MSGTR_AF_LADSPA_ErrControlAbove, setup->myname, i, hint.UpperBound); return AF_ERROR; } } af_msg(AF_MSG_VERBOSE, "%s: all controls have sane values\n", setup->myname); /* All is well! */ setup->status = AF_OK; return AF_OK; } } return AF_UNKNOWN;}/* ------------------------------------------------------------------------- *//** \brief Uninitialise the LADSPA Plugin Loader filter. * * This function deactivates the plugin(s), cleans up, frees all allocated * memory and exits. * * \return No return value. */static void uninit(struct af_instance_s *af) { int i; if (af->data) free(af->data); if (af->setup) { af_ladspa_t *setup = (af_ladspa_t*) af->setup; const LADSPA_Descriptor *pdes = setup->plugin_descriptor; if (setup->myname) { af_msg(AF_MSG_VERBOSE, "%s: cleaning up\n", setup->myname); free(setup->myname); } if (setup->chhandles) { for(i=0; i<setup->nch; i++) { if ( (setup->ninputs == 2) && (i & 1) ) { /* stereo effect */ i++; continue; } if (pdes->deactivate) pdes->deactivate(setup->chhandles[i]); if (pdes->cleanup) pdes->cleanup(setup->chhandles[i]); } free(setup->chhandles); } if (setup->file) free(setup->file); if (setup->label) free(setup->label); if (setup->inputcontrolsmap) free(setup->inputcontrolsmap); if (setup->inputcontrols) free(setup->inputcontrols); if (setup->outputcontrolsmap) free(setup->outputcontrolsmap); if (setup->outputcontrols) free(setup->outputcontrols); if (setup->inputs) free(setup->inputs); if (setup->outputs) free(setup->outputs); if (setup->inbufs) { for(i=0; i<setup->nch; i++) { if (setup->inbufs[i]) free(setup->inbufs[i]); } free(setup->inbufs); } if (setup->outbufs) { for(i=0; i<setup->nch; i++) { if (setup->outbufs[i]) free(setup->outbufs[i]); } free(setup->outbufs); } if (setup->libhandle) dlclose(setup->libhandle); free(setup); setup = NULL; }}/* ------------------------------------------------------------------------- *//** \brief Process chunk of audio data through the selected LADSPA Plugin. * * \param af Pointer to audio filter instance * \param data Pointer to chunk of audio data * * \return Either AF_ERROR or AF_OK */static af_data_t* play(struct af_instance_s *af, af_data_t *data) { af_ladspa_t *setup = af->setup; const LADSPA_Descriptor *pdes = setup->plugin_descriptor; int16_t *audio = (int16_t*)data->audio; int nsamples = data->len/2; /* /2 because it's int16_t */ int nch = data->nch; int rate = data->rate; int i, p; float v; if (setup->status !=AF_OK) return data; /* See if it's the first call. If so, setup inbufs/outbufs, instantiate * plugin, connect ports and activate plugin */ /* 2004-12-07: Also check if the buffersize has to be changed! * data->len is not constant per se! re-init buffers. */ if ( (setup->bufsize != nsamples/nch) || (setup->nch != nch) ) { /* if setup->nch==0, it's the first call, if not, something has * changed and all previous mallocs have to be freed */ if (setup->nch != 0) { af_msg(AF_MSG_DEBUG1, "%s: bufsize change; free old buffer\n", setup->myname); if(setup->inbufs) { for(i=0; i<setup->nch; i++) { if(setup->inbufs[i]) free(setup->inbufs[i]); } free(setup->inbufs); } if(setup->outbufs) { for(i=0; i<setup->nch; i++) { if(setup->outbufs[i]) free(setup->outbufs[i]); } free(setup->outbufs); } } /* everything is freed */ setup->bufsize = nsamples/nch; setup->nch = nch; setup->inbufs = calloc(nch, sizeof(float*)); setup->outbufs = calloc(nch, sizeof(float*)); af_msg(AF_MSG_DEBUG1, "%s: bufsize = %d\n", setup->myname, setup->bufsize); for(i=0; i<nch; i++) { setup->inbufs[i] = calloc(setup->bufsize, sizeof(float)); setup->outbufs[i] = calloc(setup->bufsize, sizeof(float)); } /* only on the first call, there are no handles. */ if (!setup->chhandles) { setup->chhandles = calloc(nch, sizeof(LADSPA_Handle)); /* create handles * for stereo effects, create one handle for two channels */ for(i=0; i<nch; i++) { if ( (setup->ninputs == 2) && (i & 1) ) { /* stereo effect */ /* copy the handle from previous channel */ setup->chhandles[i] = setup->chhandles[i-1]; continue; } setup->chhandles[i] = pdes->instantiate(pdes, rate); } } /* connect input/output ports for each channel/filter instance * * always (re)connect ports */ for(i=0; i<nch; i++) { pdes->connect_port(setup->chhandles[i], setup->inputs[ (setup->ninputs==2) ? i&1 : 0 ], setup->inbufs[i]); pdes->connect_port(setup->chhandles[i], setup->outputs[ (setup->ninputs==2) ? i&1 : 0 ], setup->outbufs[i]); /* connect (input) controls */ for (p=0; p<setup->nports; p++) { LADSPA_PortDescriptor d = pdes->PortDescriptors[p]; if (LADSPA_IS_PORT_CONTROL(d)) { if (LADSPA_IS_PORT_INPUT(d)) { pdes->connect_port(setup->chhandles[i], p, &(setup->inputcontrols[p]) ); } else { pdes->connect_port(setup->chhandles[i], p, &(setup->outputcontrols[p]) ); } } } /* Activate filter (if it isn't already :) ) */ if ( (pdes->activate) && (setup->activated == 0) ) { pdes->activate(setup->chhandles[i]); setup->activated = 1; } } /* All channels/filters done! except for... */ /* Stereo effect with one channel left. Use same buffer for left * and right. connect it to the second port. */ if( (setup->ninputs == 2) && (i&1) && (i >= 1) ) { pdes->connect_port(setup->chhandles[i-1], setup->inputs[ (setup->ninputs==2) ? i&1 : 0 ], setup->inbufs[i-1]); pdes->connect_port(setup->chhandles[i-1], setup->outputs[ (setup->ninputs==2) ? i&1 : 0 ], setup->outbufs[i-1]); } /* done! */ } /* setup for first call/change of bufsize is done. * normal playing routine follows... */ /* Right now, I use a separate input and output buffer. * I could change this to in-place processing (inbuf==outbuf), but some * ladspa filters are broken and are not able to handle that. This seems * fast enough, so unless somebody complains, it stays this way :) */ /* Fill inbufs */ for (p=0; p<setup->bufsize; p++) { for (i=0; i<nch; i++) { setup->inbufs[i][p] = ( (float) audio[p*nch + i] ) / 32768.0f; } } /* Run filter(s) */ for (i=0; i<nch; i++) { pdes->run(setup->chhandles[i], setup->bufsize); if (setup->ninputs==2) // stereo effect just ran i++; } /* Extract outbufs, hard clipping in case the filter exceeded [-1.0,1.0] */ for (p=0; p<setup->bufsize; p++) { for (i=0; i<nch; i++) { v = setup->outbufs[i][p]; v *= 32768.0f; v = (v > 32767.0f ? 32767.0f : v); v = (v < -32768.0f ? -32768.0f : v); audio[p*nch + i] = (int16_t) v; } } /* done */ return data;}/* ------------------------------------------------------------------------- *//** \brief Open LADSPA Plugin Loader Filter * * \param af Audio Filter instance * * \return Either AF_ERROR or AF_OK */static int open(af_instance_t *af) { af->control=control; af->uninit=uninit; af->play=play; af->mul.n=1; af->mul.d=1; af->data = calloc(1, sizeof(af_data_t)); if (af->data == NULL) return af_ladspa_malloc_failed((char*)af_info_ladspa.name); af->setup = calloc(1, sizeof(af_ladspa_t)); if (af->setup == NULL) { free(af->data); af->data=NULL; return af_ladspa_malloc_failed((char*)af_info_ladspa.name); } ((af_ladspa_t*)af->setup)->status = AF_ERROR; /* will be set to AF_OK if * all went OK and play() * should proceed. */ ((af_ladspa_t*)af->setup)->myname = strdup(af_info_ladspa.name); if (!((af_ladspa_t*)af->setup)->myname) return af_ladspa_malloc_failed((char*)af_info_ladspa.name); return AF_OK;}/* ------------------------------------------------------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -