Merge pull request #283 from FluidSynth/ladspa

Polishing of LADSPA subsystem
This commit is contained in:
Tom M 2017-11-25 11:45:49 +01:00 committed by GitHub
commit a7fe5c4257
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 1620 additions and 1113 deletions

View file

@ -52,7 +52,6 @@ set ( LIB_VERSION_INFO
# Options disabled by default
option ( enable-floats "enable type float instead of double for DSP samples" off )
option ( enable-profiling "profile the dsp code" off )
option ( enable-ladspa "enable LADSPA effect units" off )
option ( enable-portaudio "compile PortAudio support" off )
option ( enable-trap-on-fpe "enable SIGFPE trap on Floating Point Exceptions" off )
option ( enable-fpe-check "enable Floating Point Exception checks and debug messages" off )
@ -68,6 +67,7 @@ option ( enable-midishare "compile MidiShare support (if it is available)" on )
option ( enable-readline "compile readline lib line editing (if it is available)" on )
option ( enable-dbus "compile DBUS support (if it is available)" on )
option ( BUILD_SHARED_LIBS "Build a shared object or DLL" on )
option ( enable-ladspa "enable LADSPA effect units" on )
option ( enable-ipv6 "enable ipv6 support " on )
# Platform specific options
@ -260,19 +260,6 @@ if ( enable-profiling )
set ( WITH_PROFILING 1 )
endif ( enable-profiling )
unset ( HAVE_LIBDL CACHE )
unset ( LADSPA_SUPPORT CACHE )
if ( enable-ladspa )
check_include_file ( ladspa.h LADSPA_SUPPORT )
if ( LADSPA_SUPPORT )
set ( LADSPA 1 )
if ( CMAKE_DL_LIBS )
set ( HAVE_LIBDL 1 )
set ( LIBFLUID_LIBS "${LIBFLUID_LIBS};${CMAKE_DL_LIBS}" )
endif ( CMAKE_DL_LIBS )
endif ( LADSPA_SUPPORT )
endif ( enable-ladspa )
unset ( ENABLE_TRAPONFPE CACHE )
unset ( TRAP_ON_FPE CACHE )
if ( enable-trap-on-fpe AND NOT APPLE AND NOT WIN32 )
@ -307,10 +294,10 @@ endif ( CMAKE_BUILD_TYPE MATCHES "Debug" )
if(NOT enable-pkgconfig)
FIND_LIBRARY( GLIB_LIB NAMES glib glib-2.0 PATH GLIB_LIBRARY_DIR NO_DEFAULT_PATH)
FIND_LIBRARY( GTHREAD_LIB NAMES gthread gthread-2.0 PATH GTHREAD_LIBRARY_DIR NO_DEFAULT_PATH )
FIND_PATH( GLIBH_DIR glib.h PATH GLIB_INCLUDE_DIR NO_DEFAULT_PATH )
FIND_PATH( GLIBCONF_DIR glibconfig.h PATH GLIBCONF_INCLUDE_DIR NO_DEFAULT_PATH )
FIND_LIBRARY( GLIB_LIB NAMES glib glib-2.0 PATH GLIB_LIBRARY_DIR )
FIND_LIBRARY( GTHREAD_LIB NAMES gthread gthread-2.0 PATH GTHREAD_LIBRARY_DIR )
FIND_PATH( GLIBH_DIR glib.h PATH GLIB_INCLUDE_DIR )
FIND_PATH( GLIBCONF_DIR glibconfig.h PATH GLIBCONF_INCLUDE_DIR )
IF( GLIB_LIB MATCHES "GLIB_LIB-NOTFOUND" OR
GTHREAD_LIB MATCHES "GTHREAD_LIB-NOTFOUND" OR
@ -400,6 +387,15 @@ else(NOT enable-pkgconfig)
else ( enable-dbus )
unset_pkg_config ( DBUS )
endif ( enable-dbus )
unset ( LADSPA_SUPPORT CACHE )
if ( enable-ladspa )
check_include_file ( ladspa.h LADSPA_SUPPORT )
if ( LADSPA_SUPPORT )
pkg_check_modules ( GMODULE REQUIRED gmodule-2.0>=2.6.5 )
set ( LADSPA 1 )
endif ( LADSPA_SUPPORT )
endif ( enable-ladspa )
endif(NOT enable-pkgconfig)

Binary file not shown.

View file

@ -1,18 +1,18 @@
# FluidSynth LADSPA Interface
The [LADSPA](http://ladspa.org/) (Linux Audio Developer's Simple Plugin API)
binding can be used to route the FluidSynth audio output through any number
of LADSPA plugins. As the name implies, it is only available on Linux.
binding can be used to route the FluidSynth audio output through any number of
LADSPA plugins. Please note that even though the "L" in LADSPA stands for
"Linux", it can also be used on different platforms, for example Windows or
MacOS. Check the "LADSPA on other Platforms" section at the end of this guide
for more information.
## Configuration
To configure and compile FluidSynth with LADSPA support, make sure you have
the LADSPA SDK (basically the ladspa.h header file) installed. Then enable
LADSPA when calling cmake:
cmake -Denable-ladspa=1 <path-to-source>
You should see `LADSPA support: yes` in the cmake output.
To configure and compile FluidSynth with LADSPA support, make sure you have the
LADSPA SDK installed (or at least the ladspa.h header file available in an
include path). Then compile FluidSynth in the usual way. You should see
`LADSPA support: yes` in the cmake output.
To enable the LADSPA engine, use the `synth.ladspa.active` setting when
starting FluidSynth:
@ -20,45 +20,464 @@ starting FluidSynth:
fluidsynth -o synth.ladspa.active=1 ...
# Quickstart Tutorial
The following walks you through the process of adding a LADSPA plugin into your
FluidSynth configuration. It assumes that you are running FluidSynth on Linux,
that you have some experience with running Linux shell commands and that you
know how to start FluidSynth from the command line and use it to play a MIDI
file.
## Introduction to LADSPA
You don't need to to have detailed knowledge of LADSPA to use effects with
FluidSynth, but knowing some of it's concepts will help if you want to make the
best use of it.
If you have the LADSPA SDK installed you should be able to use the `listplugins`
Linux command to list all plugins installed in your LADSPA path. And to show
more details about a particular plugin library, you can use the `analyseplugin`
Linux command. Here is an example showing the details of the `delay.so` plugin
from the LADSPA SDK:
```
user@host:$ analyseplugin /usr/lib/ladspa/delay.so
Plugin Name: "Simple Delay Line"
Plugin Label: "delay_5s"
Plugin Unique ID: 1043
Maker: "Richard Furse (LADSPA example plugins)"
Copyright: "None"
Must Run Real-Time: No
Has activate() Function: Yes
Has deactivate() Function: No
Has run_adding() Function: No
Environment: Normal or Hard Real-Time
Ports: "Delay (Seconds)" input, control, 0 to 5, default 1
"Dry/Wet Balance" input, control, 0 to 1, default 0.5
"Input" input, audio
"Output" output, audio
```
This output tells you that the `delay.so` library contains only a single plugin
called "Simple Delay Line". Most importantly it lists the input and output
ports, which can be used to set plugin parameters and connect the audio input
and output to FluidSynth.
"Delay (Seconds)" and "Dry/Wet Balance" are input controls. They are the
parameters that a user can set to affect the way the plugin works. They control
how long the delay should be and how the dry and wet signals should be mixed
before writing them to the output.
"Input" and "Output" are audio ports which carry samples into the plugin and out
again after it has run. Mono plugins usually provide one set of input and output
audio ports, stereo plugins usually provide two sets. But there are even plugins
that only have a single output port and no input at all (think of noise
generators...)
Also note the line `Has run_adding() Function: No`. This specifies that this
plugin can not mix it's audio output into an output buffer, but will always
replace anything that is already there. This will become important again later
on.
## FluidSynth Host Ports
Just as LADSPA plugins have input and output ports, FluidSynth provides it's
own audio ports that can be connected to plugins. On a standard stereo setup,
the following four ports are automatically created:
- Main:L
- Main:R
- Reverb:Send
- Chorus:Send
The "Main:L" and "Main:R" ports can be connected to effect input and output
ports. They carry the main audio signals into the LADSPA effects and the
modified signals back into FluidSynth.
"Reverb:Send" and "Chorus:Send" can be used as effect inputs. They carry the
mono effect send signals (as determined by the reverb and chorus send
generators for each voice) into the LADSPA effects.
Please note that if you run FluidSynth with the internal reverb and chorus
effects active (which is the default), then those effects are already mixed
into the Main:L and Main:R channels. Fore more details, please see the "Signal
Flow" section below.
For host port setups in multi-channel configurations, please see the
"Multi-Channel Output" section below.
## Creating a Configuration File
You can configure LADSPA effects using the FluidSynth shell, but writing the
commands into a file and loading it at startup is much more comfortable. So
let's create a file `effects.txt` with the following contents:
effects.txt
```
ladspa_effect e1 /usr/lib/ladspa/delay.so
ladspa_link e1 Input Main:L
ladspa_link e1 Output Main:L
ladspa_effect e2 /usr/lib/ladspa/delay.so delay_5s
ladspa_link e2 Input Main:R
ladspa_link e2 Output Main:R
ladspa_start
```
As the "Simple Delay Line" plugin only works on a mono signal, the configuration
above creates two effects: the one we named "e1" reads from and writes to the
left FluidSynth audio channel "Main:L", the "e2" effect reads from and
writes to the right channel "Main:R".
Please note that we only specified the path to the library
`/usr/lib/ladspa/delay.so` when creating the "e1" effect, but not which plugin
from the library to use. This is possible because the delay.so library contains
only a single plugin. If you want to use a library that contains more than one
plugin, you would need to give the plugin name as well, as we've done when
creating the "e2" effect. The string to use here is what is called "Plugin
Label" in the `analyseplugin` output.
## Using the Configuration File
Lets start FluidSynth with ALSA output and the standard SoundFont, enable LADSPA
effects, load the effects.txt config file and give it a test MIDI file to play:
(You will need to replace the `test.mid` with your own MIDI file and maybe
change the paths to the effects.txt file and the SoundFont)
```
user@host:$ fluidsynth -a alsa -o synth.ladspa.active=1 -f effects.txt FluidR3_GM.sf2 test.mid
```
You should now hear the MIDI file played at a slightly lower volume with a one
second delay effect added on both left and right channel. If not, please check
the FluidSynth output for any error messages.
## Changing Parameters
You probably noticed that we did not set any values for the "Delay (Seconds)"
and "Dry/Wet Balance" control ports. The delay plugin specifies default
values for these parameters: 1 second delay and a dry/wet balance of 0.5 (check
the `analyseplugin` output above). So when you don't override them, the defaults
are automatically used for rendering.
Let's set different values now and set the delay time on the left channel to
half a second and to 1.5 seconds on the right channel:
```
ladspa_effect e1 /usr/lib/ladspa/delay.so
ladspa_link e1 Input Main:L
ladspa_link e1 Output Main:L
ladspa_set e1 Delay 0.5
ladspa_effect e2 /usr/lib/ladspa/delay.so
ladspa_link e2 Input Main:R
ladspa_link e2 Output Main:R
ladspa_set e2 Delay 1.5
ladspa_start
```
Start FluidSynth again and you should hear that the delay is shorter on the
left channel, longer on the right. You can even change control parameters while
FluidSynth is running. Just type the `ladspa_set ...` commands into the
FluidSynth shell.
And to check the difference that the LADSPA effects have on the sound output,
you can turn them off and on again during run-time. Just type in `ladspa_stop`
and `ladspa_start` into the FluidSynth shell.
### Port Name Matching
Plugin port names are sometimes very long, because the plugin writers want them
to be self-documenting. But note that we didn't need to give the complete port
name "Delay (Seconds)" in the `ladspa_set` commands, but chose to use a much
shorter version: "Delay".
When specifying a port name for the `ladspa_link` and `ladspa_set` commands,
the system will look for any port that *starts with* the name you gave it. If
there is only one match, then that port is chosen. If there are multiple
matches (meaning your port name is ambiguous), you will see an error asking
you to be more specific. So the configuration for the "e1" effect could also
have been written with much shorter port names:
```
ladspa_effect e1 /usr/lib/ladspa/delay.so
ladspa_link e1 In Main:L
ladspa_link e1 Out Main:L
ladspa_set e1 Del 0.5
```
# Signal Flow
The LADSPA effects unit runs immediately after the internal reverb and chorus
effects have been processed. When no plugins have been configured, the
effects unit is dormant and uses no additional system resources.
effects have been processed. When no effects have been configured, the LADSPA
engine is dormant and uses no additional system resources.
When at least one plugin is configured and the engine is activated, the
rendered audio is passed into the LADSPA effects unit, each plugin is
run in the order that they were created and the resulting audio is
passed back into FluidSynth (and from there to the sound card or other
output).
When at least one effect is configured and the engine is activated, the rendered
audio is passed into the LADSPA effects engine, the effects are run in the order
that they were created and the resulting audio is passed back into FluidSynth
(and from there to the sound card or other output).
## Effect Sends
Please note that SoundFont designers can specify how much signal each
instrument should add to the reverb and chorus effect sends. When FluidSynth
renders a block of audio, all currently sounding instruments are mixed into the
`Main` output channels. In addition, all instruments add their signal to the
effect send ports (`Reverb:Send` and `Chorus:Send`) according to the effect
send amount specified in the SoundFont.
If you want to replace the internal reverb or chorus effects with a LADSPA
plugin and you want to honour the decisions made by the SoundFont designer, you
should use the `Reverb:Send` or `Chorus:Send` ports as effect input and
`Main:L` and `Main:R` ports as effect outputs. (See the "Example Setups" section
below for an example on how to replace the internal reverb with a LADSPA plugin.)
Please note that FluidSynth uses a mono signal for both effects, that is why
there is only a single send port for reverb and chorus.
# Loading and Connecting Plugins
# LADSPA Command Reference
Currently the only way to configure the effects unit is via the FluidSynth
shell or via a config file.
The following is a description of all LADSPA-related commands that are
available in the FluidSynth shell if it has been compiled with LADSPA
support.
## Example Setups
- `ladspa_effect`: Create a new effect from a plugin library
- `ladspa_buffer`: Create a new buffer
- `ladspa_link`: Link an effect port to a host port or a buffer
- `ladspa_set`: Set the value of an effect control
- `ladspa_check`: Check the effect setup for any problems
- `ladspa_start`: Start the effects unit
- `ladspa_stop`: Stop the effects unit
- `ladspa_reset`: Reset the effects unit
All examples assume that your `LADSPA_PATH` environment variable points
to the directory containing the plugin libraries (e.g. /usr/lib/ladspa).
## ladspa_effect
### Single Plugin
```
ladspa_effect <effect-name> <library-path> [plugin-name] [--mix [gain]]
```
Load the LADSPA plugin library given by `<library-path>` and create a new effect
(i.e. an instance of a plugin). `<effect-name>` can be chosen by the user and must
unique. `<plugin-name>` is optional if the library contains only one plugin.
If the optional `--mix` parameter is given, then the LADSPA engine will call the
`run_adding` interface of the plugin. This will make the effect add it's output
to the output buffers instead of replacing them. The `--mix` parameter takes an
optional float value `gain`, which will be multiplied with each sample before
adding to the output buffers.
Please note that there is no command to delete a single effect once created. To
remove effects, please use `ladspa_reset` to clear everything start from
scratch.
Can only be called when the effect unit is not active.
## ladspa_buffer
```
ladspa_buffer <buffer-name>
```
Create a new audio buffer called `<buffer-name>`. The buffer is able to be used as
mono output or mono input to an effect. Buffers can be used to connect plugins
between each other without overwriting the host ports with temporary data.
Please note that there is no command to delete a buffer. To remove buffers,
please use `ladspa_reset` to clear everything and start from scratch.
Can only be used when the effect unit is not active.
## ladspa_link
```
ladspa_link <effect-name> <audio-port-name> <buffer-or-host-port-name>
```
Connects an effect input or output port with a buffer or a host port. This
command can be called multiple times and will overwrite the previous connection
made on that effect port.
Please note that there is no command to unlink an effect port. Use
`ladspa_reset` to clear everything and start from scratch.
Can only be used when the effect unit is not active.
## ladspa_set
```
ladspa_set <effect-name> <control-port-name> <float-value>
```
Sets a control port of an effect to a float value. Can be used at any time,
even when the effect unit is active.
## ladspa_check
```
ladspa_check
```
Checks the LADSPA effect configuration for errors. This command is also
implicitly called when executing `ladspa_start`.
## ladspa_start
```
ladspa_start
```
Activates the effects unit and inserts the configured effects into FluidSynth's
audio rendering pipeline.
## ladspa_stop
```
ladspa_stop
```
Deactivates the effects unit and removes the configured effects from
FluidSynth's audio rendering pipeline. The configuration is left untouched, so
it can be started again with `ladspa_start`.
## ladspa_reset
```
ladspa_reset
```
Deactivates the effects unit if active and clears all configuration and loaded
plugins.
# Example Setups
All examples assume that your `LADSPA_PATH` environment variable points to the
directory containing the plugin libraries (e.g. /usr/lib/ladspa).
## Single Plugin
The following loads the delay.so plugin library from the LADSPA SDK and
instantiates the `delay_5s` plugin from that library. It connects the
main left channel output from FluidSynth with the plugin input, the
main left channel input to FluidSynth with the plugin output. It also
sets the two control ports of the plugin to example values and starts
the engine.
instantiates the delay effect under the name "e1". It connects the main left
audio channel from FluidSynth with the plugin input and output and starts the
effects engine.
ladspa_plugin delay.so delay_5s
ladspa_port Input < in1_L
ladspa_port Output > out1_L
ladspa_port Delay = 1.0
ladspa_port Dry/Wet = 0.5
ladspa_start
```
ladspa_effect e1 delay.so
ladspa_link e1 Input Main:L
ladspa_link e1 Output Main:L
ladspa_start
```
The audible effect should be an untouched right channel and a slightly
lower volume on the left with a delay effect of 1 second on top.
## Replacing the FluidSynth Reverb Effect
If you would like a different reverb implementation than the one built-in to
FluidSynth, you can use a LADSPA reverb plugin like the "TAP Reverb" from
[Tom's Audio Processing plugins](http://tap-plugins.sourceforge.net/ladspa.html).
Here is the analyseplugin output for the `tap_reverb.so` plugin:
```
user@host:$ analyseplugin /usr/lib/ladspa/tap_reverb.so
Plugin Name: "TAP Reverberator"
Plugin Label: "tap_reverb"
Plugin Unique ID: 2142
Maker: "Tom Szilagyi"
Copyright: "GPL"
Must Run Real-Time: No
Has activate() Function: Yes
Has deactivate() Function: No
Has run_adding() Function: Yes
Environment: Normal
Ports: "Decay [ms]" input, control, 0 to 10000, default 2500
"Dry Level [dB]" input, control, -70 to 10, default 0
"Wet Level [dB]" input, control, -70 to 10, default 0
"Comb Filters" input, control, toggled, default 1
"Allpass Filters" input, control, toggled, default 1
"Bandpass Filter" input, control, toggled, default 1
"Enhanced Stereo" input, control, toggled, default 1
"Reverb Type" input, control, 0 to 42.1, default 0, integer
"Input Left" input, audio
"Output Left" output, audio
"Input Right" input, audio
"Output Right" output, audio
```
Using this information we can create a LADSPA configuration:
effects.txt
```
ladspa_effect e1 /usr/lib/ladspa/tap_reverb.so
ladspa_link e1 "Input Left" Reverb:Send
ladspa_link e1 "Input Right" Reverb:Send
ladspa_link e1 "Output Left" Main:L
ladspa_link e1 "Output Right" Main:R
ladspa_start
```
Start FluidSynth with the internal reverb disabled. (You will need to replace
the `test.mid` with your own MIDI file and maybe change the paths to the
effects.txt file and the SoundFont)
```
user@host:$ fluidsynth -a alsa -R0 -o synth.ladspa.active=1 -f effects.txt FluidR3_GM.sf2 test.mid
```
You will hear the output with a reverb effect from the plugin. And you can
change the reverb control ports with the `ladspa_set` command while the MIDI
file is playing.
# Multi-Channel Output
FluidSynth is capable of generating multi-channel output by specifying the
`synth.audio-groups` and `synth.audio-channels` configuration settings.
Explaining multi-channel output in detail is out of scope for this guide. But
using multiple output channels has an effect on the host ports that are
available to LADSPA plugins.
As soon as you configure more than one audio-channel, the main audio ports will
not be called "Main:L" and "Main:R" anymore, but will have indices added to
their name. So if you start FluidSynth with `-o synth.audio-groups=2`, then the
following ports will be created:
- Main:L1
- Main:R1
- Main:L2
- Main:R2
- Reverb:Send
- Chorus:Send
If you want all main ports to act as outputs as well as inputs to the effects,
then you also need to increase the `synth.audio-channels` setting.
# LADSPA on other Platforms
LADSPA is a very simple plugin architecture and only requires the ladspa.h
header file as compile-time dependency. To build FluidSynth on non-Linux
platform with LADSPA support, download the ladspa.h file from
http://www.ladspa.org and place it somewhere in your compiler include path. Then
configure and build LADSPA as you normally would.
All information in the above documentation is valid for all other platforms as
well. Just make sure you use the file path format specific to your platform in
the `ladspa_effect` calls. For example, on Windows you should use
```
ladspa_effect c:\path\to\ladspa\plugin.dll
```
instead of
```
ladspa_effect /path/to/ladspa/plugin.so
```
Audacity provides a large number of precompiled LADSPA plugins for Windows and
MacOS: http://www.audacityteam.org/download/plug-ins/
To get the `analyseplugin` and `listplugins` commands on Windows, you can either
compile them yourself using the LADSPA-SDK source code from ladspa.org or install
ladspa-sdk via Cygwin.

View file

@ -104,6 +104,7 @@ extern "C" {
#include "fluidsynth/gen.h"
#include "fluidsynth/voice.h"
#include "fluidsynth/version.h"
#include "fluidsynth/ladspa.h"
#ifdef __cplusplus

View file

@ -27,6 +27,7 @@ if ( NOT MACOSX_FRAMEWORK )
audio.h
event.h
gen.h
ladspa.h
log.h
midi.h
misc.h

View file

@ -0,0 +1,54 @@
/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*/
#ifndef _FLUIDSYNTH_LADSPA_H
#define _FLUIDSYNTH_LADSPA_H
#ifdef __cplusplus
extern "C" {
#endif
FLUIDSYNTH_API int fluid_ladspa_is_active(fluid_ladspa_fx_t *fx);
FLUIDSYNTH_API int fluid_ladspa_activate(fluid_ladspa_fx_t *fx);
FLUIDSYNTH_API int fluid_ladspa_deactivate(fluid_ladspa_fx_t *fx);
FLUIDSYNTH_API int fluid_ladspa_reset(fluid_ladspa_fx_t *fx);
FLUIDSYNTH_API int fluid_ladspa_check(fluid_ladspa_fx_t *fx, char *err, int err_size);
FLUIDSYNTH_API int fluid_ladspa_host_port_exists(fluid_ladspa_fx_t *fx, const char *name);
FLUIDSYNTH_API int fluid_ladspa_add_buffer(fluid_ladspa_fx_t *fx, const char *name);
FLUIDSYNTH_API int fluid_ladspa_buffer_exists(fluid_ladspa_fx_t *fx, const char *name);
FLUIDSYNTH_API int fluid_ladspa_add_effect(fluid_ladspa_fx_t *fx, const char *effect_name,
const char *lib_name, const char *plugin_name);
FLUIDSYNTH_API int fluid_ladspa_effect_can_mix(fluid_ladspa_fx_t *fx, const char *name);
FLUIDSYNTH_API int fluid_ladspa_effect_set_mix(fluid_ladspa_fx_t *fx, const char *name, int mix, float gain);
FLUIDSYNTH_API int fluid_ladspa_effect_port_exists(fluid_ladspa_fx_t *fx, const char *effect_name, const char *port_name);
FLUIDSYNTH_API int fluid_ladspa_effect_set_control(fluid_ladspa_fx_t *fx, const char *effect_name,
const char *port_name, float val);
FLUIDSYNTH_API int fluid_ladspa_effect_link(fluid_ladspa_fx_t *fx, const char *effect_name,
const char *port_name, const char *name);
#ifdef __cplusplus
}
#endif
#endif /* _FLUIDSYNTH_LADSPA_H */

View file

@ -347,6 +347,10 @@ FLUIDSYNTH_API
FLUID_DEPRECATED
void fluid_synth_set_midi_router(fluid_synth_t* synth, fluid_midi_router_t* router);
/* LADSPA */
FLUIDSYNTH_API fluid_ladspa_fx_t *fluid_synth_get_ladspa_fx(fluid_synth_t *synth);
#ifdef __cplusplus
}
#endif

View file

@ -57,6 +57,8 @@ typedef struct _fluid_sequencer_t fluid_sequencer_t; /**< Sequencer i
typedef struct _fluid_ramsfont_t fluid_ramsfont_t; /**< RAM SoundFont */
typedef struct _fluid_rampreset_t fluid_rampreset_t; /**< RAM SoundFont preset */
typedef struct _fluid_cmd_handler_t fluid_cmd_handler_t; /**< Shell Command Handler */
typedef struct _fluid_ladspa_fx_t fluid_ladspa_fx_t; /**< LADSPA effects instance */
typedef int fluid_istream_t; /**< Input stream descriptor */
typedef int fluid_ostream_t; /**< Output stream descriptor */

View file

@ -102,10 +102,6 @@ if ( LIBSNDFILE_SUPPORT )
include_directories ( ${LIBSNDFILE_INCLUDEDIR} ${LIBSNDFILE_INCLUDE_DIRS} )
endif ( LIBSNDFILE_SUPPORT )
if ( LADSPA_SUPPORT )
set ( fluid_ladspa_SOURCES bindings/fluid_ladspa.c bindings/fluid_ladspa.h )
endif ( LADSPA_SUPPORT )
if ( MIDISHARE_SUPPORT )
set ( fluid_midishare_SOURCES drivers/fluid_midishare.c )
include_directories ( ${MidiShare_INCLUDE_DIRS} )
@ -178,12 +174,15 @@ set ( libfluidsynth_SOURCES
bindings/fluid_cmd.c
bindings/fluid_cmd.h
bindings/fluid_filerenderer.c
bindings/fluid_ladspa.c
bindings/fluid_ladspa.h
)
set ( public_HEADERS
${CMAKE_SOURCE_DIR}/include/fluidsynth/audio.h
${CMAKE_SOURCE_DIR}/include/fluidsynth/event.h
${CMAKE_SOURCE_DIR}/include/fluidsynth/gen.h
${CMAKE_SOURCE_DIR}/include/fluidsynth/ladspa.h
${CMAKE_SOURCE_DIR}/include/fluidsynth/log.h
${CMAKE_SOURCE_DIR}/include/fluidsynth/midi.h
${CMAKE_SOURCE_DIR}/include/fluidsynth/misc.h
@ -235,7 +234,6 @@ add_library ( libfluidsynth
${fluid_dbus_SOURCES}
${fluid_jack_SOURCES}
${fluid_lash_SOURCES}
${fluid_ladspa_SOURCES}
${fluid_midishare_SOURCES}
${fluid_oss_SOURCES}
${fluid_portaudio_SOURCES}
@ -293,6 +291,7 @@ endif ( LIBFLUID_CPPFLAGS )
target_link_libraries ( libfluidsynth
${GLIB_LIBRARIES}
${GMODULE_LIBRARIES}
${LASH_LIBRARIES}
${JACK_LIBRARIES}
${ALSA_LIBRARIES}

View file

@ -33,9 +33,11 @@
#include <readline/history.h>
#endif
#define MAX_TOKENS 100 /* LADSPA plugins need lots of parameters */
/* FIXME: LADSPA used to need a lot of parameters on a single line. This is not
* necessary anymore, so the limits below could probably be reduced */
#define MAX_TOKENS 100
#define MAX_COMMAND_LEN 1024 /* max command length accepted by fluid_command() */
#define FLUID_WORKLINELENGTH 1024 /* LADSPA plugins use long command lines */
#define FLUID_WORKLINELENGTH 1024
#define FLUID_ENTRY_COMMAND(data) fluid_cmd_handler_t* handler=(fluid_cmd_handler_t*)(data)
@ -47,11 +49,6 @@ struct _fluid_cmd_handler_t {
fluid_midi_router_rule_t *cmd_rule; /* Rule currently being processed by shell command handler */
int cmd_rule_type; /* Type of the rule (#fluid_midi_router_rule_type) */
#ifdef LADSPA
/* Instance id of the LADSPA plugin currently being processed by shell command handler */
int ladspa_plugin_id;
#endif
};
@ -180,16 +177,14 @@ static const fluid_cmd_int_t fluid_commands[] = {
"echo arg Print arg" },
/* LADSPA-related commands */
#ifdef LADSPA
{ "ladspa_plugin", "ladspa", fluid_handle_ladspa_plugin,
"ladspa_plugin Instantiate a new LADSPA plugin"},
{ "ladspa_port", "ladspa", fluid_handle_ladspa_port,
"ladspa_port Connect a LADSPA plugin port"},
{ "ladspa_node", "ladspa", fluid_handle_ladspa_node,
"ladspa_node Create a LADSPA audio or control node"},
{ "ladspa_control", "ladspa", fluid_handle_ladspa_control,
"ladspa_control Set the value of a LADSPA control node"},
{ "ladspa_control_defaults", "ladspa", fluid_handle_ladspa_control_defaults,
"ladspa_control_defaults Assign all unconnected controls on all plugins their default value"},
{ "ladspa_effect", "ladspa", fluid_handle_ladspa_effect,
"ladspa_effect Create a new effect from a LADSPA plugin"},
{ "ladspa_link", "ladspa", fluid_handle_ladspa_link,
"ladspa_link Connect an effect port to a host port or buffer"},
{ "ladspa_buffer", "ladspa", fluid_handle_ladspa_buffer,
"ladspa_buffer Create a LADSPA buffer"},
{ "ladspa_set", "ladspa", fluid_handle_ladspa_set,
"ladspa_set Set the value of an effect control port"},
{ "ladspa_check", "ladspa", fluid_handle_ladspa_check,
"ladspa_check Check LADSPA configuration"},
{ "ladspa_start", "ladspa", fluid_handle_ladspa_start,
@ -1893,26 +1888,36 @@ int fluid_handle_router_par2(void* data, int ac, char** av, fluid_ostream_t out)
return FLUID_FAILED; \
}
#define CHECK_LADSPA_INACTIVE(_fx, _out) \
if (fluid_ladspa_is_active(_fx)) \
{ \
fluid_ostream_printf(_out, "LADSPA already started.\n"); \
return FLUID_FAILED; \
}
#define LADSPA_ERR_LEN (1024)
/**
* ladspa_start
*/
int fluid_handle_ladspa_start(void* data, int ac, char **av, fluid_ostream_t out)
{
FLUID_ENTRY_COMMAND(data);
fluid_ladspa_fx_t *fx = handler->synth->ladspa_fx;
char error[LADSPA_ERR_LEN];
CHECK_LADSPA_ENABLED(fx, out);
if (fluid_ladspa_is_active(fx))
if (ac != 0)
{
fluid_ostream_printf(out, "LADSPA already started.\n");
fluid_ostream_printf(out, "ladspa_start does not accept any arguments\n");
return FLUID_FAILED;
}
CHECK_LADSPA_ENABLED(fx, out);
CHECK_LADSPA_INACTIVE(fx, out);
if (fluid_ladspa_check(fx, error, LADSPA_ERR_LEN) != FLUID_OK)
{
fluid_ostream_printf(out, "LADSPA check failed: %s", error);
fluid_ostream_printf(out, "LADSPA not started.\n");
fluid_ostream_printf(out, "Unable to start LADSPA: %s", error);
return FLUID_FAILED;
}
@ -1925,11 +1930,20 @@ int fluid_handle_ladspa_start(void* data, int ac, char **av, fluid_ostream_t out
return FLUID_OK;
}
/**
* ladspa_stop
*/
int fluid_handle_ladspa_stop(void* data, int ac, char **av, fluid_ostream_t out)
{
FLUID_ENTRY_COMMAND(data);
fluid_ladspa_fx_t *fx = handler->synth->ladspa_fx;
if (ac != 0)
{
fluid_ostream_printf(out, "ladspa_stop does not accept any arguments\n");
return FLUID_FAILED;
}
CHECK_LADSPA_ENABLED(fx, out);
if (!fluid_ladspa_is_active(fx))
@ -1946,11 +1960,20 @@ int fluid_handle_ladspa_stop(void* data, int ac, char **av, fluid_ostream_t out)
return FLUID_OK;
}
/**
* ladspa_reset
*/
int fluid_handle_ladspa_reset(void* data, int ac, char **av, fluid_ostream_t out)
{
FLUID_ENTRY_COMMAND(data);
fluid_ladspa_fx_t *fx = handler->synth->ladspa_fx;
if (ac != 0)
{
fluid_ostream_printf(out, "ladspa_reset does not accept any arguments\n");
return FLUID_FAILED;
}
CHECK_LADSPA_ENABLED(fx, out);
fluid_ladspa_reset(fx);
@ -1958,30 +1981,21 @@ int fluid_handle_ladspa_reset(void* data, int ac, char **av, fluid_ostream_t out
return FLUID_OK;
}
int fluid_handle_ladspa_control_defaults(void* data, int ac, char **av, fluid_ostream_t out)
{
FLUID_ENTRY_COMMAND(data);
fluid_ladspa_fx_t *fx = handler->synth->ladspa_fx;
CHECK_LADSPA_ENABLED(fx, out);
if (fluid_ladspa_control_defaults(fx) != FLUID_OK)
{
fluid_ostream_printf(out, "Error while setting default values for control ports\n");
return FLUID_FAILED;
}
fluid_ostream_printf(out, "Control port defaults set\n");
return FLUID_OK;
}
/**
* ladspa_check
*/
int fluid_handle_ladspa_check(void* data, int ac, char **av, fluid_ostream_t out)
{
FLUID_ENTRY_COMMAND(data);
fluid_ladspa_fx_t *fx = handler->synth->ladspa_fx;
char error[LADSPA_ERR_LEN];
if (ac != 0)
{
fluid_ostream_printf(out, "ladspa_reset does not accept any arguments\n");
return FLUID_FAILED;
}
CHECK_LADSPA_ENABLED(fx, out);
if (fluid_ladspa_check(fx, error, LADSPA_ERR_LEN) != FLUID_OK)
@ -1995,173 +2009,163 @@ int fluid_handle_ladspa_check(void* data, int ac, char **av, fluid_ostream_t out
return FLUID_OK;
}
int fluid_handle_ladspa_control(void* data, int ac, char **av, fluid_ostream_t out)
/**
* ladspa_set <effect> <port> <value>
*/
int fluid_handle_ladspa_set(void *data, int ac, char **av, fluid_ostream_t out)
{
FLUID_ENTRY_COMMAND(data);
fluid_ladspa_fx_t *fx = handler->synth->ladspa_fx;
CHECK_LADSPA_ENABLED(fx, out);
if (ac != 2)
if (ac != 3)
{
fluid_ostream_printf(out, "ladspa_control needs two arguments: node name and value.\n");
fluid_ostream_printf(out, "ladspa_set needs three arguments: <effect> <port> <value>\n");
return FLUID_FAILED;
};
CHECK_LADSPA_ENABLED(fx, out);
/* Redundant check, just here to give a more detailed error message */
if (!fluid_ladspa_node_exists(fx, av[0]))
if (!fluid_ladspa_effect_port_exists(fx, av[0], av[1]))
{
fluid_ostream_printf(out, "Node '%s' not found.\n", av[0]);
fluid_ostream_printf(out, "Port '%s' not found on effect '%s'\n", av[1], av[0]);
return FLUID_FAILED;
}
if (fluid_ladspa_set_control_node(fx, av[0], atof(av[1])) != FLUID_OK)
if (fluid_ladspa_effect_set_control(fx, av[0], av[1], atof(av[2])) != FLUID_OK)
{
fluid_ostream_printf(out, "Failed to set node '%s', maybe it's not a control node?\n",
av[0]);
fluid_ostream_printf(out, "Failed to set port '%s' on effect '%s', "
"maybe it is not a control port?\n", av[1], av[0]);
return FLUID_FAILED;
}
return FLUID_OK;
};
int fluid_handle_ladspa_node(void* data, int ac, char **av, fluid_ostream_t out)
/**
* ladspa_buffer <name>
*/
int fluid_handle_ladspa_buffer(void *data, int ac, char **av, fluid_ostream_t out)
{
FLUID_ENTRY_COMMAND(data);
fluid_ladspa_fx_t *fx = handler->synth->ladspa_fx;
char *name;
char *type;
CHECK_LADSPA_ENABLED(fx, out);
if (ac < 2)
if (ac != 1)
{
fluid_ostream_printf(out, "ladspa_node needs at least two arguments: node name and type.\n");
fluid_ostream_printf(out, "ladspa_buffer needs one argument: <name>\n");
return FLUID_FAILED;
};
name = av[0];
type = av[1];
CHECK_LADSPA_ENABLED(fx, out);
CHECK_LADSPA_INACTIVE(fx, out);
/* audio node - additional no arguments */
if (FLUID_STRCMP(type, "audio") == 0)
if (fluid_ladspa_add_buffer(fx, av[0]) != FLUID_OK)
{
if (fluid_ladspa_add_audio_node(fx, name) != FLUID_OK)
{
fluid_ostream_printf(out, "Failed to add audio node.\n");
return FLUID_FAILED;
}
}
/* control node - arguments: <val> */
else if (FLUID_STRCMP(type, "control") == 0)
{
if (ac != 3)
{
fluid_ostream_printf(out, "Control nodes need 3 arguments.\n");
return FLUID_FAILED;
}
if (fluid_ladspa_add_control_node(fx, name, atof(av[2])) != FLUID_OK)
{
fluid_ostream_printf(out, "Failed to add contrl node.\n");
return FLUID_FAILED;
}
}
else {
fluid_ostream_printf(out, "Invalid node type.\n");
return FLUID_FAILED;
fluid_ostream_printf(out, "Failed to add buffer\n");
return FLUID_FAILED;
}
return FLUID_OK;
};
int fluid_handle_ladspa_plugin(void* data, int ac, char **av, fluid_ostream_t out)
/**
* ladspa_effect <name> <library> [plugin] [--mix [gain]]
*/
int fluid_handle_ladspa_effect(void* data, int ac, char **av, fluid_ostream_t out)
{
FLUID_ENTRY_COMMAND(data);
fluid_ladspa_fx_t *fx = handler->synth->ladspa_fx;
int plugin_id;
char *plugin_name = NULL;
int pos;
int mix = FALSE;
float gain = 1.0f;
if (ac < 2 || ac > 5)
{
fluid_ostream_printf(out, "ladspa_effect invalid arguments: "
"<name> <library> [plugin] [--mix [gain]]\n");
return FLUID_FAILED;
}
pos = 2;
/* If the first optional arg is not --mix, then it must be the plugin label */
if ((pos < ac) && (FLUID_STRCMP(av[pos], "--mix") != 0))
{
plugin_name = av[pos];
pos++;
}
/* If this optional arg is --mix and there's an argument after it, that that
* must be the gain */
if ((pos < ac) && (FLUID_STRCMP(av[pos], "--mix") == 0))
{
mix = TRUE;
if (pos + 1 < ac)
{
gain = atof(av[pos + 1]);
}
}
CHECK_LADSPA_ENABLED(fx, out);
CHECK_LADSPA_INACTIVE(fx, out);
if (ac != 2)
if (fluid_ladspa_add_effect(fx, av[0], av[1], plugin_name) != FLUID_OK)
{
fluid_ostream_printf(out, "ladspa_plugin needs 2 arguments: library and plugin id.\n");
fluid_ostream_printf(out, "Failed to create effect\n");
return FLUID_FAILED;
}
plugin_id = fluid_ladspa_add_plugin(fx, av[0], av[1]);
if (plugin_id < 0)
if (mix)
{
fluid_ostream_printf(out, "Failed to add plugin.\n");
return FLUID_FAILED;
}
if (!fluid_ladspa_effect_can_mix(fx, av[0]))
{
fluid_ostream_printf(out, "Effect '%s' does not support --mix mode\n", av[0]);
return FLUID_FAILED;
}
/* store current plugin in the handler, so that subsequent ladspa_port
* commands know which plugin to configure */
handler->ladspa_plugin_id = plugin_id;
if (fluid_ladspa_effect_set_mix(fx, av[0], mix, gain) != FLUID_OK)
{
fluid_ostream_printf(out, "Failed to set --mix mode\n");
return FLUID_FAILED;
}
}
return FLUID_OK;
}
int fluid_handle_ladspa_port(void* data, int ac, char **av, fluid_ostream_t out)
/*
* ladspa_link <effect> <port> <buffer or host port>
*/
int fluid_handle_ladspa_link(void* data, int ac, char **av, fluid_ostream_t out)
{
FLUID_ENTRY_COMMAND(data);
fluid_ladspa_fx_t *fx = handler->synth->ladspa_fx;
int dir;
CHECK_LADSPA_ENABLED(fx, out);
if (ac != 3)
{
fluid_ostream_printf(out, "ladspa_port needs 3 arguments: "
"port name, direction and node name.\n");
fluid_ostream_printf(out, "ladspa_link needs 3 arguments: "
"<effect> <port> <buffer or host name>\n");
return FLUID_FAILED;
}
if (handler->ladspa_plugin_id == -1)
CHECK_LADSPA_ENABLED(fx, out);
CHECK_LADSPA_INACTIVE(fx, out);
if (!fluid_ladspa_effect_port_exists(fx, av[0], av[1]))
{
fluid_ostream_printf(out, "Please choose a plugin with ladspa_plugin first.\n");
fluid_ostream_printf(out, "Port '%s' not found on effect '%s'\n", av[1], av[0]);
return FLUID_FAILED;
}
if (FLUID_STRCMP(av[1], "<") == 0)
if (!fluid_ladspa_host_port_exists(fx, av[2]) && !fluid_ladspa_buffer_exists(fx, av[2]))
{
dir = FLUID_LADSPA_INPUT;
}
else if (FLUID_STRCMP(av[1], ">") == 0)
{
dir = FLUID_LADSPA_OUTPUT;
}
else if (FLUID_STRCMP(av[1], "=") == 0)
{
dir = FLUID_LADSPA_FIXED;
}
else
{
fluid_ostream_printf(out, "Invalid direction, please use <, > or =\n");
fluid_ostream_printf(out, "Host port or buffer '%s' not found.\n", av[2]);
return FLUID_FAILED;
}
/* Check port and node name before trying to connect them by name. This is
* redundant, as fluid_ladspa_connect checks them as well, but we do it
* here anyway to give the user better feedback in case a port or node
* could not be found.
*/
if (!fluid_ladspa_port_exists(fx, handler->ladspa_plugin_id, av[0]))
if (fluid_ladspa_effect_link(fx, av[0], av[1], av[2]) != FLUID_OK)
{
fluid_ostream_printf(out, "Port '%s' not found.\n", av[0]);
return FLUID_FAILED;
}
if (dir != FLUID_LADSPA_FIXED && !fluid_ladspa_node_exists(fx, av[2]))
{
fluid_ostream_printf(out, "Node '%s' not found.\n", av[2]);
return FLUID_FAILED;
}
if (fluid_ladspa_connect(fx, handler->ladspa_plugin_id, dir, av[0], av[2]) != FLUID_OK)
{
fluid_ostream_printf(out, "Failed to connect plugin port.\n");
fluid_ostream_printf(out, "Failed to link port\n");
return FLUID_FAILED;
}
@ -2285,10 +2289,6 @@ fluid_cmd_handler_t* new_fluid_cmd_handler(fluid_synth_t* synth, fluid_midi_rout
}
}
#ifdef LADSPA
handler->ladspa_plugin_id = -1;
#endif
return handler;
}

View file

@ -85,15 +85,14 @@ int fluid_handle_router_par1(void* data, int ac, char** av, fluid_ostream_t out)
int fluid_handle_router_par2(void* data, int ac, char** av, fluid_ostream_t out);
#ifdef LADSPA
int fluid_handle_ladspa_plugin(void* data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_ladspa_port(void* data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_ladspa_node(void* data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_ladspa_control(void* data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_ladspa_control_defaults(void* data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_ladspa_check(void* data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_ladspa_start(void* data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_ladspa_stop(void* data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_ladspa_reset(void* data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_ladspa_effect(void *data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_ladspa_link(void *data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_ladspa_buffer(void *data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_ladspa_set(void *data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_ladspa_check(void *data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_ladspa_start(void *data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_ladspa_stop(void *data, int ac, char **av, fluid_ostream_t out);
int fluid_handle_ladspa_reset(void *data, int ac, char **av, fluid_ostream_t out);
#endif
fluid_cmd_t* fluid_cmd_copy(fluid_cmd_t* cmd);

File diff suppressed because it is too large Load diff

View file

@ -18,51 +18,19 @@
* 02110-1301, USA
*/
/* Author: Markus Nentwig, nentwig@users.sourceforge.net
*/
#ifndef _FLUID_LADSPA_H
#define _FLUID_LADSPA_H
#include "fluid_sys.h"
#include "fluidsynth_priv.h"
#ifdef LADSPA
typedef enum _fluid_ladspa_dir_t {
FLUID_LADSPA_INPUT,
FLUID_LADSPA_OUTPUT,
FLUID_LADSPA_FIXED
} fluid_ladspa_dir_t;
typedef struct _fluid_ladspa_fx_t fluid_ladspa_fx_t;
fluid_ladspa_fx_t *new_fluid_ladspa_fx(fluid_real_t sample_rate, int audio_groups, int effects_channels, int audio_channels, int buffer_size);
fluid_ladspa_fx_t *new_fluid_ladspa_fx(fluid_real_t sample_rate, int buffer_size);
void delete_fluid_ladspa_fx(fluid_ladspa_fx_t *fx);
int fluid_ladspa_set_sample_rate(fluid_ladspa_fx_t *fx, fluid_real_t sample_rate);
int fluid_ladspa_is_active(fluid_ladspa_fx_t *fx);
int fluid_ladspa_activate(fluid_ladspa_fx_t *fx);
int fluid_ladspa_deactivate(fluid_ladspa_fx_t *fx);
int fluid_ladspa_reset(fluid_ladspa_fx_t *fx);
void fluid_ladspa_run(fluid_ladspa_fx_t *fx, int block_count, int block_size);
void fluid_ladspa_run(fluid_ladspa_fx_t *fx, fluid_real_t *left_buf[], fluid_real_t *right_buf[],
fluid_real_t *fx_left_buf[], fluid_real_t *fx_right_buf[], int block_count, int block_size);
int fluid_ladspa_add_host_ports(fluid_ladspa_fx_t *fx, const char *prefix,
int num_buffers, fluid_real_t *buffers[]);
int fluid_ladspa_add_plugin(fluid_ladspa_fx_t *fx, const char *lib_name, const char *plugin_name);
int fluid_ladspa_port_exists(fluid_ladspa_fx_t *fx, int plugin_id, const char *name);
int fluid_ladspa_add_audio_node(fluid_ladspa_fx_t *fx, const char *name);
int fluid_ladspa_add_control_node(fluid_ladspa_fx_t *fx, const char *name, fluid_real_t val);
int fluid_ladspa_set_control_node(fluid_ladspa_fx_t *fx, const char *name, fluid_real_t val);
int fluid_ladspa_node_exists(fluid_ladspa_fx_t *fx, const char *name);
int fluid_ladspa_connect(fluid_ladspa_fx_t *fx, int plugin_id, fluid_ladspa_dir_t dir,
const char *port_name, const char *node_name);
int fluid_ladspa_check(fluid_ladspa_fx_t *fx, char *err, int err_size);
int fluid_ladspa_control_defaults(fluid_ladspa_fx_t *fx);
#endif /* LADSPA */
#endif /* _FLUID_LADSPA_H */

View file

@ -49,9 +49,6 @@
/* whether or not we are supporting lash */
#cmakedefine HAVE_LASH @HAVE_LASH@
/* Define to 1 if you have the `dl' library (-ldl). */
#cmakedefine HAVE_LIBDL @HAVE_LIBDL@
/* Define to 1 if you have the `MidiShare' library (-lMidiShare). */
#cmakedefine HAVE_LIBMIDISHARE @HAVE_LIBMIDISHARE@

View file

@ -141,12 +141,10 @@ fluid_rvoice_mixer_process_fx(fluid_rvoice_mixer_t* mixer)
}
#ifdef LADSPA
/* Run the signal through the LADSPA Fx unit */
/* Run the signal through the LADSPA Fx unit. The buffers have already been
* set up in fluid_rvoice_mixer_set_ladspa. */
if (mixer->ladspa_fx) {
fluid_ladspa_run(mixer->ladspa_fx,
mixer->buffers.left_buf, mixer->buffers.right_buf,
mixer->buffers.fx_left_buf, mixer->buffers.fx_right_buf,
mixer->current_blockcount, FLUID_BUFSIZE);
fluid_ladspa_run(mixer->ladspa_fx, mixer->current_blockcount, FLUID_BUFSIZE);
fluid_check_fpe("LADSPA");
}
#endif
@ -203,15 +201,21 @@ fluid_mix_one(fluid_rvoice_t* rvoice, fluid_real_t** bufs, unsigned int bufcount
static FLUID_INLINE int
fluid_mixer_buffers_prepare(fluid_mixer_buffers_t* buffers, fluid_real_t** outbufs)
{
fluid_real_t* reverb_buf, *chorus_buf;
fluid_real_t *reverb_buf, *chorus_buf;
int i;
int with_reverb = buffers->mixer->fx.with_reverb;
int with_chorus = buffers->mixer->fx.with_chorus;
/* Set up the reverb / chorus buffers only, when the effect is
* enabled on synth level. Nonexisting buffers are detected in the
* DSP loop. Not sending the reverb / chorus signal saves some time
* in that case. */
reverb_buf = buffers->mixer->fx.with_reverb ? buffers->fx_left_buf[SYNTH_REVERB_CHANNEL] : NULL;
chorus_buf = buffers->mixer->fx.with_chorus ? buffers->fx_left_buf[SYNTH_CHORUS_CHANNEL] : NULL;
/* Set up the reverb and chorus buffers only when the effect is enabled or
* when LADSPA is active. Nonexisting buffers are detected in the DSP loop.
* Not sending the effect signals saves some time in that case. */
#ifdef LADSPA
int with_ladspa = (buffers->mixer->ladspa_fx != NULL);
with_reverb = (with_reverb | with_ladspa);
with_chorus = (with_chorus | with_ladspa);
#endif
reverb_buf = (with_reverb) ? buffers->fx_left_buf[SYNTH_REVERB_CHANNEL] : NULL;
chorus_buf = (with_chorus) ? buffers->fx_left_buf[SYNTH_CHORUS_CHANNEL] : NULL;
outbufs[buffers->buf_count*2 + SYNTH_REVERB_CHANNEL] = reverb_buf;
outbufs[buffers->buf_count*2 + SYNTH_CHORUS_CHANNEL] = chorus_buf;
@ -627,9 +631,29 @@ void delete_fluid_rvoice_mixer(fluid_rvoice_mixer_t* mixer)
#ifdef LADSPA
void fluid_rvoice_mixer_set_ladspa(fluid_rvoice_mixer_t* mixer, fluid_ladspa_fx_t *ladspa_fx)
/**
* Set a LADSPS fx instance to be used by the mixer and assign the mixer buffers
* as LADSPA host buffers with sensible names */
void fluid_rvoice_mixer_set_ladspa(fluid_rvoice_mixer_t* mixer,
fluid_ladspa_fx_t *ladspa_fx, int audio_groups)
{
mixer->ladspa_fx = ladspa_fx;
mixer->ladspa_fx = ladspa_fx;
if (ladspa_fx == NULL)
{
return;
}
fluid_ladspa_add_host_ports(ladspa_fx, "Main:L", audio_groups,
mixer->buffers.left_buf);
fluid_ladspa_add_host_ports(ladspa_fx, "Main:R", audio_groups,
mixer->buffers.right_buf);
fluid_ladspa_add_host_ports(ladspa_fx, "Reverb:Send", 1,
&mixer->buffers.fx_left_buf[SYNTH_REVERB_CHANNEL]);
fluid_ladspa_add_host_ports(ladspa_fx, "Chorus:Send", 1,
&mixer->buffers.fx_left_buf[SYNTH_REVERB_CHANNEL]);
}
#endif

View file

@ -69,7 +69,8 @@ void fluid_rvoice_mixer_set_threads(fluid_rvoice_mixer_t* mixer, int thread_coun
int prio_level);
#ifdef LADSPA
void fluid_rvoice_mixer_set_ladspa(fluid_rvoice_mixer_t* mixer, fluid_ladspa_fx_t* ladspa_fx);
void fluid_rvoice_mixer_set_ladspa(fluid_rvoice_mixer_t* mixer,
fluid_ladspa_fx_t *ladspa_fx, int audio_groups);
#endif
#endif

View file

@ -711,14 +711,14 @@ new_fluid_synth(fluid_settings_t *settings)
fluid_settings_getint(settings, "synth.ladspa.active", &with_ladspa);
if (with_ladspa) {
#ifdef LADSPA
synth->ladspa_fx = new_fluid_ladspa_fx(synth->sample_rate, synth->audio_groups,
synth->effects_channels, synth->audio_channels,
synth->ladspa_fx = new_fluid_ladspa_fx(synth->sample_rate,
FLUID_MIXER_MAX_BUFFERS_DEFAULT * FLUID_BUFSIZE);
if(synth->ladspa_fx == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory");
goto error_recovery;
}
fluid_rvoice_mixer_set_ladspa(synth->eventhandler->mixer, synth->ladspa_fx);
fluid_rvoice_mixer_set_ladspa(synth->eventhandler->mixer, synth->ladspa_fx,
synth->audio_groups);
#else /* LADSPA */
FLUID_LOG(FLUID_WARN, "FluidSynth has not been compiled with LADSPA support");
#endif /* LADSPA */
@ -5288,3 +5288,16 @@ int fluid_synth_set_channel_type(fluid_synth_t* synth, int chan, int type)
FLUID_API_RETURN(FLUID_OK);
}
/**
* Return the LADSPA effects instance used by FluidSynth
*
* @param synth FluidSynth instance
* @return pointer to LADSPA fx or NULL if compiled without LADSPA support or LADSPA is not active
*/
fluid_ladspa_fx_t *fluid_synth_get_ladspa_fx(fluid_synth_t *synth)
{
fluid_return_val_if_fail(synth != NULL, NULL);
return synth->ladspa_fx;
}

View file

@ -169,9 +169,7 @@ struct _fluid_synth_t
fluid_mod_t* default_mod; /**< the (dynamic) list of default modulators */
#ifdef LADSPA
fluid_ladspa_fx_t* ladspa_fx; /**< Effects unit for LADSPA support */
#endif
fluid_ladspa_fx_t* ladspa_fx; /**< Effects unit for LADSPA support */
};
fluid_preset_t* fluid_synth_find_preset(fluid_synth_t* synth,

View file

@ -39,6 +39,9 @@
#include <glib.h>
#include "fluidsynth_priv.h"
#ifdef LADSPA
#include <gmodule.h>
#endif
/**
* Macro used for safely accessing a message from a GError and using a default
@ -320,6 +323,19 @@ void delete_fluid_thread(fluid_thread_t* thread);
void fluid_thread_self_set_prio (int prio_level);
int fluid_thread_join(fluid_thread_t* thread);
/* Dynamic Module Loading, currently only used by LADSPA subsystem */
#ifdef LADSPA
typedef GModule fluid_module_t;
#define fluid_module_open(_name) g_module_open((_name), G_MODULE_BIND_LOCAL)
#define fluid_module_close(_mod) g_module_close(_mod)
#define fluid_module_error() g_module_error()
#define fluid_module_name(_mod) g_module_name(_mod)
#define fluid_module_symbol(_mod, _name, _ptr) g_module_symbol((_mod), (_name), (_ptr))
#endif /* LADSPA */
/* Sockets and I/O */
fluid_istream_t fluid_get_stdin (void);

View file

@ -275,7 +275,7 @@ do { strncpy(_dst,_src,_n); \
#endif
#if defined(WIN32) && !defined(MINGW32)
#define FLUID_STRNCASECMP _strincmp
#define FLUID_STRNCASECMP _strnicmp
#else
#define FLUID_STRNCASECMP strncasecmp
#endif