Switch tap to submodule

This commit is contained in:
Tres Finocchiaro
2017-11-08 22:20:42 -05:00
parent d63cfe0980
commit c102fa8ab4
29 changed files with 15 additions and 13302 deletions

3
.gitmodules vendored
View File

@@ -19,3 +19,6 @@
[submodule "plugins/LadspaEffect/swh/ladspa"]
path = plugins/LadspaEffect/swh/ladspa
url = https://github.com/swh/ladspa
[submodule "plugins/LadspaEffect/tap/tap-plugins"]
path = plugins/LadspaEffect/tap/tap-plugins
url = https://github.com/tomszilagyi/tap-plugins

View File

@@ -1,22 +1,27 @@
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/include")
FILE(GLOB PLUGIN_SOURCES *.c)
FILE(GLOB PLUGIN_SOURCES tap-plugins/*.c)
LIST(SORT PLUGIN_SOURCES)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -Wno-write-strings -fomit-frame-pointer -fno-strict-aliasing -fstrength-reduce -funroll-loops -ffast-math")
FOREACH(_item ${PLUGIN_SOURCES})
GET_FILENAME_COMPONENT(_plugin "${_item}" NAME_WE)
ADD_LIBRARY("${_plugin}" MODULE "${_item}")
# TAP pinknoise will re-init srand(); use existing seed instead
IF("${_plugin}" MATCHES "tap_pinknoise")
TARGET_COMPILE_DEFINITIONS("${_plugin}" PRIVATE TAP_DISABLE_SRAND=1)
ENDIF()
INSTALL(TARGETS "${_plugin}" LIBRARY DESTINATION "${PLUGIN_DIR}/ladspa")
SET_TARGET_PROPERTIES("${_plugin}" PROPERTIES PREFIX "")
IF(LMMS_BUILD_WIN32)
# Don't strip if "Debug" or "RelWithDebInfo"
IF(LMMS_BUILD_WIN32 AND NOT CMAKE_BUILD_TYPE MATCHES "Deb")
ADD_CUSTOM_COMMAND(TARGET "${_plugin}" POST_BUILD COMMAND "${STRIP}" \"$<TARGET_FILE:${_plugin}>\")
ENDIF(LMMS_BUILD_WIN32)
ENDIF()
IF(LMMS_BUILD_APPLE)
SET_TARGET_PROPERTIES("${_plugin}" PROPERTIES LINK_FLAGS "${LINK_FLAGS} -Bsymbolic -lm")
ELSEIF(NOT LMMS_BUILD_OPENBSD)
SET_TARGET_PROPERTIES("${_plugin}" PROPERTIES LINK_FLAGS "${LINK_FLAGS} -shared -Wl,-no-undefined -Wl,-Bsymbolic -lm")
ENDIF(LMMS_BUILD_APPLE)
ENDIF()
IF(LMMS_BUILD_LINUX OR LMMS_BUILD_HAIKU)
SET_TARGET_PROPERTIES("${_plugin}" PROPERTIES LINK_FLAGS "${LINK_FLAGS}")
ENDIF(LMMS_BUILD_LINUX OR LMMS_BUILD_HAIKU)
ENDFOREACH(_item ${PLUGIN_SOURCES})
ENDIF()
ENDFOREACH()

View File

@@ -1,340 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@@ -1,66 +0,0 @@
The author would like to thank the following people for their help,
support, comments, suggestions, patches etc.
If you discover yourself in the following list and would like to
remain nameless instead, please write to the author.
In no particular order:
Anand Kumria <akumria@debian.org> constantly maintains a Debian
package of this software.
As the author of the lrdf library, Steve Harris <steve@plugin.org.uk>
was kind enough to take a look at the RDF file describing these
plugins.
Alexander Koenig <alex@lisas.de> discovered that the AutoPanner (and
Tremolo) didn't work at very small frequency values, and sent a patch
that became the base of the solution.
Forrest Cook <cook@lwn.net> suggested implementing an AutoPanner as a
new TAP-plugin.
Nick Lamb <njl98r@ecs.soton.ac.uk> suggested using his Demolition
[http://www.ecs.soton.ac.uk/~njl98r/code/ladspa/] program to
sanity-check the TAP-plugins. Demolition proved essential, a must for
any LADSPA plugin developer. It revealed bugs and LADSPA
non-conformancies too many to mention in the TAP-plugins code, which
could be fixed easily this way.
Linium <intent@netpratique.fr> discovered a bug in EQ and EQ-BW:
the plugins reinitialized themselves on each transport stop, which
resulted in the effect disappearing after every STOP->PLAY.
As a main Ardour developer, Taybin Rutkin <taybin@earthlink.net>
implemented using RDF metadata to generate drop-down lists in LADSPA
plugin GUIs in Ardour. This made it much easier to create good-looking
and easy to use plugins; in particular TAP Reverberator and TAP
Dynamics are among the "big winners".
Luke Yelavich <luke@audioslack.com> sent a patch that cleaned up the
Makefile a bit by introducing the variables CFLAGS and LDFLAGS.
Jan Depner <eviltwin69@cableone.net> suggested implementing some kind
of doubler plugin, and he gave me useful pointers about the Midpoint
Displacement Algorithm with which a semi-random series of numbers
following a fractal pattern can be generated. Without him, the TAP
Fractal Doubler would have never been written. He also helped a lot
with the CPU runaway problems in TAP Reverberator, by reporting the
problem and trying out my solutions.
Maarten Maathuis <madman2003@gmail.com> contributed the Bauer
stereophonic-to-binaural DSP plugin. NOTE: this plugin only existed in
CVS between releases 0.7.0 and 0.7.1; it has been agreed to be removed
from TAP-plugins and released separately.
Damon Chaplin <damon@karuna.eclipse.co.uk> tracked down issues that
caused problems on 64-bit machines, found uninitialised variables via
Valgrind, and also pinned down long lurking denormal issues. Thanks!
And, of course, special thanks to the Ardour [http://ardour.org] and
JACK [http://jackit.sf.net] development teams for their tireless
efforts in creating one of the best Linux audio engineering platforms
(and besides that, the recommended host for these plugins).
TAP-plugins aims to be a very small contribution to this effort.

View File

@@ -1,44 +0,0 @@
TAP-plugins (Tom's Audio Processing plugins)
--------------------------------------------
AUTHOR: Tom Szilagyi <tszilagyi@users.sourceforge.net>
WEBPAGE: http://tap-plugins.sf.net
Welcome!
TAP-plugins is a bunch of LADSPA plugins for audio processing. It runs
on the GNU/Linux operating system, and possibly other UNIX-like
operating systems.
LADSPA stands for Linux Audio Developers Simple Plugin API.
Learn more about LADSPA at http://www.ladspa.org
You need a LADSPA-aware host program to use these plugins.
I recommend using Ardour, which is a professional multichannel hard
disc recorder and digital audio workstation for Linux. These plugins
were developed and tested using Ardour, but they should work with any
LADSPA-capable host. Learn more about Ardour at http://ardour.org
Installation and usage of the plugins is very simple. Please take a
moment to edit the top of the Makefile if you wish to install the
plugins in a directory other than /usr/local/lib/ladspa (the default
place for plugins). A destination directory for RDF metadata is also
set there (defaults to /usr/local/share/ladspa/rdf) which you may also
want to change. Then run "make" and (as root) "make install". No
special packages are needed to compile these plugins, so there is no
./configure script.
A thorough manual is provided in html format. It is identical to the
project website. There is no need to save that manually, though: it is
provided as a separate package called tap-plugins-doc. After
downloading and untarring it, just open index.html with your favorite
Any Browser to view it.
Questions, comments, suggestions, bugreports and fixes are always
welcome at: <tszilagyi@users.sourceforge.net>
Have fun, turn up the volume and kick the shit out of your neighbours!

View File

@@ -1,361 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
Patches were received from:
Alexander Koenig <alex@lisas.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_autopan.c,v 1.6 2004/02/21 17:33:36 tszilagyi Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ladspa.h>
#include "tap_utils.h"
/* The Unique ID of the plugin: */
#define ID_STEREO 2146
/* The port numbers for the plugin: */
#define CONTROL_FREQ 0
#define CONTROL_DEPTH 1
#define CONTROL_GAIN 2
#define INPUT_L 3
#define INPUT_R 4
#define OUTPUT_L 5
#define OUTPUT_R 6
/* Total number of ports */
#define PORTCOUNT_STEREO 7
/* cosine table for fast computations */
LADSPA_Data cos_table[1024];
/* The structure used to hold port connection information and state */
typedef struct {
LADSPA_Data * freq;
LADSPA_Data * depth;
LADSPA_Data * gain;
LADSPA_Data * input_L;
LADSPA_Data * input_R;
LADSPA_Data * output_L;
LADSPA_Data * output_R;
unsigned long SampleRate;
LADSPA_Data Phase;
LADSPA_Data run_adding_gain;
} AutoPan;
/* Construct a new plugin instance. */
LADSPA_Handle
instantiate_AutoPan(const LADSPA_Descriptor * Descriptor,
unsigned long SampleRate) {
LADSPA_Handle * ptr;
if ((ptr = malloc(sizeof(AutoPan))) != NULL) {
((AutoPan *)ptr)->SampleRate = SampleRate;
((AutoPan *)ptr)->run_adding_gain = 1.0;
return ptr;
}
return NULL;
}
void
activate_AutoPan(LADSPA_Handle Instance) {
AutoPan * ptr;
ptr = (AutoPan *)Instance;
ptr->Phase = 0.0f;
}
/* Connect a port to a data location. */
void
connect_port_AutoPan(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * DataLocation) {
AutoPan * ptr;
ptr = (AutoPan *)Instance;
switch (Port) {
case CONTROL_FREQ:
ptr->freq = DataLocation;
break;
case CONTROL_DEPTH:
ptr->depth = DataLocation;
break;
case CONTROL_GAIN:
ptr->gain = DataLocation;
break;
case INPUT_L:
ptr->input_L = DataLocation;
break;
case INPUT_R:
ptr->input_R = DataLocation;
break;
case OUTPUT_L:
ptr->output_L = DataLocation;
break;
case OUTPUT_R:
ptr->output_R = DataLocation;
break;
}
}
void
run_AutoPan(LADSPA_Handle Instance,
unsigned long SampleCount) {
AutoPan * ptr = (AutoPan *)Instance;
LADSPA_Data * input_L = ptr->input_L;
LADSPA_Data * input_R = ptr->input_R;
LADSPA_Data * output_L = ptr->output_L;
LADSPA_Data * output_R = ptr->output_R;
LADSPA_Data freq = LIMIT(*(ptr->freq),0.0f,20.0f);
LADSPA_Data depth = LIMIT(*(ptr->depth),0.0f,100.0f);
LADSPA_Data gain = db2lin(LIMIT(*(ptr->gain),-70.0f,20.0f));
unsigned long sample_index;
LADSPA_Data phase_L = 0;
LADSPA_Data phase_R = 0;
for (sample_index = 0; sample_index < SampleCount; sample_index++) {
phase_L = 1024.0f * freq * sample_index / ptr->SampleRate + ptr->Phase;
while (phase_L >= 1024.0f)
phase_L -= 1024.0f;
phase_R = phase_L + 512.0f;
while (phase_R >= 1024.0f)
phase_R -= 1024.0f;
*(output_L++) = *(input_L++) * gain *
(1 - 0.5*depth/100 + 0.5 * depth/100 * cos_table[(unsigned long) phase_L]);
*(output_R++) = *(input_R++) * gain *
(1 - 0.5*depth/100 + 0.5 * depth/100 * cos_table[(unsigned long) phase_R]);
}
ptr->Phase = phase_L;
while (ptr->Phase >= 1024.0f)
ptr->Phase -= 1024.0f;
}
void
set_run_adding_gain_AutoPan(LADSPA_Handle Instance, LADSPA_Data gain) {
AutoPan * ptr;
ptr = (AutoPan *)Instance;
ptr->run_adding_gain = gain;
}
void
run_adding_AutoPan(LADSPA_Handle Instance,
unsigned long SampleCount) {
AutoPan * ptr = (AutoPan *)Instance;
LADSPA_Data * input_L = ptr->input_L;
LADSPA_Data * input_R = ptr->input_R;
LADSPA_Data * output_L = ptr->output_L;
LADSPA_Data * output_R = ptr->output_R;
LADSPA_Data freq = LIMIT(*(ptr->freq),0.0f,20.0f);
LADSPA_Data depth = LIMIT(*(ptr->depth),0.0f,100.0f);
LADSPA_Data gain = db2lin(LIMIT(*(ptr->gain),-70.0f,20.0f));
unsigned long sample_index;
LADSPA_Data phase_L = 0;
LADSPA_Data phase_R = 0;
for (sample_index = 0; sample_index < SampleCount; sample_index++) {
phase_L = 1024.0f * freq * sample_index / ptr->SampleRate + ptr->Phase;
while (phase_L >= 1024.0f)
phase_L -= 1024.0f;
phase_R = phase_L + 512.0f;
while (phase_R >= 1024.0f)
phase_R -= 1024.0f;
*(output_L++) += *(input_L++) * gain * ptr->run_adding_gain *
(1 - 0.5*depth/100 + 0.5 * depth/100 * cos_table[(unsigned long) phase_L]);
*(output_R++) += *(input_R++) * gain * ptr->run_adding_gain *
(1 - 0.5*depth/100 + 0.5 * depth/100 * cos_table[(unsigned long) phase_R]);
}
ptr->Phase = phase_L;
while (ptr->Phase >= 1024.0f)
ptr->Phase -= 1024.0f;
}
/* Throw away an AutoPan effect instance. */
void
cleanup_AutoPan(LADSPA_Handle Instance) {
free(Instance);
}
LADSPA_Descriptor * mono_descriptor = NULL;
/* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
loaded. */
void
__attribute__((constructor)) tap_init() {
int i;
char ** port_names;
LADSPA_PortDescriptor * port_descriptors;
LADSPA_PortRangeHint * port_range_hints;
if ((mono_descriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
exit(1);
for (i = 0; i < 1024; i++)
cos_table[i] = cosf(i * M_PI / 512.0f);
mono_descriptor->UniqueID = ID_STEREO;
mono_descriptor->Label = strdup("tap_autopan");
mono_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
mono_descriptor->Name = strdup("TAP AutoPanner");
mono_descriptor->Maker = strdup("Tom Szilagyi");
mono_descriptor->Copyright = strdup("GPL");
mono_descriptor->PortCount = PORTCOUNT_STEREO;
if ((port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortDescriptor))) == NULL)
exit(1);
mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
port_descriptors[CONTROL_FREQ] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[CONTROL_DEPTH] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[CONTROL_GAIN] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[INPUT_L] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[INPUT_R] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT_L] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT_R] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
if ((port_names =
(char **)calloc(PORTCOUNT_STEREO, sizeof(char *))) == NULL)
exit(1);
mono_descriptor->PortNames = (const char **)port_names;
port_names[CONTROL_FREQ] = strdup("Frequency [Hz]");
port_names[CONTROL_DEPTH] = strdup("Depth [%]");
port_names[CONTROL_GAIN] = strdup("Gain [dB]");
port_names[INPUT_L] = strdup("Input L");
port_names[INPUT_R] = strdup("Input R");
port_names[OUTPUT_L] = strdup("Output L");
port_names[OUTPUT_R] = strdup("Output R");
if ((port_range_hints =
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortRangeHint)))) == NULL)
exit(1);
mono_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
port_range_hints[CONTROL_FREQ].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[CONTROL_DEPTH].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[CONTROL_GAIN].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[CONTROL_FREQ].LowerBound = 0;
port_range_hints[CONTROL_FREQ].UpperBound = 20;
port_range_hints[CONTROL_DEPTH].LowerBound = 0;
port_range_hints[CONTROL_DEPTH].UpperBound = 100;
port_range_hints[CONTROL_GAIN].LowerBound = -70;
port_range_hints[CONTROL_GAIN].UpperBound = 20;
port_range_hints[INPUT_L].HintDescriptor = 0;
port_range_hints[INPUT_R].HintDescriptor = 0;
port_range_hints[OUTPUT_L].HintDescriptor = 0;
port_range_hints[OUTPUT_R].HintDescriptor = 0;
mono_descriptor->instantiate = instantiate_AutoPan;
mono_descriptor->connect_port = connect_port_AutoPan;
mono_descriptor->activate = activate_AutoPan;
mono_descriptor->run = run_AutoPan;
mono_descriptor->run_adding = run_adding_AutoPan;
mono_descriptor->set_run_adding_gain = set_run_adding_gain_AutoPan;
mono_descriptor->deactivate = NULL;
mono_descriptor->cleanup = cleanup_AutoPan;
}
void
delete_descriptor(LADSPA_Descriptor * descriptor) {
unsigned long index;
if (descriptor) {
free((char *)descriptor->Label);
free((char *)descriptor->Name);
free((char *)descriptor->Maker);
free((char *)descriptor->Copyright);
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
for (index = 0; index < descriptor->PortCount; index++)
free((char *)(descriptor->PortNames[index]));
free((char **)descriptor->PortNames);
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
free(descriptor);
}
}
/* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
void
__attribute__((destructor)) tap_fini() {
delete_descriptor(mono_descriptor);
}
/* Return a descriptor of the requested plugin type. */
const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index) {
switch (Index) {
case 0:
return mono_descriptor;
default:
return NULL;
}
}

View File

@@ -1,595 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_chorusflanger.c,v 1.3 2004/08/17 09:15:21 tszilagyi Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <ladspa.h>
#include "tap_utils.h"
/* The Unique ID of the plugin: */
#define ID_STEREO 2159
/* The port numbers for the plugin: */
#define FREQ 0
#define PHASE 1
#define DEPTH 2
#define DELAY 3
#define CONTOUR 4
#define DRYLEVEL 5
#define WETLEVEL 6
#define INPUT_L 7
#define INPUT_R 8
#define OUTPUT_L 9
#define OUTPUT_R 10
/* Total number of ports */
#define PORTCOUNT_STEREO 11
/*
* Largest buffer lengths needed (at 192 kHz).
* These are summed up to determine the size of *one* buffer per channel.
*/
#define DEPTH_BUFLEN 450
#define DELAY_BUFLEN 19200
/* Max. frequency setting */
#define MAX_FREQ 5.0f
/* bandwidth of highpass filters (in octaves) */
#define HP_BW 1
/* cosine table for fast computations */
#define COS_TABLE_SIZE 1024
LADSPA_Data cos_table[COS_TABLE_SIZE];
/* The structure used to hold port connection information and state */
typedef struct {
LADSPA_Data * freq;
LADSPA_Data * phase;
LADSPA_Data * depth;
LADSPA_Data * delay;
LADSPA_Data * contour;
LADSPA_Data * drylevel;
LADSPA_Data * wetlevel;
LADSPA_Data * input_L;
LADSPA_Data * input_R;
LADSPA_Data * output_L;
LADSPA_Data * output_R;
LADSPA_Data * ring_L;
unsigned long buflen_L;
unsigned long pos_L;
LADSPA_Data * ring_R;
unsigned long buflen_R;
unsigned long pos_R;
biquad highpass_L;
biquad highpass_R;
float cm_phase;
float dm_phase;
unsigned long sample_rate;
LADSPA_Data run_adding_gain;
} ChorusFlanger;
/* Construct a new plugin instance. */
LADSPA_Handle
instantiate_ChorusFlanger(const LADSPA_Descriptor * Descriptor,
unsigned long sample_rate) {
LADSPA_Handle * ptr;
if ((ptr = malloc(sizeof(ChorusFlanger))) != NULL) {
((ChorusFlanger *)ptr)->sample_rate = sample_rate;
((ChorusFlanger *)ptr)->run_adding_gain = 1.0f;
if ((((ChorusFlanger *)ptr)->ring_L =
calloc((DEPTH_BUFLEN + DELAY_BUFLEN) * sample_rate / 192000,
sizeof(LADSPA_Data))) == NULL)
return NULL;
((ChorusFlanger *)ptr)->buflen_L = (DEPTH_BUFLEN + DELAY_BUFLEN) * sample_rate / 192000;
((ChorusFlanger *)ptr)->pos_L = 0;
if ((((ChorusFlanger *)ptr)->ring_R =
calloc((DEPTH_BUFLEN + DELAY_BUFLEN) * sample_rate / 192000,
sizeof(LADSPA_Data))) == NULL)
return NULL;
((ChorusFlanger *)ptr)->buflen_R = (DEPTH_BUFLEN + DELAY_BUFLEN) * sample_rate / 192000;
((ChorusFlanger *)ptr)->pos_R = 0;
((ChorusFlanger *)ptr)->cm_phase = 0.0f;
((ChorusFlanger *)ptr)->dm_phase = 0.0f;
return ptr;
}
return NULL;
}
void
activate_ChorusFlanger(LADSPA_Handle Instance) {
ChorusFlanger * ptr = (ChorusFlanger *)Instance;
unsigned long i;
for (i = 0; i < (DEPTH_BUFLEN + DELAY_BUFLEN) * ptr->sample_rate / 192000; i++) {
ptr->ring_L[i] = 0.0f;
ptr->ring_R[i] = 0.0f;
}
biquad_init(&ptr->highpass_L);
biquad_init(&ptr->highpass_R);
}
/* Connect a port to a data location. */
void
connect_port_ChorusFlanger(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * data) {
ChorusFlanger * ptr = (ChorusFlanger *)Instance;
switch (Port) {
case FREQ:
ptr->freq = data;
break;
case PHASE:
ptr->phase = data;
break;
case DEPTH:
ptr->depth = data;
break;
case DELAY:
ptr->delay = data;
break;
case CONTOUR:
ptr->contour = data;
break;
case DRYLEVEL:
ptr->drylevel = data;
break;
case WETLEVEL:
ptr->wetlevel = data;
break;
case INPUT_L:
ptr->input_L = data;
break;
case INPUT_R:
ptr->input_R = data;
break;
case OUTPUT_L:
ptr->output_L = data;
break;
case OUTPUT_R:
ptr->output_R = data;
break;
}
}
void
run_ChorusFlanger(LADSPA_Handle Instance,
unsigned long SampleCount) {
ChorusFlanger * ptr = (ChorusFlanger *)Instance;
LADSPA_Data freq = LIMIT(*(ptr->freq), 0.0f, MAX_FREQ);
LADSPA_Data phase = LIMIT(*(ptr->phase), 0.0f, 180.0f) / 180.0f;
LADSPA_Data depth = 100.0f * ptr->sample_rate / 44100.0f
* LIMIT(*(ptr->depth),0.0f,100.0f) / 100.0f;
LADSPA_Data delay = LIMIT(*(ptr->delay),0.0f,100.0f);
LADSPA_Data contour = LIMIT(*(ptr->contour), 20.0f, 20000.0f);
LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
LADSPA_Data wetlevel = db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
LADSPA_Data * input_L = ptr->input_L;
LADSPA_Data * input_R = ptr->input_R;
LADSPA_Data * output_L = ptr->output_L;
LADSPA_Data * output_R = ptr->output_R;
unsigned long sample_index;
unsigned long sample_count = SampleCount;
LADSPA_Data in_L = 0.0f;
LADSPA_Data in_R = 0.0f;
LADSPA_Data d_L = 0.0f;
LADSPA_Data d_R = 0.0f;
LADSPA_Data f_L = 0.0f;
LADSPA_Data f_R = 0.0f;
LADSPA_Data out_L = 0.0f;
LADSPA_Data out_R = 0.0f;
float phase_L = 0.0f;
float phase_R = 0.0f;
float fpos_L = 0.0f;
float fpos_R = 0.0f;
float n_L = 0.0f;
float n_R = 0.0f;
float rem_L = 0.0f;
float rem_R = 0.0f;
float s_a_L, s_a_R, s_b_L, s_b_R;
float d_pos = 0.0f;
if (delay < 1.0f)
delay = 1.0f;
delay = 100.0f - delay;
hp_set_params(&ptr->highpass_L, contour, HP_BW, ptr->sample_rate);
hp_set_params(&ptr->highpass_R, contour, HP_BW, ptr->sample_rate);
for (sample_index = 0; sample_index < sample_count; sample_index++) {
in_L = *(input_L++);
in_R = *(input_R++);
push_buffer(in_L, ptr->ring_L, ptr->buflen_L, &(ptr->pos_L));
push_buffer(in_R, ptr->ring_R, ptr->buflen_R, &(ptr->pos_R));
ptr->cm_phase += freq / ptr->sample_rate * COS_TABLE_SIZE;
while (ptr->cm_phase >= COS_TABLE_SIZE)
ptr->cm_phase -= COS_TABLE_SIZE;
ptr->dm_phase = phase * COS_TABLE_SIZE / 2.0f;
phase_L = ptr->cm_phase;
phase_R = ptr->cm_phase + ptr->dm_phase;
while (phase_R >= COS_TABLE_SIZE)
phase_R -= COS_TABLE_SIZE;
d_pos = delay * ptr->sample_rate / 1000.0f;
fpos_L = d_pos + depth * (0.5f + 0.5f * cos_table[(unsigned long)phase_L]);
fpos_R = d_pos + depth * (0.5f + 0.5f * cos_table[(unsigned long)phase_R]);
n_L = floorf(fpos_L);
n_R = floorf(fpos_R);
rem_L = fpos_L - n_L;
rem_R = fpos_R - n_R;
s_a_L = read_buffer(ptr->ring_L, ptr->buflen_L,
ptr->pos_L, (unsigned long) n_L);
s_b_L = read_buffer(ptr->ring_L, ptr->buflen_L,
ptr->pos_L, (unsigned long) n_L + 1);
s_a_R = read_buffer(ptr->ring_R, ptr->buflen_R,
ptr->pos_R, (unsigned long) n_R);
s_b_R = read_buffer(ptr->ring_R, ptr->buflen_R,
ptr->pos_R, (unsigned long) n_R + 1);
d_L = ((1 - rem_L) * s_a_L + rem_L * s_b_L);
d_R = ((1 - rem_R) * s_a_R + rem_R * s_b_R);
f_L = biquad_run(&ptr->highpass_L, d_L);
f_R = biquad_run(&ptr->highpass_R, d_R);
out_L = drylevel * in_L + wetlevel * f_L;
out_R = drylevel * in_R + wetlevel * f_R;
*(output_L++) = out_L;
*(output_R++) = out_R;
}
}
void
set_run_adding_gain_ChorusFlanger(LADSPA_Handle Instance, LADSPA_Data gain) {
ChorusFlanger * ptr = (ChorusFlanger *)Instance;
ptr->run_adding_gain = gain;
}
void
run_adding_ChorusFlanger(LADSPA_Handle Instance,
unsigned long SampleCount) {
ChorusFlanger * ptr = (ChorusFlanger *)Instance;
LADSPA_Data freq = LIMIT(*(ptr->freq), 0.0f, MAX_FREQ);
LADSPA_Data phase = LIMIT(*(ptr->phase), 0.0f, 180.0f) / 180.0f;
LADSPA_Data depth = 100.0f * ptr->sample_rate / 44100.0f
* LIMIT(*(ptr->depth),0.0f,100.0f) / 100.0f;
LADSPA_Data delay = LIMIT(*(ptr->delay),0.0f,100.0f);
LADSPA_Data contour = LIMIT(*(ptr->contour), 20.0f, 20000.0f);
LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
LADSPA_Data wetlevel = db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
LADSPA_Data * input_L = ptr->input_L;
LADSPA_Data * input_R = ptr->input_R;
LADSPA_Data * output_L = ptr->output_L;
LADSPA_Data * output_R = ptr->output_R;
unsigned long sample_index;
unsigned long sample_count = SampleCount;
LADSPA_Data in_L = 0.0f;
LADSPA_Data in_R = 0.0f;
LADSPA_Data d_L = 0.0f;
LADSPA_Data d_R = 0.0f;
LADSPA_Data f_L = 0.0f;
LADSPA_Data f_R = 0.0f;
LADSPA_Data out_L = 0.0f;
LADSPA_Data out_R = 0.0f;
float phase_L = 0.0f;
float phase_R = 0.0f;
float fpos_L = 0.0f;
float fpos_R = 0.0f;
float n_L = 0.0f;
float n_R = 0.0f;
float rem_L = 0.0f;
float rem_R = 0.0f;
float s_a_L, s_a_R, s_b_L, s_b_R;
float d_pos = 0.0f;
if (delay < 1.0f)
delay = 1.0f;
delay = 100.0f - delay;
hp_set_params(&ptr->highpass_L, contour, HP_BW, ptr->sample_rate);
hp_set_params(&ptr->highpass_R, contour, HP_BW, ptr->sample_rate);
for (sample_index = 0; sample_index < sample_count; sample_index++) {
in_L = *(input_L++);
in_R = *(input_R++);
push_buffer(in_L, ptr->ring_L, ptr->buflen_L, &(ptr->pos_L));
push_buffer(in_R, ptr->ring_R, ptr->buflen_R, &(ptr->pos_R));
ptr->cm_phase += freq / ptr->sample_rate * COS_TABLE_SIZE;
while (ptr->cm_phase >= COS_TABLE_SIZE)
ptr->cm_phase -= COS_TABLE_SIZE;
ptr->dm_phase = phase * COS_TABLE_SIZE / 2.0f;
phase_L = ptr->cm_phase;
phase_R = ptr->cm_phase + ptr->dm_phase;
while (phase_R >= COS_TABLE_SIZE)
phase_R -= COS_TABLE_SIZE;
d_pos = delay * ptr->sample_rate / 1000.0f;
fpos_L = d_pos + depth * (0.5f + 0.5f * cos_table[(unsigned long)phase_L]);
fpos_R = d_pos + depth * (0.5f + 0.5f * cos_table[(unsigned long)phase_R]);
n_L = floorf(fpos_L);
n_R = floorf(fpos_R);
rem_L = fpos_L - n_L;
rem_R = fpos_R - n_R;
s_a_L = read_buffer(ptr->ring_L, ptr->buflen_L,
ptr->pos_L, (unsigned long) n_L);
s_b_L = read_buffer(ptr->ring_L, ptr->buflen_L,
ptr->pos_L, (unsigned long) n_L + 1);
s_a_R = read_buffer(ptr->ring_R, ptr->buflen_R,
ptr->pos_R, (unsigned long) n_R);
s_b_R = read_buffer(ptr->ring_R, ptr->buflen_R,
ptr->pos_R, (unsigned long) n_R + 1);
d_L = ((1 - rem_L) * s_a_L + rem_L * s_b_L);
d_R = ((1 - rem_R) * s_a_R + rem_R * s_b_R);
f_L = biquad_run(&ptr->highpass_L, d_L);
f_R = biquad_run(&ptr->highpass_R, d_R);
out_L = drylevel * in_L + wetlevel * f_L;
out_R = drylevel * in_R + wetlevel * f_R;
*(output_L++) += ptr->run_adding_gain * out_L;
*(output_R++) += ptr->run_adding_gain * out_R;
}
}
/* Throw away a ChorusFlanger effect instance. */
void
cleanup_ChorusFlanger(LADSPA_Handle Instance) {
ChorusFlanger * ptr = (ChorusFlanger *)Instance;
free(ptr->ring_L);
free(ptr->ring_R);
free(Instance);
}
LADSPA_Descriptor * stereo_descriptor = NULL;
/* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
loaded. */
void
__attribute__((constructor)) tap_init() {
char ** port_names;
LADSPA_PortDescriptor * port_descriptors;
LADSPA_PortRangeHint * port_range_hints;
int i;
if ((stereo_descriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
exit(1);
for (i = 0; i < COS_TABLE_SIZE; i++)
cos_table[i] = cosf(i * 2.0f * M_PI / COS_TABLE_SIZE);
stereo_descriptor->UniqueID = ID_STEREO;
stereo_descriptor->Label = strdup("tap_chorusflanger");
stereo_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
stereo_descriptor->Name = strdup("TAP Chorus/Flanger");
stereo_descriptor->Maker = strdup("Tom Szilagyi");
stereo_descriptor->Copyright = strdup("GPL");
stereo_descriptor->PortCount = PORTCOUNT_STEREO;
if ((port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortDescriptor))) == NULL)
exit(1);
stereo_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
port_descriptors[FREQ] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[PHASE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[DEPTH] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[DELAY] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[CONTOUR] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[DRYLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[WETLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[INPUT_L] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[INPUT_R] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT_L] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT_R] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
if ((port_names =
(char **)calloc(PORTCOUNT_STEREO, sizeof(char *))) == NULL)
exit(1);
stereo_descriptor->PortNames = (const char **)port_names;
port_names[FREQ] = strdup("Frequency [Hz]");
port_names[PHASE] = strdup("L/R Phase Shift [deg]");
port_names[DEPTH] = strdup("Depth [%]");
port_names[DELAY] = strdup("Delay [ms]");
port_names[CONTOUR] = strdup("Contour [Hz]");
port_names[DRYLEVEL] = strdup("Dry Level [dB]");
port_names[WETLEVEL] = strdup("Wet Level [dB]");
port_names[INPUT_L] = strdup("Input_L");
port_names[INPUT_R] = strdup("Input_R");
port_names[OUTPUT_L] = strdup("Output_L");
port_names[OUTPUT_R] = strdup("Output_R");
if ((port_range_hints =
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortRangeHint)))) == NULL)
exit(1);
stereo_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
port_range_hints[FREQ].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_LOW);
port_range_hints[PHASE].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MIDDLE);
port_range_hints[DEPTH].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_HIGH);
port_range_hints[DELAY].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_LOW);
port_range_hints[CONTOUR].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_100);
port_range_hints[DRYLEVEL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[WETLEVEL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[FREQ].LowerBound = 0.0f;
port_range_hints[FREQ].UpperBound = MAX_FREQ;
port_range_hints[PHASE].LowerBound = 0.0f;
port_range_hints[PHASE].UpperBound = 180.0f;
port_range_hints[DEPTH].LowerBound = 0.0f;
port_range_hints[DEPTH].UpperBound = 100.0f;
port_range_hints[DELAY].LowerBound = 0.0f;
port_range_hints[DELAY].UpperBound = 100.0f;
port_range_hints[CONTOUR].LowerBound = 20.0f;
port_range_hints[CONTOUR].UpperBound = 20000.0f;
port_range_hints[DRYLEVEL].LowerBound = -90.0f;
port_range_hints[DRYLEVEL].UpperBound = +20.0f;
port_range_hints[WETLEVEL].LowerBound = -90.0f;
port_range_hints[WETLEVEL].UpperBound = +20.0f;
port_range_hints[INPUT_L].HintDescriptor = 0;
port_range_hints[INPUT_R].HintDescriptor = 0;
port_range_hints[OUTPUT_L].HintDescriptor = 0;
port_range_hints[OUTPUT_R].HintDescriptor = 0;
stereo_descriptor->instantiate = instantiate_ChorusFlanger;
stereo_descriptor->connect_port = connect_port_ChorusFlanger;
stereo_descriptor->activate = activate_ChorusFlanger;
stereo_descriptor->run = run_ChorusFlanger;
stereo_descriptor->run_adding = run_adding_ChorusFlanger;
stereo_descriptor->set_run_adding_gain = set_run_adding_gain_ChorusFlanger;
stereo_descriptor->deactivate = NULL;
stereo_descriptor->cleanup = cleanup_ChorusFlanger;
}
void
delete_descriptor(LADSPA_Descriptor * descriptor) {
unsigned long index;
if (descriptor) {
free((char *)descriptor->Label);
free((char *)descriptor->Name);
free((char *)descriptor->Maker);
free((char *)descriptor->Copyright);
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
for (index = 0; index < descriptor->PortCount; index++)
free((char *)(descriptor->PortNames[index]));
free((char **)descriptor->PortNames);
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
free(descriptor);
}
}
/* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
void
__attribute__((destructor)) tap_fini() {
delete_descriptor(stereo_descriptor);
}
/* Return a descriptor of the requested plugin type. */
const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index) {
switch (Index) {
case 0:
return stereo_descriptor;
default:
return NULL;
}
}

View File

@@ -1,491 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_deesser.c,v 1.7 2004/05/01 16:15:06 tszilagyi Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ladspa.h>
#include "tap_utils.h"
/* The Unique ID of the plugin: */
#define ID_MONO 2147
/* The port numbers for the plugin: */
#define THRESHOLD 0
#define FREQ 1
#define SIDECHAIN 2
#define MONITOR 3
#define ATTENUAT 4
#define INPUT 5
#define OUTPUT 6
/* Total number of ports */
#define PORTCOUNT_MONO 7
/* Bandwidth of sidechain lowpass/highpass filters */
#define SIDECH_BW 0.3f
/* Used to hold 10 ms gain data, enough for sample rates up to 192 kHz */
#define RINGBUF_SIZE 2000
/* 4 digits precision from 1.000 to 9.999 */
LADSPA_Data log10_table[9000];
/* The structure used to hold port connection information and state */
typedef struct {
LADSPA_Data * threshold;
LADSPA_Data * audiomode;
LADSPA_Data * freq;
LADSPA_Data * sidechain;
LADSPA_Data * monitor;
LADSPA_Data * attenuat;
LADSPA_Data * input;
LADSPA_Data * output;
biquad sidech_lo_filter;
biquad sidech_hi_filter;
LADSPA_Data * ringbuffer;
unsigned long buflen;
unsigned long pos;
LADSPA_Data sum;
LADSPA_Data old_freq;
unsigned long sample_rate;
LADSPA_Data run_adding_gain;
} DeEsser;
/* fast linear to decibel conversion using log10_table[] */
LADSPA_Data fast_lin2db(LADSPA_Data lin) {
unsigned long k;
int exp = 0;
LADSPA_Data mant = ABS(lin);
/* sanity checks */
if (mant == 0.0f)
return(-1.0f/0.0f); /* -inf */
if (mant == 1.0f/0.0f) /* +inf */
return(mant);
while (mant < 1.0f) {
mant *= 10;
exp --;
}
while (mant >= 10.0f) {
mant /= 10;
exp ++;
}
k = (mant - 0.999999f) * 1000.0f;
return 20.0f * (log10_table[k] + exp);
}
/* Construct a new plugin instance. */
LADSPA_Handle
instantiate_DeEsser(const LADSPA_Descriptor * Descriptor,
unsigned long SampleRate) {
LADSPA_Handle * ptr;
if ((ptr = malloc(sizeof(DeEsser))) != NULL) {
((DeEsser *)ptr)->sample_rate = SampleRate;
((DeEsser *)ptr)->run_adding_gain = 1.0f;
/* init filters */
biquad_init(&((DeEsser *)ptr)->sidech_lo_filter);
biquad_init(&((DeEsser *)ptr)->sidech_hi_filter);
/* alloc mem for ringbuffer */
if ((((DeEsser *)ptr)->ringbuffer =
calloc(RINGBUF_SIZE, sizeof(LADSPA_Data))) == NULL)
return NULL;
/* 10 ms attenuation data is stored */
((DeEsser *)ptr)->buflen = ((DeEsser *)ptr)->sample_rate / 100;
((DeEsser *)ptr)->pos = 0;
((DeEsser *)ptr)->sum = 0.0f;
((DeEsser *)ptr)->old_freq = 0;
return ptr;
}
return NULL;
}
void
activate_DeEsser(LADSPA_Handle Instance) {
DeEsser * ptr = (DeEsser *)Instance;
unsigned long i;
for (i = 0; i < RINGBUF_SIZE; i++)
ptr->ringbuffer[i] = 0.0f;
}
/* Connect a port to a data location. */
void
connect_port_DeEsser(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * DataLocation) {
DeEsser * ptr;
ptr = (DeEsser *)Instance;
switch (Port) {
case THRESHOLD:
ptr->threshold = DataLocation;
break;
case FREQ:
ptr->freq = DataLocation;
break;
case SIDECHAIN:
ptr->sidechain = DataLocation;
break;
case MONITOR:
ptr->monitor = DataLocation;
break;
case ATTENUAT:
ptr->attenuat = DataLocation;
*(ptr->attenuat) = 0.0f;
break;
case INPUT:
ptr->input = DataLocation;
break;
case OUTPUT:
ptr->output = DataLocation;
break;
}
}
void
run_DeEsser(LADSPA_Handle Instance,
unsigned long SampleCount) {
DeEsser * ptr = (DeEsser *)Instance;
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
LADSPA_Data threshold = LIMIT(*(ptr->threshold),-50.0f,10.0f);
LADSPA_Data freq = LIMIT(*(ptr->freq),2000.0f,16000.0f);
LADSPA_Data sidechain = LIMIT(*(ptr->sidechain),0.0f,1.0f);
LADSPA_Data monitor = LIMIT(*(ptr->monitor),0.0f,1.0f);
unsigned long sample_index;
LADSPA_Data in = 0;
LADSPA_Data out = 0;
LADSPA_Data sidech = 0;
LADSPA_Data ampl_db = 0.0f;
LADSPA_Data attn = 0.0f;
LADSPA_Data max_attn = 0.0f;
if (ptr->old_freq != freq) {
lp_set_params(&ptr->sidech_lo_filter, freq, SIDECH_BW, ptr->sample_rate);
hp_set_params(&ptr->sidech_hi_filter, freq, SIDECH_BW, ptr->sample_rate);
ptr->old_freq = freq;
}
for (sample_index = 0; sample_index < SampleCount; sample_index++) {
in = *(input++);
/* process sidechain filters */
sidech = biquad_run(&ptr->sidech_hi_filter, in);
if (sidechain > 0.1f)
sidech = biquad_run(&ptr->sidech_lo_filter, sidech);
ampl_db = fast_lin2db(sidech);
if (ampl_db <= threshold)
attn = 0.0f;
else
attn = -0.5f * (ampl_db - threshold);
ptr->sum += attn;
ptr->sum -= push_buffer(attn, ptr->ringbuffer, ptr->buflen, &ptr->pos);
if (-1.0f * ptr->sum > max_attn)
max_attn = -0.01f * ptr->sum;
in *= db2lin(ptr->sum / 100.0f);
/* output selector */
if (monitor > 0.1f)
out = sidech;
else
out = in;
*(output++) = out;
*(ptr->attenuat) = LIMIT(max_attn,0,10);
}
}
void
set_run_adding_gain_DeEsser(LADSPA_Handle Instance, LADSPA_Data gain) {
DeEsser * ptr = (DeEsser *)Instance;
ptr->run_adding_gain = gain;
}
void
run_adding_DeEsser(LADSPA_Handle Instance,
unsigned long SampleCount) {
DeEsser * ptr = (DeEsser *)Instance;
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
LADSPA_Data threshold = LIMIT(*(ptr->threshold),-50.0f,10.0f);
LADSPA_Data freq = LIMIT(*(ptr->freq),2000.0f,16000.0f);
LADSPA_Data sidechain = LIMIT(*(ptr->sidechain),0.0f,1.0f);
LADSPA_Data monitor = LIMIT(*(ptr->monitor),0.0f,1.0f);
unsigned long sample_index;
LADSPA_Data in = 0;
LADSPA_Data out = 0;
LADSPA_Data sidech = 0;
LADSPA_Data ampl_db = 0.0f;
LADSPA_Data attn = 0.0f;
LADSPA_Data max_attn = 0.0f;
if (ptr->old_freq != freq) {
lp_set_params(&ptr->sidech_lo_filter, freq, SIDECH_BW, ptr->sample_rate);
hp_set_params(&ptr->sidech_hi_filter, freq, SIDECH_BW, ptr->sample_rate);
ptr->old_freq = freq;
}
for (sample_index = 0; sample_index < SampleCount; sample_index++) {
in = *(input++);
/* process sidechain filters */
sidech = biquad_run(&ptr->sidech_hi_filter, in);
if (sidechain > 0.1f)
sidech = biquad_run(&ptr->sidech_lo_filter, sidech);
ampl_db = 20.0f * log10f(sidech);
if (ampl_db <= threshold)
attn = 0.0f;
else
attn = -0.5f * (ampl_db - threshold);
ptr->sum += attn;
ptr->sum -= push_buffer(attn, ptr->ringbuffer, ptr->buflen, &ptr->pos);
if (-1.0f * ptr->sum > max_attn)
max_attn = -0.01f * ptr->sum;
in *= db2lin(ptr->sum / 100.0f);
/* output selector */
if (monitor > 0.1f)
out = sidech;
else
out = in;
*(output++) += ptr->run_adding_gain * out;
*(ptr->attenuat) = LIMIT(max_attn,0,10);
}
}
/* Throw away a DeEsser effect instance. */
void
cleanup_DeEsser(LADSPA_Handle Instance) {
DeEsser * ptr = (DeEsser *)Instance;
free(ptr->ringbuffer);
free(Instance);
}
LADSPA_Descriptor * mono_descriptor = NULL;
/* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
loaded. */
void
__attribute__((constructor)) tap_init() {
int i;
char ** port_names;
LADSPA_PortDescriptor * port_descriptors;
LADSPA_PortRangeHint * port_range_hints;
if ((mono_descriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
exit(1);
/* compute the log10 table */
for (i = 0; i < 9000; i++)
log10_table[i] = log10f(1.0f + i / 1000.0f);
mono_descriptor->UniqueID = ID_MONO;
mono_descriptor->Label = strdup("tap_deesser");
mono_descriptor->Properties = 0;
mono_descriptor->Name = strdup("TAP DeEsser");
mono_descriptor->Maker = strdup("Tom Szilagyi");
mono_descriptor->Copyright = strdup("GPL");
mono_descriptor->PortCount = PORTCOUNT_MONO;
if ((port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
exit(1);
mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
port_descriptors[THRESHOLD] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[FREQ] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[SIDECHAIN] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[MONITOR] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[ATTENUAT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
port_descriptors[INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
if ((port_names =
(char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
exit(1);
mono_descriptor->PortNames = (const char **)port_names;
port_names[THRESHOLD] = strdup("Threshold Level [dB]");
port_names[FREQ] = strdup("Frequency [Hz]");
port_names[SIDECHAIN] = strdup("Sidechain Filter");
port_names[MONITOR] = strdup("Monitor");
port_names[ATTENUAT] = strdup("Attenuation [dB]");
port_names[INPUT] = strdup("Input");
port_names[OUTPUT] = strdup("Output");
if ((port_range_hints =
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
exit(1);
mono_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
port_range_hints[THRESHOLD].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[FREQ].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_LOW);
port_range_hints[SIDECHAIN].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_INTEGER |
LADSPA_HINT_DEFAULT_0);
port_range_hints[MONITOR].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_INTEGER |
LADSPA_HINT_DEFAULT_0);
port_range_hints[ATTENUAT].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[THRESHOLD].LowerBound = -50;
port_range_hints[THRESHOLD].UpperBound = 10;
port_range_hints[FREQ].LowerBound = 2000;
port_range_hints[FREQ].UpperBound = 16000;
port_range_hints[SIDECHAIN].LowerBound = 0.0f;
port_range_hints[SIDECHAIN].UpperBound = 1.01f;
port_range_hints[MONITOR].LowerBound = 0.0f;
port_range_hints[MONITOR].UpperBound = 1.01f;
port_range_hints[ATTENUAT].LowerBound = 0.0f;
port_range_hints[ATTENUAT].UpperBound = 10.0f;
port_range_hints[INPUT].HintDescriptor = 0;
port_range_hints[OUTPUT].HintDescriptor = 0;
mono_descriptor->instantiate = instantiate_DeEsser;
mono_descriptor->connect_port = connect_port_DeEsser;
mono_descriptor->activate = activate_DeEsser;
mono_descriptor->run = run_DeEsser;
mono_descriptor->run_adding = run_adding_DeEsser;
mono_descriptor->set_run_adding_gain = set_run_adding_gain_DeEsser;
mono_descriptor->deactivate = NULL;
mono_descriptor->cleanup = cleanup_DeEsser;
}
void
delete_descriptor(LADSPA_Descriptor * descriptor) {
unsigned long index;
if (descriptor) {
free((char *)descriptor->Label);
free((char *)descriptor->Name);
free((char *)descriptor->Maker);
free((char *)descriptor->Copyright);
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
for (index = 0; index < descriptor->PortCount; index++)
free((char *)(descriptor->PortNames[index]));
free((char **)descriptor->PortNames);
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
free(descriptor);
}
}
/* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
void
__attribute__((destructor)) tap_fini() {
delete_descriptor(mono_descriptor);
}
/* Return a descriptor of the requested plugin type. */
const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index) {
switch (Index) {
case 0:
return mono_descriptor;
default:
return NULL;
}
}

View File

@@ -1,737 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_doubler.c,v 1.4 2004/08/13 18:34:31 tszilagyi Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <ladspa.h>
#include "tap_utils.h"
/* The Unique ID of the plugin: */
#define ID_STEREO 2156
/* The port numbers for the plugin: */
#define TIME 0
#define PITCH 1
#define DRYLEVEL 2
#define DRYPOSL 3
#define DRYPOSR 4
#define WETLEVEL 5
#define WETPOSL 6
#define WETPOSR 7
#define INPUT_L 8
#define INPUT_R 9
#define OUTPUT_L 10
#define OUTPUT_R 11
/* Total number of ports */
#define PORTCOUNT_STEREO 12
/* Number of pink noise samples to be generated at once */
#define NOISE_LEN 1024
/*
* Largest buffer length needed (at 192 kHz).
*/
#define BUFLEN 11520
/* The structure used to hold port connection information and state */
typedef struct {
LADSPA_Data * time;
LADSPA_Data * pitch;
LADSPA_Data * drylevel;
LADSPA_Data * dryposl;
LADSPA_Data * dryposr;
LADSPA_Data * wetlevel;
LADSPA_Data * wetposl;
LADSPA_Data * wetposr;
LADSPA_Data * input_L;
LADSPA_Data * input_R;
LADSPA_Data * output_L;
LADSPA_Data * output_R;
LADSPA_Data old_time;
LADSPA_Data old_pitch;
LADSPA_Data * ring_L;
unsigned long buflen_L;
unsigned long pos_L;
LADSPA_Data * ring_R;
unsigned long buflen_R;
unsigned long pos_R;
LADSPA_Data * ring_pnoise;
unsigned long buflen_pnoise;
unsigned long pos_pnoise;
LADSPA_Data * ring_dnoise;
unsigned long buflen_dnoise;
unsigned long pos_dnoise;
float delay;
float d_delay;
float p_delay;
unsigned long n_delay;
float pitchmod;
float d_pitch;
float p_pitch;
unsigned long n_pitch;
unsigned long p_stretch;
unsigned long d_stretch;
unsigned long sample_rate;
LADSPA_Data run_adding_gain;
} Doubler;
/* generate fractal pattern using Midpoint Displacement Method
* v: buffer of floats to output fractal pattern to
* N: length of v, MUST be integer power of 2 (ie 128, 256, ...)
* H: Hurst constant, between 0 and 0.9999 (fractal dimension)
*/
void
fractal(LADSPA_Data * v, int N, float H) {
int l = N;
int k;
float r = 1.0f;
int c;
v[0] = 0;
while (l > 1) {
k = N / l;
for (c = 0; c < k; c++) {
v[c*l + l/2] = (v[c*l] + v[((c+1) * l) % N]) / 2.0f +
2.0f * r * (rand() - (float)RAND_MAX/2.0f) / (float)RAND_MAX;
v[c*l + l/2] = LIMIT(v[c*l + l/2], -1.0f, 1.0f);
}
l /= 2;
r /= powf(2, H);
}
}
/* Construct a new plugin instance. */
LADSPA_Handle
instantiate_Doubler(const LADSPA_Descriptor * Descriptor,
unsigned long sample_rate) {
LADSPA_Handle * ptr;
if ((ptr = malloc(sizeof(Doubler))) != NULL) {
((Doubler *)ptr)->sample_rate = sample_rate;
((Doubler *)ptr)->run_adding_gain = 1.0f;
if ((((Doubler *)ptr)->ring_L =
calloc(BUFLEN * sample_rate / 192000, sizeof(LADSPA_Data))) == NULL)
return NULL;
((Doubler *)ptr)->buflen_L = BUFLEN * sample_rate / 192000;
((Doubler *)ptr)->pos_L = 0;
if ((((Doubler *)ptr)->ring_R =
calloc(BUFLEN * sample_rate / 192000, sizeof(LADSPA_Data))) == NULL)
return NULL;
((Doubler *)ptr)->buflen_R = BUFLEN * sample_rate / 192000;
((Doubler *)ptr)->pos_R = 0;
if ((((Doubler *)ptr)->ring_pnoise =
calloc(NOISE_LEN, sizeof(LADSPA_Data))) == NULL)
return NULL;
((Doubler *)ptr)->buflen_pnoise = NOISE_LEN;
((Doubler *)ptr)->pos_pnoise = 0;
if ((((Doubler *)ptr)->ring_dnoise =
calloc(NOISE_LEN, sizeof(LADSPA_Data))) == NULL)
return NULL;
((Doubler *)ptr)->buflen_dnoise = NOISE_LEN;
((Doubler *)ptr)->pos_dnoise = 0;
((Doubler *)ptr)->d_stretch = sample_rate / 10;
((Doubler *)ptr)->p_stretch = sample_rate / 1000;
((Doubler *)ptr)->delay = 0.0f;
((Doubler *)ptr)->d_delay = 0.0f;
((Doubler *)ptr)->p_delay = 0.0f;
((Doubler *)ptr)->n_delay = ((Doubler *)ptr)->d_stretch;
((Doubler *)ptr)->pitchmod = 0.0f;
((Doubler *)ptr)->d_pitch = 0.0f;
((Doubler *)ptr)->p_pitch = 0.0f;
((Doubler *)ptr)->n_pitch = ((Doubler *)ptr)->p_stretch;
return ptr;
}
return NULL;
}
void
activate_Doubler(LADSPA_Handle Instance) {
Doubler * ptr = (Doubler *)Instance;
unsigned long i;
for (i = 0; i < BUFLEN * ptr->sample_rate / 192000; i++) {
ptr->ring_L[i] = 0.0f;
ptr->ring_R[i] = 0.0f;
}
ptr->old_time = -1.0f;
ptr->old_pitch = -1.0f;
}
/* Connect a port to a data location. */
void
connect_port_Doubler(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * data) {
Doubler * ptr = (Doubler *)Instance;
switch (Port) {
case TIME:
ptr->time = data;
break;
case PITCH:
ptr->pitch = data;
break;
case DRYLEVEL:
ptr->drylevel = data;
break;
case DRYPOSL:
ptr->dryposl = data;
break;
case DRYPOSR:
ptr->dryposr = data;
break;
case WETLEVEL:
ptr->wetlevel = data;
break;
case WETPOSL:
ptr->wetposl = data;
break;
case WETPOSR:
ptr->wetposr = data;
break;
case INPUT_L:
ptr->input_L = data;
break;
case INPUT_R:
ptr->input_R = data;
break;
case OUTPUT_L:
ptr->output_L = data;
break;
case OUTPUT_R:
ptr->output_R = data;
break;
}
}
void
run_Doubler(LADSPA_Handle Instance,
unsigned long SampleCount) {
Doubler * ptr = (Doubler *)Instance;
LADSPA_Data pitch = LIMIT(*(ptr->pitch),0.0f,1.0f) + 0.75f;
LADSPA_Data depth = LIMIT(((1.0f - LIMIT(*(ptr->pitch),0.0f,1.0f)) * 1.75f + 0.25f) *
ptr->sample_rate / 6000.0f / M_PI,
0, ptr->buflen_L / 2);
LADSPA_Data time = LIMIT(*(ptr->time), 0.0f, 1.0f) + 0.5f;
LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
LADSPA_Data wetlevel = db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
LADSPA_Data dryposl = 1.0f - LIMIT(*(ptr->dryposl), 0.0f, 1.0f);
LADSPA_Data dryposr = LIMIT(*(ptr->dryposr), 0.0f, 1.0f);
LADSPA_Data wetposl = 1.0f - LIMIT(*(ptr->wetposl), 0.0f, 1.0f);
LADSPA_Data wetposr = LIMIT(*(ptr->wetposr), 0.0f, 1.0f);
LADSPA_Data * input_L = ptr->input_L;
LADSPA_Data * input_R = ptr->input_R;
LADSPA_Data * output_L = ptr->output_L;
LADSPA_Data * output_R = ptr->output_R;
unsigned long sample_index;
unsigned long sample_count = SampleCount;
LADSPA_Data in_L = 0.0f;
LADSPA_Data in_R = 0.0f;
LADSPA_Data out_L = 0.0f;
LADSPA_Data out_R = 0.0f;
LADSPA_Data fpos = 0.0f;
LADSPA_Data n = 0.0f;
LADSPA_Data rem = 0.0f;
LADSPA_Data s_a_L, s_a_R, s_b_L, s_b_R;
LADSPA_Data prev_p_pitch = 0.0f;
LADSPA_Data prev_p_delay = 0.0f;
LADSPA_Data delay;
LADSPA_Data drystream_L = 0.0f;
LADSPA_Data drystream_R = 0.0f;
LADSPA_Data wetstream_L = 0.0f;
LADSPA_Data wetstream_R = 0.0f;
if (ptr->old_pitch != pitch) {
ptr->pitchmod = ptr->p_pitch;
prev_p_pitch = ptr->p_pitch;
fractal(ptr->ring_pnoise, NOISE_LEN, pitch);
ptr->pos_pnoise = 0;
ptr->p_pitch = push_buffer(0.0f, ptr->ring_pnoise,
ptr->buflen_pnoise, &(ptr->pos_pnoise));
ptr->d_pitch = (ptr->p_pitch - prev_p_pitch) / (float)(ptr->p_stretch);
ptr->n_pitch = 0;
ptr->old_pitch = pitch;
}
if (ptr->old_time != time) {
ptr->delay = ptr->p_delay;
prev_p_delay = ptr->p_delay;
fractal(ptr->ring_dnoise, NOISE_LEN, time);
ptr->pos_dnoise = 0;
ptr->p_delay = push_buffer(0.0f, ptr->ring_dnoise,
ptr->buflen_dnoise, &(ptr->pos_dnoise));
ptr->d_delay = (ptr->p_delay - prev_p_delay) / (float)(ptr->d_stretch);
ptr->n_delay = 0;
ptr->old_time = time;
}
for (sample_index = 0; sample_index < sample_count; sample_index++) {
in_L = *(input_L++);
in_R = *(input_R++);
push_buffer(in_L, ptr->ring_L, ptr->buflen_L, &(ptr->pos_L));
push_buffer(in_R, ptr->ring_R, ptr->buflen_R, &(ptr->pos_R));
if (ptr->n_pitch < ptr->p_stretch) {
ptr->pitchmod += ptr->d_pitch;
ptr->n_pitch++;
} else {
ptr->pitchmod = ptr->p_pitch;
prev_p_pitch = ptr->p_pitch;
if (!ptr->pos_pnoise) {
fractal(ptr->ring_pnoise, NOISE_LEN, pitch);
}
ptr->p_pitch = push_buffer(0.0f, ptr->ring_pnoise,
ptr->buflen_pnoise, &(ptr->pos_pnoise));
ptr->d_pitch = (ptr->p_pitch - prev_p_pitch) / (float)(ptr->p_stretch);
ptr->n_pitch = 0;
}
if (ptr->n_delay < ptr->d_stretch) {
ptr->delay += ptr->d_delay;
ptr->n_delay++;
} else {
ptr->delay = ptr->p_delay;
prev_p_delay = ptr->p_delay;
if (!ptr->pos_dnoise) {
fractal(ptr->ring_dnoise, NOISE_LEN, time);
}
ptr->p_delay = push_buffer(0.0f, ptr->ring_dnoise,
ptr->buflen_dnoise, &(ptr->pos_dnoise));
ptr->d_delay = (ptr->p_delay - prev_p_delay) / (float)(ptr->d_stretch);
ptr->n_delay = 0;
}
delay = (12.5f * ptr->delay + 37.5f) * ptr->sample_rate / 1000.0f;
fpos = ptr->buflen_L - depth * (1.0f - ptr->pitchmod) - delay - 1.0f;
n = floorf(fpos);
rem = fpos - n;
s_a_L = read_buffer(ptr->ring_L, ptr->buflen_L,
ptr->pos_L, (unsigned long) n);
s_b_L = read_buffer(ptr->ring_L, ptr->buflen_L,
ptr->pos_L, (unsigned long) n + 1);
s_a_R = read_buffer(ptr->ring_R, ptr->buflen_R,
ptr->pos_R, (unsigned long) n);
s_b_R = read_buffer(ptr->ring_R, ptr->buflen_R,
ptr->pos_R, (unsigned long) n + 1);
drystream_L = drylevel * in_L;
drystream_R = drylevel * in_R;
wetstream_L = wetlevel * ((1 - rem) * s_a_L + rem * s_b_L);
wetstream_R = wetlevel * ((1 - rem) * s_a_R + rem * s_b_R);
out_L = dryposl * drystream_L + (1.0f - dryposr) * drystream_R +
wetposl * wetstream_L + (1.0f - wetposr) * wetstream_R;
out_R = (1.0f - dryposl) * drystream_L + dryposr * drystream_R +
(1.0f - wetposl) * wetstream_L + wetposr * wetstream_R;
*(output_L++) = out_L;
*(output_R++) = out_R;
}
}
void
set_run_adding_gain_Doubler(LADSPA_Handle Instance, LADSPA_Data gain) {
Doubler * ptr = (Doubler *)Instance;
ptr->run_adding_gain = gain;
}
void
run_adding_Doubler(LADSPA_Handle Instance,
unsigned long SampleCount) {
Doubler * ptr = (Doubler *)Instance;
LADSPA_Data pitch = LIMIT(*(ptr->pitch),0.0f,1.0f) + 0.75f;
LADSPA_Data depth = LIMIT(((1.0f - LIMIT(*(ptr->pitch),0.0f,1.0f)) * 1.75f + 0.25f) *
ptr->sample_rate / 6000.0f / M_PI,
0, ptr->buflen_L / 2);
LADSPA_Data time = LIMIT(*(ptr->time), 0.0f, 1.0f) + 0.5f;
LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
LADSPA_Data wetlevel = db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
LADSPA_Data dryposl = 1.0f - LIMIT(*(ptr->dryposl), 0.0f, 1.0f);
LADSPA_Data dryposr = LIMIT(*(ptr->dryposr), 0.0f, 1.0f);
LADSPA_Data wetposl = 1.0f - LIMIT(*(ptr->wetposl), 0.0f, 1.0f);
LADSPA_Data wetposr = LIMIT(*(ptr->wetposr), 0.0f, 1.0f);
LADSPA_Data * input_L = ptr->input_L;
LADSPA_Data * input_R = ptr->input_R;
LADSPA_Data * output_L = ptr->output_L;
LADSPA_Data * output_R = ptr->output_R;
unsigned long sample_index;
unsigned long sample_count = SampleCount;
LADSPA_Data in_L = 0.0f;
LADSPA_Data in_R = 0.0f;
LADSPA_Data out_L = 0.0f;
LADSPA_Data out_R = 0.0f;
LADSPA_Data fpos = 0.0f;
LADSPA_Data n = 0.0f;
LADSPA_Data rem = 0.0f;
LADSPA_Data s_a_L, s_a_R, s_b_L, s_b_R;
LADSPA_Data prev_p_pitch = 0.0f;
LADSPA_Data prev_p_delay = 0.0f;
LADSPA_Data delay;
LADSPA_Data drystream_L = 0.0f;
LADSPA_Data drystream_R = 0.0f;
LADSPA_Data wetstream_L = 0.0f;
LADSPA_Data wetstream_R = 0.0f;
if (ptr->old_pitch != pitch) {
ptr->pitchmod = ptr->p_pitch;
prev_p_pitch = ptr->p_pitch;
fractal(ptr->ring_pnoise, NOISE_LEN, pitch);
ptr->pos_pnoise = 0;
ptr->p_pitch = push_buffer(0.0f, ptr->ring_pnoise,
ptr->buflen_pnoise, &(ptr->pos_pnoise));
ptr->d_pitch = (ptr->p_pitch - prev_p_pitch) / (float)(ptr->p_stretch);
ptr->n_pitch = 0;
ptr->old_pitch = pitch;
}
if (ptr->old_time != time) {
ptr->delay = ptr->p_delay;
prev_p_delay = ptr->p_delay;
fractal(ptr->ring_dnoise, NOISE_LEN, time);
ptr->pos_dnoise = 0;
ptr->p_delay = push_buffer(0.0f, ptr->ring_dnoise,
ptr->buflen_dnoise, &(ptr->pos_dnoise));
ptr->d_delay = (ptr->p_delay - prev_p_delay) / (float)(ptr->d_stretch);
ptr->n_delay = 0;
ptr->old_time = time;
}
for (sample_index = 0; sample_index < sample_count; sample_index++) {
in_L = *(input_L++);
in_R = *(input_R++);
push_buffer(in_L, ptr->ring_L, ptr->buflen_L, &(ptr->pos_L));
push_buffer(in_R, ptr->ring_R, ptr->buflen_R, &(ptr->pos_R));
if (ptr->n_pitch < ptr->p_stretch) {
ptr->pitchmod += ptr->d_pitch;
ptr->n_pitch++;
} else {
ptr->pitchmod = ptr->p_pitch;
prev_p_pitch = ptr->p_pitch;
if (!ptr->pos_pnoise) {
fractal(ptr->ring_pnoise, NOISE_LEN, pitch);
}
ptr->p_pitch = push_buffer(0.0f, ptr->ring_pnoise,
ptr->buflen_pnoise, &(ptr->pos_pnoise));
ptr->d_pitch = (ptr->p_pitch - prev_p_pitch) / (float)(ptr->p_stretch);
ptr->n_pitch = 0;
}
if (ptr->n_delay < ptr->d_stretch) {
ptr->delay += ptr->d_delay;
ptr->n_delay++;
} else {
ptr->delay = ptr->p_delay;
prev_p_delay = ptr->p_delay;
if (!ptr->pos_dnoise) {
fractal(ptr->ring_dnoise, NOISE_LEN, time);
}
ptr->p_delay = push_buffer(0.0f, ptr->ring_dnoise,
ptr->buflen_dnoise, &(ptr->pos_dnoise));
ptr->d_delay = (ptr->p_delay - prev_p_delay) / (float)(ptr->d_stretch);
ptr->n_delay = 0;
}
delay = (12.5f * ptr->delay + 37.5f) * ptr->sample_rate / 1000.0f;
fpos = ptr->buflen_L - depth * (1.0f - ptr->pitchmod) - delay - 1.0f;
n = floorf(fpos);
rem = fpos - n;
s_a_L = read_buffer(ptr->ring_L, ptr->buflen_L,
ptr->pos_L, (unsigned long) n);
s_b_L = read_buffer(ptr->ring_L, ptr->buflen_L,
ptr->pos_L, (unsigned long) n + 1);
s_a_R = read_buffer(ptr->ring_R, ptr->buflen_R,
ptr->pos_R, (unsigned long) n);
s_b_R = read_buffer(ptr->ring_R, ptr->buflen_R,
ptr->pos_R, (unsigned long) n + 1);
drystream_L = drylevel * in_L;
drystream_R = drylevel * in_R;
wetstream_L = wetlevel * ((1 - rem) * s_a_L + rem * s_b_L);
wetstream_R = wetlevel * ((1 - rem) * s_a_R + rem * s_b_R);
out_L = dryposl * drystream_L + (1.0f - dryposr) * drystream_R +
wetposl * wetstream_L + (1.0f - wetposr) * wetstream_R;
out_R = (1.0f - dryposl) * drystream_L + dryposr * drystream_R +
(1.0f - wetposl) * wetstream_L + wetposr * wetstream_R;
*(output_L++) += ptr->run_adding_gain * out_L;
*(output_R++) += ptr->run_adding_gain * out_R;
}
}
/* Throw away a Doubler effect instance. */
void
cleanup_Doubler(LADSPA_Handle Instance) {
Doubler * ptr = (Doubler *)Instance;
free(ptr->ring_L);
free(ptr->ring_R);
free(ptr->ring_pnoise);
free(ptr->ring_dnoise);
free(Instance);
}
LADSPA_Descriptor * stereo_descriptor = NULL;
/* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
loaded. */
void
__attribute__((constructor)) tap_init() {
char ** port_names;
LADSPA_PortDescriptor * port_descriptors;
LADSPA_PortRangeHint * port_range_hints;
if ((stereo_descriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
exit(1);
stereo_descriptor->UniqueID = ID_STEREO;
stereo_descriptor->Label = strdup("tap_doubler");
stereo_descriptor->Properties = 0;
stereo_descriptor->Name = strdup("TAP Fractal Doubler");
stereo_descriptor->Maker = strdup("Tom Szilagyi");
stereo_descriptor->Copyright = strdup("GPL");
stereo_descriptor->PortCount = PORTCOUNT_STEREO;
if ((port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortDescriptor))) == NULL)
exit(1);
stereo_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
port_descriptors[TIME] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[PITCH] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[DRYLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[DRYPOSL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[DRYPOSR] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[WETLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[WETPOSL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[WETPOSR] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[INPUT_L] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[INPUT_R] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT_L] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT_R] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
if ((port_names =
(char **)calloc(PORTCOUNT_STEREO, sizeof(char *))) == NULL)
exit(1);
stereo_descriptor->PortNames = (const char **)port_names;
port_names[TIME] = strdup("Time Tracking");
port_names[PITCH] = strdup("Pitch Tracking");
port_names[DRYLEVEL] = strdup("Dry Level [dB]");
port_names[DRYPOSL] = strdup("Dry Left Position");
port_names[DRYPOSR] = strdup("Dry Right Position");
port_names[WETLEVEL] = strdup("Wet Level [dB]");
port_names[WETPOSL] = strdup("Wet Left Position");
port_names[WETPOSR] = strdup("Wet Right Position");
port_names[INPUT_L] = strdup("Input_L");
port_names[INPUT_R] = strdup("Input_R");
port_names[OUTPUT_L] = strdup("Output_L");
port_names[OUTPUT_R] = strdup("Output_R");
if ((port_range_hints =
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortRangeHint)))) == NULL)
exit(1);
stereo_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
port_range_hints[TIME].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MIDDLE);
port_range_hints[PITCH].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MIDDLE);
port_range_hints[DRYLEVEL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[DRYPOSL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MINIMUM);
port_range_hints[DRYPOSR].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MAXIMUM);
port_range_hints[WETLEVEL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[WETPOSL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MINIMUM);
port_range_hints[WETPOSR].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MAXIMUM);
port_range_hints[TIME].LowerBound = 0.0f;
port_range_hints[TIME].UpperBound = 1.0f;
port_range_hints[PITCH].LowerBound = 0.0f;
port_range_hints[PITCH].UpperBound = 1.0f;
port_range_hints[DRYLEVEL].LowerBound = -90.0f;
port_range_hints[DRYLEVEL].UpperBound = +20.0f;
port_range_hints[DRYPOSL].LowerBound = 0.0f;
port_range_hints[DRYPOSL].UpperBound = 1.0f;
port_range_hints[DRYPOSR].LowerBound = 0.0f;
port_range_hints[DRYPOSR].UpperBound = 1.0f;
port_range_hints[WETLEVEL].LowerBound = -90.0f;
port_range_hints[WETLEVEL].UpperBound = +20.0f;
port_range_hints[WETPOSL].LowerBound = 0.0f;
port_range_hints[WETPOSL].UpperBound = 1.0f;
port_range_hints[WETPOSR].LowerBound = 0.0f;
port_range_hints[WETPOSR].UpperBound = 1.0f;
port_range_hints[INPUT_L].HintDescriptor = 0;
port_range_hints[INPUT_R].HintDescriptor = 0;
port_range_hints[OUTPUT_L].HintDescriptor = 0;
port_range_hints[OUTPUT_R].HintDescriptor = 0;
stereo_descriptor->instantiate = instantiate_Doubler;
stereo_descriptor->connect_port = connect_port_Doubler;
stereo_descriptor->activate = activate_Doubler;
stereo_descriptor->run = run_Doubler;
stereo_descriptor->run_adding = run_adding_Doubler;
stereo_descriptor->set_run_adding_gain = set_run_adding_gain_Doubler;
stereo_descriptor->deactivate = NULL;
stereo_descriptor->cleanup = cleanup_Doubler;
}
void
delete_descriptor(LADSPA_Descriptor * descriptor) {
unsigned long index;
if (descriptor) {
free((char *)descriptor->Label);
free((char *)descriptor->Name);
free((char *)descriptor->Maker);
free((char *)descriptor->Copyright);
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
for (index = 0; index < descriptor->PortCount; index++)
free((char *)(descriptor->PortNames[index]));
free((char **)descriptor->PortNames);
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
free(descriptor);
}
}
/* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
void
__attribute__((destructor)) tap_fini() {
delete_descriptor(stereo_descriptor);
}
/* Return a descriptor of the requested plugin type. */
const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index) {
switch (Index) {
case 0:
return stereo_descriptor;
default:
return NULL;
}
}

View File

@@ -1,666 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_dynamics_m.c,v 1.2 2004/06/15 14:50:55 tszilagyi Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <ladspa.h>
#include "tap_utils.h"
/* ***** VERY IMPORTANT! *****
*
* If you enable this, the plugin will use float arithmetics in DSP
* calculations. This usually yields lower average CPU usage, but
* occasionaly may result in high CPU peaks which cause trouble to you
* and your JACK server. The default is to use fixpoint arithmetics
* (with the following #define commented out). But (depending on the
* processor on which you run the code) you may find floating point
* mode usable.
*/
/*#define DYN_CALC_FLOAT*/
typedef signed int sample;
/* coefficient for float to sample (signed int) conversion */
#define F2S 2147483
#ifdef DYN_CALC_FLOAT
typedef LADSPA_Data dyn_t;
typedef float rms_t;
#else
typedef sample dyn_t;
typedef int64_t rms_t;
#endif
/* The Unique ID of the plugin: */
#define ID_MONO 2152
/* The port numbers for the plugin: */
#define ATTACK 0
#define RELEASE 1
#define OFFSGAIN 2
#define MUGAIN 3
#define RMSENV 4
#define MODGAIN 5
#define MODE 6
#define INPUT 7
#define OUTPUT 8
/* Total number of ports */
#define PORTCOUNT_MONO 9
#define TABSIZE 256
#define RMSSIZE 64
typedef struct {
rms_t buffer[RMSSIZE];
unsigned int pos;
rms_t sum;
} rms_env;
/* max. number of breakpoints on in/out dB graph */
#define MAX_POINTS 20
typedef struct {
LADSPA_Data x;
LADSPA_Data y;
} GRAPH_POINT;
typedef struct {
unsigned long num_points;
GRAPH_POINT points[MAX_POINTS];
} DYNAMICS_DATA;
#include "tap_dynamics_presets.h"
/* The structure used to hold port connection information and state */
typedef struct {
LADSPA_Data * attack;
LADSPA_Data * release;
LADSPA_Data * offsgain;
LADSPA_Data * mugain;
LADSPA_Data * rmsenv;
LADSPA_Data * modgain;
LADSPA_Data * mode;
LADSPA_Data * input;
LADSPA_Data * output;
unsigned long sample_rate;
float * as;
unsigned long count;
dyn_t amp;
dyn_t env;
float gain;
float gain_out;
rms_env * rms;
rms_t sum;
DYNAMICS_DATA graph;
LADSPA_Data run_adding_gain;
} Dynamics;
/* RMS envelope stuff, grabbed without a second thought from Steve Harris's swh-plugins, util/rms.c */
/* Adapted, though, to be able to use fixed-point arithmetics as well. */
rms_env *
rms_env_new(void) {
rms_env * new = (rms_env *)calloc(1, sizeof(rms_env));
return new;
}
void
rms_env_reset(rms_env *r) {
unsigned int i;
for (i = 0; i < RMSSIZE; i++) {
r->buffer[i] = 0.0f;
}
r->pos = 0;
r->sum = 0.0f;
}
inline static
dyn_t
rms_env_process(rms_env *r, const rms_t x) {
r->sum -= r->buffer[r->pos];
r->sum += x;
r->buffer[r->pos] = x;
r->pos = (r->pos + 1) & (RMSSIZE - 1);
#ifdef DYN_CALC_FLOAT
return sqrt(r->sum / (float)RMSSIZE);
#else
return sqrt(r->sum / RMSSIZE);
#endif
}
inline
LADSPA_Data
get_table_gain(int mode, LADSPA_Data level) {
LADSPA_Data x1 = -80.0f;
LADSPA_Data y1 = -80.0f;
LADSPA_Data x2 = 0.0f;
LADSPA_Data y2 = 0.0f;
unsigned int i = 0;
if (level <= -80.0f)
return get_table_gain(mode, -79.9f);
while (i < dyn_data[mode].num_points && dyn_data[mode].points[i].x < level) {
x1 = dyn_data[mode].points[i].x;
y1 = dyn_data[mode].points[i].y;
i++;
}
if (i < dyn_data[mode].num_points) {
x2 = dyn_data[mode].points[i].x;
y2 = dyn_data[mode].points[i].y;
} else
return 0.0f;
return y1 + ((level - x1) * (y2 - y1) / (x2 - x1)) - level;
}
/* Construct a new plugin instance. */
LADSPA_Handle
instantiate_Dynamics(const LADSPA_Descriptor * Descriptor, unsigned long sample_rate) {
LADSPA_Handle * ptr;
float * as = NULL;
unsigned int count = 0;
dyn_t amp = 0.0f;
dyn_t env = 0.0f;
float gain = 0.0f;
float gain_out = 0.0f;
rms_env * rms = NULL;
rms_t sum = 0;
int i;
if ((ptr = malloc(sizeof(Dynamics))) == NULL)
return NULL;
((Dynamics *)ptr)->sample_rate = sample_rate;
((Dynamics *)ptr)->run_adding_gain = 1.0;
if ((rms = rms_env_new()) == NULL)
return NULL;
if ((as = malloc(TABSIZE * sizeof(float))) == NULL)
return NULL;
as[0] = 1.0f;
for (i = 1; i < TABSIZE; i++) {
as[i] = expf(-1.0f / (sample_rate * (float)i / (float)TABSIZE));
}
((Dynamics *)ptr)->as = as;
((Dynamics *)ptr)->count = count;
((Dynamics *)ptr)->amp = amp;
((Dynamics *)ptr)->env = env;
((Dynamics *)ptr)->gain = gain;
((Dynamics *)ptr)->gain_out = gain_out;
((Dynamics *)ptr)->rms = rms;
((Dynamics *)ptr)->sum = sum;
return ptr;
}
/* Connect a port to a data location. */
void
connect_port_Dynamics(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * DataLocation) {
Dynamics * ptr = (Dynamics *)Instance;
switch (Port) {
case ATTACK:
ptr->attack = DataLocation;
break;
case RELEASE:
ptr->release = DataLocation;
break;
case OFFSGAIN:
ptr->offsgain = DataLocation;
break;
case MUGAIN:
ptr->mugain = DataLocation;
break;
case RMSENV:
ptr->rmsenv = DataLocation;
*(ptr->rmsenv) = -60.0f;
break;
case MODGAIN:
ptr->modgain = DataLocation;
*(ptr->modgain) = 0.0f;
break;
case MODE:
ptr->mode = DataLocation;
break;
case INPUT:
ptr->input = DataLocation;
break;
case OUTPUT:
ptr->output = DataLocation;
break;
}
}
void
run_Dynamics(LADSPA_Handle Instance,
unsigned long sample_count) {
Dynamics * ptr = (Dynamics *)Instance;
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
const float attack = LIMIT(*(ptr->attack), 4.0f, 500.0f);
const float release = LIMIT(*(ptr->release), 4.0f, 1000.0f);
const float offsgain = LIMIT(*(ptr->offsgain), -20.0f, 20.0f);
const float mugain = db2lin(LIMIT(*(ptr->mugain), -20.0f, 20.0f));
const int mode = LIMIT(*(ptr->mode), 0, NUM_MODES-1);
unsigned long sample_index;
dyn_t amp = ptr->amp;
dyn_t env = ptr->env;
float * as = ptr->as;
unsigned int count = ptr->count;
float gain = ptr->gain;
float gain_out = ptr->gain_out;
rms_env * rms = ptr->rms;
rms_t sum = ptr->sum;
const float ga = as[(unsigned int)(attack * 0.001f * (float)(TABSIZE-1))];
const float gr = as[(unsigned int)(release * 0.001f * (float)(TABSIZE-1))];
const float ef_a = ga * 0.25f;
const float ef_ai = 1.0f - ef_a;
float level = 0.0f;
float adjust = 0.0f;
for (sample_index = 0; sample_index < sample_count; sample_index++) {
#ifdef DYN_CALC_FLOAT
sum += input[sample_index] * input[sample_index];
if (amp > env) {
env = env * ga + amp * (1.0f - ga);
} else {
env = env * gr + amp * (1.0f - gr);
}
#else
sum += (rms_t)(input[sample_index] * F2S * input[sample_index] * F2S);
if (amp) {
if (amp > env) {
env = (double)env * ga + (double)amp * (1.0f - ga);
} else {
env = (double)env * gr + (double)amp * (1.0f - gr);
}
} else
env = 0;
#endif
if (count++ % 4 == 3) {
#ifdef DYN_CALC_FLOAT
amp = rms_env_process(rms, sum / 4);
#else
if (sum)
amp = rms_env_process(rms, sum / 4);
else
amp = 0;
#endif
#ifdef DYN_CALC_FLOAT
if (isnan(amp))
amp = 0.0f;
#endif
sum = 0;
/* set gain_out according to the difference between
the envelope volume level (env) and the corresponding
output level (from graph) */
#ifdef DYN_CALC_FLOAT
level = 20 * log10f(2 * env);
#else
level = 20 * log10f(2 * (double)env / (double)F2S);
#endif
adjust = get_table_gain(mode, level + offsgain);
gain_out = db2lin(adjust);
}
gain = gain * ef_a + gain_out * ef_ai;
output[sample_index] = input[sample_index] * gain * mugain;
}
ptr->sum = sum;
ptr->amp = amp;
ptr->gain = gain;
ptr->gain_out = gain_out;
ptr->env = env;
ptr->count = count;
*(ptr->rmsenv) = LIMIT(level, -60.0f, 20.0f);
*(ptr->modgain) = LIMIT(adjust, -60.0f, 20.0f);
}
void
set_run_adding_gain_Dynamics(LADSPA_Handle Instance, LADSPA_Data gain) {
Dynamics * ptr = (Dynamics *)Instance;
ptr->run_adding_gain = gain;
}
void
run_adding_Dynamics(LADSPA_Handle Instance,
unsigned long sample_count) {
Dynamics * ptr = (Dynamics *)Instance;
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
const float attack = LIMIT(*(ptr->attack), 4.0f, 500.0f);
const float release = LIMIT(*(ptr->release), 4.0f, 1000.0f);
const float offsgain = LIMIT(*(ptr->offsgain), -20.0f, 20.0f);
const float mugain = db2lin(LIMIT(*(ptr->mugain), -20.0f, 20.0f));
const int mode = LIMIT(*(ptr->mode), 0, NUM_MODES-1);
unsigned long sample_index;
dyn_t amp = ptr->amp;
dyn_t env = ptr->env;
float * as = ptr->as;
unsigned int count = ptr->count;
float gain = ptr->gain;
float gain_out = ptr->gain_out;
rms_env * rms = ptr->rms;
rms_t sum = ptr->sum;
const float ga = as[(unsigned int)(attack * 0.001f * (float)(TABSIZE-1))];
const float gr = as[(unsigned int)(release * 0.001f * (float)(TABSIZE-1))];
const float ef_a = ga * 0.25f;
const float ef_ai = 1.0f - ef_a;
float level = 0.0f;
float adjust = 0.0f;
for (sample_index = 0; sample_index < sample_count; sample_index++) {
#ifdef DYN_CALC_FLOAT
sum += input[sample_index] * input[sample_index];
if (amp > env) {
env = env * ga + amp * (1.0f - ga);
} else {
env = env * gr + amp * (1.0f - gr);
}
#else
sum += (rms_t)(input[sample_index] * F2S * input[sample_index] * F2S);
if (amp) {
if (amp > env) {
env = (double)env * ga + (double)amp * (1.0f - ga);
} else {
env = (double)env * gr + (double)amp * (1.0f - gr);
}
} else
env = 0;
#endif
if (count++ % 4 == 3) {
#ifdef DYN_CALC_FLOAT
amp = rms_env_process(rms, sum / 4);
#else
if (sum)
amp = rms_env_process(rms, sum / 4);
else
amp = 0;
#endif
#ifdef DYN_CALC_FLOAT
if (isnan(amp))
amp = 0.0f;
#endif
sum = 0;
/* set gain_out according to the difference between
the envelope volume level (env) and the corresponding
output level (from graph) */
#ifdef DYN_CALC_FLOAT
level = 20 * log10f(2 * env);
#else
level = 20 * log10f(2 * (double)env / (double)F2S);
#endif
adjust = get_table_gain(mode, level + offsgain);
gain_out = db2lin(adjust);
}
gain = gain * ef_a + gain_out * ef_ai;
output[sample_index] += ptr->run_adding_gain * input[sample_index] * gain * mugain;
}
ptr->sum = sum;
ptr->amp = amp;
ptr->gain = gain;
ptr->gain_out = gain_out;
ptr->env = env;
ptr->count = count;
*(ptr->rmsenv) = LIMIT(level, -60.0f, 20.0f);
*(ptr->modgain) = LIMIT(adjust, -60.0f, 20.0f);
}
/* Throw away a Dynamics effect instance. */
void
cleanup_Dynamics(LADSPA_Handle Instance) {
Dynamics * ptr = (Dynamics *)Instance;
free(ptr->rms);
free(ptr->as);
free(Instance);
}
LADSPA_Descriptor * mono_descriptor = NULL;
/* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
loaded. */
void
__attribute__((constructor)) tap_init() {
char ** port_names;
LADSPA_PortDescriptor * port_descriptors;
LADSPA_PortRangeHint * port_range_hints;
if ((mono_descriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
exit(1);
mono_descriptor->UniqueID = ID_MONO;
mono_descriptor->Label = strdup("tap_dynamics_m");
mono_descriptor->Properties = 0;
mono_descriptor->Name = strdup("TAP Dynamics (M)");
mono_descriptor->Maker = strdup("Tom Szilagyi");
mono_descriptor->Copyright = strdup("GPL");
mono_descriptor->PortCount = PORTCOUNT_MONO;
if ((port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
exit(1);
mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
port_descriptors[ATTACK] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[RELEASE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[OFFSGAIN] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[MUGAIN] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[MODE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[RMSENV] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
port_descriptors[MODGAIN] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
port_descriptors[INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
if ((port_names =
(char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
exit(1);
mono_descriptor->PortNames = (const char **)port_names;
port_names[ATTACK] = strdup("Attack [ms]");
port_names[RELEASE] = strdup("Release [ms]");
port_names[OFFSGAIN] = strdup("Offset Gain [dB]");
port_names[MUGAIN] = strdup("Makeup Gain [dB]");
port_names[MODE] = strdup("Function");
port_names[RMSENV] = strdup("Envelope Volume [dB]");
port_names[MODGAIN] = strdup("Gain Adjustment [dB]");
port_names[INPUT] = strdup("Input");
port_names[OUTPUT] = strdup("Output");
if ((port_range_hints =
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
exit(1);
mono_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
port_range_hints[ATTACK].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_LOW);
port_range_hints[RELEASE].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MIDDLE);
port_range_hints[OFFSGAIN].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[MUGAIN].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[RMSENV].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[MODGAIN].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[MODE].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_INTEGER |
LADSPA_HINT_DEFAULT_0);
port_range_hints[ATTACK].LowerBound = 4.0f;
port_range_hints[ATTACK].UpperBound = 500.0f;
port_range_hints[RELEASE].LowerBound = 4.0f;
port_range_hints[RELEASE].UpperBound = 1000.0f;
port_range_hints[OFFSGAIN].LowerBound = -20.0f;
port_range_hints[OFFSGAIN].UpperBound = 20.0f;
port_range_hints[MUGAIN].LowerBound = -20.0f;
port_range_hints[MUGAIN].UpperBound = 20.0f;
port_range_hints[RMSENV].LowerBound = -60.0f;
port_range_hints[RMSENV].UpperBound = 20.0f;
port_range_hints[MODGAIN].LowerBound = -60.0f;
port_range_hints[MODGAIN].UpperBound = 20.0f;
port_range_hints[MODE].LowerBound = 0;
port_range_hints[MODE].UpperBound = NUM_MODES - 0.9f;
port_range_hints[INPUT].HintDescriptor = 0;
port_range_hints[OUTPUT].HintDescriptor = 0;
mono_descriptor->instantiate = instantiate_Dynamics;
mono_descriptor->connect_port = connect_port_Dynamics;
mono_descriptor->activate = NULL;
mono_descriptor->run = run_Dynamics;
mono_descriptor->run_adding = run_adding_Dynamics;
mono_descriptor->set_run_adding_gain = set_run_adding_gain_Dynamics;
mono_descriptor->deactivate = NULL;
mono_descriptor->cleanup = cleanup_Dynamics;
}
void
delete_descriptor(LADSPA_Descriptor * descriptor) {
unsigned long index;
if (descriptor) {
free((char *)descriptor->Label);
free((char *)descriptor->Name);
free((char *)descriptor->Maker);
free((char *)descriptor->Copyright);
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
for (index = 0; index < descriptor->PortCount; index++)
free((char *)(descriptor->PortNames[index]));
free((char **)descriptor->PortNames);
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
free(descriptor);
}
}
/* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
void
__attribute__((destructor)) tap_fini() {
delete_descriptor(mono_descriptor);
}
/* Return a descriptor of the requested plugin type. */
const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index) {
switch (Index) {
case 0:
return mono_descriptor;
default:
return NULL;
}
}

View File

@@ -1,204 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_dynamics_presets.h,v 1.1 2004/05/01 16:15:06 tszilagyi Exp $
*/
/* Number of dynamics presets */
#define NUM_MODES 15
/* Dynamics presets data */
DYNAMICS_DATA dyn_data[NUM_MODES] = {
{ /* 2:1 compression starting at -6 dB */
4,
{
{-80.0f, -80.0f},
{-6.0f, -6.0f},
{0.0f, -3.8f},
{20.0f, 3.5f},
},
},
{ /* 2:1 compression starting at -9 dB */
4,
{
{-80.0f, -80.0f},
{-9.0f, -9.0f},
{0.0f, -5.3f},
{20.0f, 2.9f},
},
},
{ /* 2:1 compression starting at -12 dB */
4,
{
{-80.0f, -80.0f},
{-12.0f, -12.0f},
{0.0f, -6.8f},
{20.0f, 1.9f},
},
},
{ /* 2:1 compression starting at -18 dB */
4,
{
{-80.0f, -80.0f},
{-18.0f, -18.0f},
{0.0f, -9.8f},
{20.0f, -0.7f},
},
},
{ /* 2.5:1 compression starting at -12 dB */
4,
{
{-80.0f, -80.0f},
{-12.0f, -12.0f},
{0.0f, -7.5f},
{20.0f, 0.0f},
},
},
{ /* 3:1 compression starting at -12 dB */
4,
{
{-80.0f, -80.0f},
{-12.0f, -12.0f},
{0.0f, -9.0f},
{20.0f, -4.0f},
},
},
{ /* 3:1 compression starting at -15 dB */
4,
{
{-80.0f, -80.0f},
{-15.0f, -15.0f},
{0.0f, -10.8f},
{20.0f, -5.2f},
},
},
{ /* Compressor/Gate */
5,
{
{-80.0f, -105.0f},
{-62.0f, -80.0f},
{-15.4f, -15.4f},
{0.0f, -12.0f},
{20.0f, -7.6f},
},
},
{ /* Expander */
8,
{
{-80.0f, -169.0f},
{-54.0f, -80.0f},
{-49.5f, -64.6f},
{-41.1f, -41.1f},
{-25.8f, -15.0f},
{-10.8f, -4.5f},
{0.0f, 0.0f},
{20.0f, 8.3f},
},
},
{ /* Hard limiter at -6 dB */
3,
{
{-80.0f, -80.0f},
{-6.0f, -6.0f},
{20.0f, -6.0f},
},
},
{ /* Hard limiter at -12 dB */
3,
{
{-80.0f, -80.0f},
{-12.0f, -12.0f},
{20.0f, -12.0f},
},
},
{ /* Hard noise gate at -35 dB */
4,
{
{-80.0f, -115.0f},
{-35.1f, -80.0f},
{-35.0f, -35.0f},
{20.0f, 20.0f},
},
},
{ /* Soft limiter */
5,
{
{-80.0f, -80.0f},
{-12.4f, -12.4f},
{-6.0f, -8.0f},
{0.0f, -6.8f},
{20.0f, -2.8f},
},
},
{ /* Soft knee comp/gate (-24 dB threshold) */
8,
{
{-80.0f, -113.7f},
{-46.3f, -80.0f},
{-42.0f, -56.8f},
{-33.6f, -36.3f},
{-24.0f, -24.0f},
{-11.1f, -15.4f},
{0.0f, -12.0f},
{20.0f, -5.8f},
},
},
{ /* Soft noise gate below -36 dB */
7,
{
{-80.0f, -104.0f},
{-56.0f, -80.0f},
{-51.8f, -67.2f},
{-44.7f, -49.3f},
{-34.0f, -34.0f},
{0.0f, 0.0f},
{20.0f, 20.0f},
},
},
/* You can add your own presets here.
* Please read the docs about the format.
*/
};

View File

@@ -1,877 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_dynamics_st.c,v 1.2 2004/06/15 14:50:55 tszilagyi Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <ladspa.h>
#include "tap_utils.h"
/* ***** VERY IMPORTANT! *****
*
* If you enable this, the plugin will use float arithmetics in DSP
* calculations. This usually yields lower average CPU usage, but
* occasionaly may result in high CPU peaks which cause trouble to you
* and your JACK server. The default is to use fixpoint arithmetics
* (with the following #define commented out). But (depending on the
* processor on which you run the code) you may find floating point
* mode usable.
*/
/*#define DYN_CALC_FLOAT*/
typedef signed int sample;
/* coefficient for float to sample (signed int) conversion */
/* this allows for about 60 dB headroom above 0dB, if 0 dB is equivalent to 1.0f */
/* As 2^31 equals more than 180 dB, about 120 dB dynamics remains below 0 dB */
#define F2S 2147483
#ifdef DYN_CALC_FLOAT
typedef LADSPA_Data dyn_t;
typedef float rms_t;
#else
typedef sample dyn_t;
typedef int64_t rms_t;
#endif
/* The Unique ID of the plugin: */
#define ID_STEREO 2153
/* The port numbers for the plugin: */
#define ATTACK 0
#define RELEASE 1
#define OFFSGAIN 2
#define MUGAIN 3
#define RMSENV_L 4
#define RMSENV_R 5
#define MODGAIN_L 6
#define MODGAIN_R 7
#define STEREO 8
#define MODE 9
#define INPUT_L 10
#define INPUT_R 11
#define OUTPUT_L 12
#define OUTPUT_R 13
/* Total number of ports */
#define PORTCOUNT_STEREO 14
#define TABSIZE 256
#define RMSSIZE 64
typedef struct {
rms_t buffer[RMSSIZE];
unsigned int pos;
rms_t sum;
} rms_env;
/* max. number of breakpoints on in/out dB graph */
#define MAX_POINTS 20
typedef struct {
LADSPA_Data x;
LADSPA_Data y;
} GRAPH_POINT;
typedef struct {
unsigned long num_points;
GRAPH_POINT points[MAX_POINTS];
} DYNAMICS_DATA;
#include "tap_dynamics_presets.h"
/* The structure used to hold port connection information and state */
typedef struct {
LADSPA_Data * attack;
LADSPA_Data * release;
LADSPA_Data * offsgain;
LADSPA_Data * mugain;
LADSPA_Data * rmsenv_L;
LADSPA_Data * rmsenv_R;
LADSPA_Data * modgain_L;
LADSPA_Data * modgain_R;
LADSPA_Data * stereo;
LADSPA_Data * mode;
LADSPA_Data * input_L;
LADSPA_Data * output_L;
LADSPA_Data * input_R;
LADSPA_Data * output_R;
unsigned long sample_rate;
float * as;
unsigned long count;
dyn_t amp_L;
dyn_t amp_R;
dyn_t env_L;
dyn_t env_R;
float gain_L;
float gain_R;
float gain_out_L;
float gain_out_R;
rms_env * rms_L;
rms_env * rms_R;
rms_t sum_L;
rms_t sum_R;
DYNAMICS_DATA graph;
LADSPA_Data run_adding_gain;
} Dynamics;
/* RMS envelope stuff, grabbed without a second thought from Steve Harris's swh-plugins, util/rms.c */
/* Adapted, though, to be able to use fixed-point arithmetics as well. */
rms_env *
rms_env_new(void) {
rms_env * new = (rms_env *)calloc(1, sizeof(rms_env));
return new;
}
void
rms_env_reset(rms_env *r) {
unsigned int i;
for (i = 0; i < RMSSIZE; i++) {
r->buffer[i] = 0.0f;
}
r->pos = 0;
r->sum = 0.0f;
}
inline static
dyn_t
rms_env_process(rms_env *r, const rms_t x) {
r->sum -= r->buffer[r->pos];
r->sum += x;
r->buffer[r->pos] = x;
r->pos = (r->pos + 1) & (RMSSIZE - 1);
#ifdef DYN_CALC_FLOAT
return sqrt(r->sum / (float)RMSSIZE);
#else
return sqrt(r->sum / RMSSIZE);
#endif
}
inline
LADSPA_Data
get_table_gain(int mode, LADSPA_Data level) {
LADSPA_Data x1 = -80.0f;
LADSPA_Data y1 = -80.0f;
LADSPA_Data x2 = 0.0f;
LADSPA_Data y2 = 0.0f;
unsigned int i = 0;
if (level <= -80.0f)
return get_table_gain(mode, -79.9f);
while (i < dyn_data[mode].num_points && dyn_data[mode].points[i].x < level) {
x1 = dyn_data[mode].points[i].x;
y1 = dyn_data[mode].points[i].y;
i++;
}
if (i < dyn_data[mode].num_points) {
x2 = dyn_data[mode].points[i].x;
y2 = dyn_data[mode].points[i].y;
} else
return 0.0f;
return y1 + ((level - x1) * (y2 - y1) / (x2 - x1)) - level;
}
/* Construct a new plugin instance. */
LADSPA_Handle
instantiate_Dynamics(const LADSPA_Descriptor * Descriptor, unsigned long sample_rate) {
LADSPA_Handle * ptr;
float * as = NULL;
unsigned int count = 0;
dyn_t amp_L = 0.0f;
dyn_t amp_R = 0.0f;
dyn_t env_L = 0.0f;
dyn_t env_R = 0.0f;
float gain_L = 0.0f;
float gain_R = 0.0f;
float gain_out_L = 0.0f;
float gain_out_R = 0.0f;
rms_env * rms_L = NULL;
rms_env * rms_R = NULL;
rms_t sum_L = 0.0f;
rms_t sum_R = 0.0f;
int i;
if ((ptr = malloc(sizeof(Dynamics))) == NULL)
return NULL;
((Dynamics *)ptr)->sample_rate = sample_rate;
((Dynamics *)ptr)->run_adding_gain = 1.0;
if ((rms_L = rms_env_new()) == NULL)
return NULL;
if ((rms_R = rms_env_new()) == NULL)
return NULL;
if ((as = malloc(TABSIZE * sizeof(float))) == NULL)
return NULL;
as[0] = 1.0f;
for (i = 1; i < TABSIZE; i++) {
as[i] = expf(-1.0f / (sample_rate * (float)i / (float)TABSIZE));
}
((Dynamics *)ptr)->as = as;
((Dynamics *)ptr)->count = count;
((Dynamics *)ptr)->amp_L = amp_L;
((Dynamics *)ptr)->amp_R = amp_R;
((Dynamics *)ptr)->env_L = env_L;
((Dynamics *)ptr)->env_R = env_R;
((Dynamics *)ptr)->gain_L = gain_L;
((Dynamics *)ptr)->gain_R = gain_R;
((Dynamics *)ptr)->gain_out_L = gain_out_L;
((Dynamics *)ptr)->gain_out_R = gain_out_R;
((Dynamics *)ptr)->rms_L = rms_L;
((Dynamics *)ptr)->rms_R = rms_R;
((Dynamics *)ptr)->sum_L = sum_L;
((Dynamics *)ptr)->sum_R = sum_R;
return ptr;
}
/* Connect a port to a data location. */
void
connect_port_Dynamics(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * DataLocation) {
Dynamics * ptr = (Dynamics *)Instance;
switch (Port) {
case ATTACK:
ptr->attack = DataLocation;
break;
case RELEASE:
ptr->release = DataLocation;
break;
case OFFSGAIN:
ptr->offsgain = DataLocation;
break;
case MUGAIN:
ptr->mugain = DataLocation;
break;
case RMSENV_L:
ptr->rmsenv_L = DataLocation;
*(ptr->rmsenv_L) = -60.0f;
break;
case RMSENV_R:
ptr->rmsenv_R = DataLocation;
*(ptr->rmsenv_R) = -60.0f;
break;
case MODGAIN_L:
ptr->modgain_L = DataLocation;
*(ptr->modgain_L) = 0.0f;
break;
case MODGAIN_R:
ptr->modgain_R = DataLocation;
*(ptr->modgain_R) = 0.0f;
break;
case STEREO:
ptr->stereo = DataLocation;
break;
case MODE:
ptr->mode = DataLocation;
break;
case INPUT_L:
ptr->input_L = DataLocation;
break;
case OUTPUT_L:
ptr->output_L = DataLocation;
break;
case INPUT_R:
ptr->input_R = DataLocation;
break;
case OUTPUT_R:
ptr->output_R = DataLocation;
break;
}
}
void
run_Dynamics(LADSPA_Handle Instance,
unsigned long sample_count) {
Dynamics * ptr = (Dynamics *)Instance;
LADSPA_Data * input_L = ptr->input_L;
LADSPA_Data * output_L = ptr->output_L;
LADSPA_Data * input_R = ptr->input_R;
LADSPA_Data * output_R = ptr->output_R;
const float attack = LIMIT(*(ptr->attack), 4.0f, 500.0f);
const float release = LIMIT(*(ptr->release), 4.0f, 1000.0f);
const float offsgain = LIMIT(*(ptr->offsgain), -20.0f, 20.0f);
const float mugain = db2lin(LIMIT(*(ptr->mugain), -20.0f, 20.0f));
const int stereo = LIMIT(*(ptr->stereo), 0, 2);
const int mode = LIMIT(*(ptr->mode), 0, NUM_MODES-1);
unsigned long sample_index;
dyn_t amp_L = ptr->amp_L;
dyn_t amp_R = ptr->amp_R;
dyn_t env_L = ptr->env_L;
dyn_t env_R = ptr->env_R;
float * as = ptr->as;
unsigned int count = ptr->count;
float gain_L = ptr->gain_L;
float gain_R = ptr->gain_R;
float gain_out_L = ptr->gain_out_L;
float gain_out_R = ptr->gain_out_R;
rms_env * rms_L = ptr->rms_L;
rms_env * rms_R = ptr->rms_R;
rms_t sum_L = ptr->sum_L;
rms_t sum_R = ptr->sum_R;
const float ga = as[(unsigned int)(attack * 0.001f * (LADSPA_Data)(TABSIZE-1))];
const float gr = as[(unsigned int)(release * 0.001f * (LADSPA_Data)(TABSIZE-1))];
const float ef_a = ga * 0.25f;
const float ef_ai = 1.0f - ef_a;
float level_L = 0.0f;
float level_R = 0.0f;
float adjust_L = 0.0f;
float adjust_R = 0.0f;
for (sample_index = 0; sample_index < sample_count; sample_index++) {
#ifdef DYN_CALC_FLOAT
sum_L += input_L[sample_index] * input_L[sample_index];
sum_R += input_R[sample_index] * input_R[sample_index];
if (amp_L > env_L) {
env_L = env_L * ga + amp_L * (1.0f - ga);
} else {
env_L = env_L * gr + amp_L * (1.0f - gr);
}
if (amp_R > env_R) {
env_R = env_R * ga + amp_R * (1.0f - ga);
} else {
env_R = env_R * gr + amp_R * (1.0f - gr);
}
#else
sum_L += (rms_t)(input_L[sample_index] * F2S) * (rms_t)(input_L[sample_index] * F2S);
sum_R += (rms_t)(input_R[sample_index] * F2S) * (rms_t)(input_R[sample_index] * F2S);
if (amp_L) {
if (amp_L > env_L) {
env_L = (double)env_L * ga + (double)amp_L * (1.0f - ga);
} else {
env_L = (double)env_L * gr + (double)amp_L * (1.0f - gr);
}
} else
env_L = 0;
if (amp_R) {
if (amp_R > env_R) {
env_R = (double)env_R * ga + (double)amp_R * (1.0f - ga);
} else {
env_R = (double)env_R * gr + (double)amp_R * (1.0f - gr);
}
} else
env_R = 0;
#endif
if (count++ % 4 == 3) {
#ifdef DYN_CALC_FLOAT
amp_L = rms_env_process(rms_L, sum_L * 0.25f);
amp_R = rms_env_process(rms_R, sum_R * 0.25f);
#else
if (sum_L)
amp_L = rms_env_process(rms_L, sum_L * 0.25f);
else
amp_L = 0;
if (sum_R)
amp_R = rms_env_process(rms_R, sum_R * 0.25f);
else
amp_R = 0;
#endif
#ifdef DYN_CALC_FLOAT
if (isnan(amp_L))
amp_L = 0.0f;
if (isnan(amp_R))
amp_R = 0.0f;
#endif
sum_L = sum_R = 0;
/* set gain_out according to the difference between
the envelope volume level (env) and the corresponding
output level (from graph) */
#ifdef DYN_CALC_FLOAT
level_L = 20 * log10f(2 * env_L);
level_R = 20 * log10f(2 * env_R);
#else
level_L = 20 * log10f(2 * (double)env_L / (double)F2S);
level_R = 20 * log10f(2 * (double)env_R / (double)F2S);
#endif
adjust_L = get_table_gain(mode, level_L + offsgain);
adjust_R = get_table_gain(mode, level_R + offsgain);
/* set gains according to stereo mode */
switch (stereo) {
case 0:
gain_out_L = db2lin(adjust_L);
gain_out_R = db2lin(adjust_R);
break;
case 1:
adjust_L = adjust_R = (adjust_L + adjust_R) / 2.0f;
gain_out_L = gain_out_R = db2lin(adjust_L);
break;
case 2:
adjust_L = adjust_R = (adjust_L > adjust_R) ? adjust_L : adjust_R;
gain_out_L = gain_out_R = db2lin(adjust_L);
break;
}
}
gain_L = gain_L * ef_a + gain_out_L * ef_ai;
gain_R = gain_R * ef_a + gain_out_R * ef_ai;
output_L[sample_index] = input_L[sample_index] * gain_L * mugain;
output_R[sample_index] = input_R[sample_index] * gain_R * mugain;
}
ptr->sum_L = sum_L;
ptr->sum_R = sum_R;
ptr->amp_L = amp_L;
ptr->amp_R = amp_R;
ptr->gain_L = gain_L;
ptr->gain_R = gain_R;
ptr->gain_out_L = gain_out_L;
ptr->gain_out_R = gain_out_R;
ptr->env_L = env_L;
ptr->env_R = env_R;
ptr->count = count;
*(ptr->rmsenv_L) = LIMIT(level_L, -60.0f, 20.0f);
*(ptr->rmsenv_R) = LIMIT(level_R, -60.0f, 20.0f);
*(ptr->modgain_L) = LIMIT(adjust_L, -60.0f, 20.0f);
*(ptr->modgain_R) = LIMIT(adjust_R, -60.0f, 20.0f);
}
void
set_run_adding_gain_Dynamics(LADSPA_Handle Instance, LADSPA_Data gain) {
Dynamics * ptr = (Dynamics *)Instance;
ptr->run_adding_gain = gain;
}
void
run_adding_Dynamics(LADSPA_Handle Instance,
unsigned long sample_count) {
Dynamics * ptr = (Dynamics *)Instance;
LADSPA_Data * input_L = ptr->input_L;
LADSPA_Data * output_L = ptr->output_L;
LADSPA_Data * input_R = ptr->input_R;
LADSPA_Data * output_R = ptr->output_R;
const float attack = LIMIT(*(ptr->attack), 4.0f, 500.0f);
const float release = LIMIT(*(ptr->release), 4.0f, 1000.0f);
const float offsgain = LIMIT(*(ptr->offsgain), -20.0f, 20.0f);
const float mugain = db2lin(LIMIT(*(ptr->mugain), -20.0f, 20.0f));
const int stereo = LIMIT(*(ptr->stereo), 0, 2);
const int mode = LIMIT(*(ptr->mode), 0, NUM_MODES-1);
unsigned long sample_index;
dyn_t amp_L = ptr->amp_L;
dyn_t amp_R = ptr->amp_R;
dyn_t env_L = ptr->env_L;
dyn_t env_R = ptr->env_R;
float * as = ptr->as;
unsigned int count = ptr->count;
float gain_L = ptr->gain_L;
float gain_R = ptr->gain_R;
float gain_out_L = ptr->gain_out_L;
float gain_out_R = ptr->gain_out_R;
rms_env * rms_L = ptr->rms_L;
rms_env * rms_R = ptr->rms_R;
rms_t sum_L = ptr->sum_L;
rms_t sum_R = ptr->sum_R;
const float ga = as[(unsigned int)(attack * 0.001f * (LADSPA_Data)(TABSIZE-1))];
const float gr = as[(unsigned int)(release * 0.001f * (LADSPA_Data)(TABSIZE-1))];
const float ef_a = ga * 0.25f;
const float ef_ai = 1.0f - ef_a;
float level_L = 0.0f;
float level_R = 0.0f;
float adjust_L = 0.0f;
float adjust_R = 0.0f;
for (sample_index = 0; sample_index < sample_count; sample_index++) {
#ifdef DYN_CALC_FLOAT
sum_L += input_L[sample_index] * input_L[sample_index];
sum_R += input_R[sample_index] * input_R[sample_index];
if (amp_L > env_L) {
env_L = env_L * ga + amp_L * (1.0f - ga);
} else {
env_L = env_L * gr + amp_L * (1.0f - gr);
}
if (amp_R > env_R) {
env_R = env_R * ga + amp_R * (1.0f - ga);
} else {
env_R = env_R * gr + amp_R * (1.0f - gr);
}
#else
sum_L += (rms_t)(input_L[sample_index] * F2S) * (rms_t)(input_L[sample_index] * F2S);
sum_R += (rms_t)(input_R[sample_index] * F2S) * (rms_t)(input_R[sample_index] * F2S);
if (amp_L) {
if (amp_L > env_L) {
env_L = (double)env_L * ga + (double)amp_L * (1.0f - ga);
} else {
env_L = (double)env_L * gr + (double)amp_L * (1.0f - gr);
}
} else
env_L = 0;
if (amp_R) {
if (amp_R > env_R) {
env_R = (double)env_R * ga + (double)amp_R * (1.0f - ga);
} else {
env_R = (double)env_R * gr + (double)amp_R * (1.0f - gr);
}
} else
env_R = 0;
#endif
if (count++ % 4 == 3) {
#ifdef DYN_CALC_FLOAT
amp_L = rms_env_process(rms_L, sum_L * 0.25f);
amp_R = rms_env_process(rms_R, sum_R * 0.25f);
#else
if (sum_L)
amp_L = rms_env_process(rms_L, sum_L * 0.25f);
else
amp_L = 0;
if (sum_R)
amp_R = rms_env_process(rms_R, sum_R * 0.25f);
else
amp_R = 0;
#endif
#ifdef DYN_CALC_FLOAT
if (isnan(amp_L))
amp_L = 0.0f;
if (isnan(amp_R))
amp_R = 0.0f;
#endif
sum_L = sum_R = 0;
/* set gain_out according to the difference between
the envelope volume level (env) and the corresponding
output level (from graph) */
#ifdef DYN_CALC_FLOAT
level_L = 20 * log10f(2 * env_L);
level_R = 20 * log10f(2 * env_R);
#else
level_L = 20 * log10f(2 * (double)env_L / (double)F2S);
level_R = 20 * log10f(2 * (double)env_R / (double)F2S);
#endif
adjust_L = get_table_gain(mode, level_L + offsgain);
adjust_R = get_table_gain(mode, level_R + offsgain);
/* set gains according to stereo mode */
switch (stereo) {
case 0:
gain_out_L = db2lin(adjust_L);
gain_out_R = db2lin(adjust_R);
break;
case 1:
adjust_L = adjust_R = (adjust_L + adjust_R) / 2.0f;
gain_out_L = gain_out_R = db2lin(adjust_L);
break;
case 2:
adjust_L = adjust_R = (adjust_L > adjust_R) ? adjust_L : adjust_R;
gain_out_L = gain_out_R = db2lin(adjust_L);
break;
}
}
gain_L = gain_L * ef_a + gain_out_L * ef_ai;
gain_R = gain_R * ef_a + gain_out_R * ef_ai;
output_L[sample_index] += ptr->run_adding_gain * input_L[sample_index] * gain_L * mugain;
output_R[sample_index] += ptr->run_adding_gain * input_R[sample_index] * gain_R * mugain;
}
ptr->sum_L = sum_L;
ptr->sum_R = sum_R;
ptr->amp_L = amp_L;
ptr->amp_R = amp_R;
ptr->gain_L = gain_L;
ptr->gain_R = gain_R;
ptr->gain_out_L = gain_out_L;
ptr->gain_out_R = gain_out_R;
ptr->env_L = env_L;
ptr->env_R = env_R;
ptr->count = count;
*(ptr->rmsenv_L) = LIMIT(level_L, -60.0f, 20.0f);
*(ptr->rmsenv_R) = LIMIT(level_R, -60.0f, 20.0f);
*(ptr->modgain_L) = LIMIT(adjust_L, -60.0f, 20.0f);
*(ptr->modgain_R) = LIMIT(adjust_R, -60.0f, 20.0f);
}
/* Throw away a Dynamics effect instance. */
void
cleanup_Dynamics(LADSPA_Handle Instance) {
Dynamics * ptr = (Dynamics *)Instance;
free(ptr->rms_L);
free(ptr->rms_R);
free(ptr->as);
free(Instance);
}
LADSPA_Descriptor * stereo_descriptor = NULL;
/* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
loaded. */
void
__attribute__((constructor)) tap_init() {
char ** port_names;
LADSPA_PortDescriptor * port_descriptors;
LADSPA_PortRangeHint * port_range_hints;
if ((stereo_descriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
exit(1);
stereo_descriptor->UniqueID = ID_STEREO;
stereo_descriptor->Label = strdup("tap_dynamics_st");
stereo_descriptor->Properties = 0;
stereo_descriptor->Name = strdup("TAP Dynamics (St)");
stereo_descriptor->Maker = strdup("Tom Szilagyi");
stereo_descriptor->Copyright = strdup("GPL");
stereo_descriptor->PortCount = PORTCOUNT_STEREO;
if ((port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortDescriptor))) == NULL)
exit(1);
stereo_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
port_descriptors[ATTACK] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[RELEASE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[OFFSGAIN] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[MUGAIN] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[STEREO] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[MODE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[RMSENV_L] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
port_descriptors[RMSENV_R] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
port_descriptors[MODGAIN_L] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
port_descriptors[MODGAIN_R] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
port_descriptors[INPUT_L] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[INPUT_R] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT_L] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT_R] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
if ((port_names =
(char **)calloc(PORTCOUNT_STEREO, sizeof(char *))) == NULL)
exit(1);
stereo_descriptor->PortNames = (const char **)port_names;
port_names[ATTACK] = strdup("Attack [ms]");
port_names[RELEASE] = strdup("Release [ms]");
port_names[OFFSGAIN] = strdup("Offset Gain [dB]");
port_names[MUGAIN] = strdup("Makeup Gain [dB]");
port_names[STEREO] = strdup("Stereo Mode");
port_names[MODE] = strdup("Function");
port_names[RMSENV_L] = strdup("Envelope Volume (L) [dB]");
port_names[RMSENV_R] = strdup("Envelope Volume (R) [dB]");
port_names[MODGAIN_L] = strdup("Gain Adjustment (L) [dB]");
port_names[MODGAIN_R] = strdup("Gain Adjustment (R) [dB]");
port_names[INPUT_L] = strdup("Input Left");
port_names[INPUT_R] = strdup("Input Right");
port_names[OUTPUT_L] = strdup("Output Left");
port_names[OUTPUT_R] = strdup("Output Right");
if ((port_range_hints =
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortRangeHint)))) == NULL)
exit(1);
stereo_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
port_range_hints[ATTACK].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_LOW);
port_range_hints[RELEASE].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MIDDLE);
port_range_hints[OFFSGAIN].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[MUGAIN].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[RMSENV_L].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[RMSENV_R].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[MODGAIN_L].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[MODGAIN_R].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[STEREO].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_INTEGER |
LADSPA_HINT_DEFAULT_0);
port_range_hints[MODE].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_INTEGER |
LADSPA_HINT_DEFAULT_0);
port_range_hints[ATTACK].LowerBound = 4.0f;
port_range_hints[ATTACK].UpperBound = 500.0f;
port_range_hints[RELEASE].LowerBound = 4.0f;
port_range_hints[RELEASE].UpperBound = 1000.0f;
port_range_hints[OFFSGAIN].LowerBound = -20.0f;
port_range_hints[OFFSGAIN].UpperBound = 20.0f;
port_range_hints[MUGAIN].LowerBound = -20.0f;
port_range_hints[MUGAIN].UpperBound = 20.0f;
port_range_hints[RMSENV_L].LowerBound = -60.0f;
port_range_hints[RMSENV_L].UpperBound = 20.0f;
port_range_hints[RMSENV_R].LowerBound = -60.0f;
port_range_hints[RMSENV_R].UpperBound = 20.0f;
port_range_hints[MODGAIN_L].LowerBound = -60.0f;
port_range_hints[MODGAIN_L].UpperBound = 20.0f;
port_range_hints[MODGAIN_R].LowerBound = -60.0f;
port_range_hints[MODGAIN_R].UpperBound = 20.0f;
port_range_hints[STEREO].LowerBound = 0;
port_range_hints[STEREO].UpperBound = 2.1f;
port_range_hints[MODE].LowerBound = 0;
port_range_hints[MODE].UpperBound = NUM_MODES - 0.9f;
port_range_hints[INPUT_L].HintDescriptor = 0;
port_range_hints[INPUT_R].HintDescriptor = 0;
port_range_hints[OUTPUT_L].HintDescriptor = 0;
port_range_hints[OUTPUT_R].HintDescriptor = 0;
stereo_descriptor->instantiate = instantiate_Dynamics;
stereo_descriptor->connect_port = connect_port_Dynamics;
stereo_descriptor->activate = NULL;
stereo_descriptor->run = run_Dynamics;
stereo_descriptor->run_adding = run_adding_Dynamics;
stereo_descriptor->set_run_adding_gain = set_run_adding_gain_Dynamics;
stereo_descriptor->deactivate = NULL;
stereo_descriptor->cleanup = cleanup_Dynamics;
}
void
delete_descriptor(LADSPA_Descriptor * descriptor) {
unsigned long index;
if (descriptor) {
free((char *)descriptor->Label);
free((char *)descriptor->Name);
free((char *)descriptor->Maker);
free((char *)descriptor->Copyright);
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
for (index = 0; index < descriptor->PortCount; index++)
free((char *)(descriptor->PortNames[index]));
free((char **)descriptor->PortNames);
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
free(descriptor);
}
}
/* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
void
__attribute__((destructor)) tap_fini() {
delete_descriptor(stereo_descriptor);
}
/* Return a descriptor of the requested plugin type. */
const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index) {
switch (Index) {
case 0:
return stereo_descriptor;
default:
return NULL;
}
}

View File

@@ -1,629 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_echo.c,v 1.7 2004/12/06 09:32:41 tszilagyi Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ladspa.h>
#include "tap_utils.h"
/* The Unique ID of the plugin: */
#define ID_STEREO 2143
/* The port numbers for the plugin: */
#define DELAYTIME_L 0
#define FEEDBACK_L 1
#define DELAYTIME_R 2
#define FEEDBACK_R 3
#define STRENGTH_L 4
#define STRENGTH_R 5
#define DRYLEVEL 6
#define MODE 7
#define HAAS 8
#define REV_OUTCH 9
#define INPUT_L 10
#define OUTPUT_L 11
#define INPUT_R 12
#define OUTPUT_R 13
/* Total number of ports */
#define PORTCOUNT_STEREO 14
/* Maximum delay (ms) */
#define MAX_DELAY 2000
/* The structure used to hold port connection information and state */
typedef struct {
LADSPA_Data * delaytime_L;
LADSPA_Data * delaytime_R;
LADSPA_Data * feedback_L;
LADSPA_Data * feedback_R;
LADSPA_Data * strength_L;
LADSPA_Data * strength_R;
LADSPA_Data * drylevel;
LADSPA_Data * mode;
LADSPA_Data * haas;
LADSPA_Data * rev_outch;
LADSPA_Data * input_L;
LADSPA_Data * output_L;
LADSPA_Data * input_R;
LADSPA_Data * output_R;
unsigned long sample_rate;
LADSPA_Data mpx_out_L;
LADSPA_Data mpx_out_R;
LADSPA_Data * ringbuffer_L;
LADSPA_Data * ringbuffer_R;
unsigned long * buffer_pos_L;
unsigned long * buffer_pos_R;
LADSPA_Data run_adding_gain;
} Echo;
/* Construct a new plugin instance. */
LADSPA_Handle
instantiate_Echo(const LADSPA_Descriptor * Descriptor,
unsigned long SampleRate) {
LADSPA_Handle * ptr;
if ((ptr = malloc(sizeof(Echo))) != NULL) {
((Echo *)ptr)->sample_rate = SampleRate;
((Echo *)ptr)->run_adding_gain = 1.0f;
/* allocate memory for ringbuffers and related dynamic vars */
if ((((Echo *)ptr)->ringbuffer_L =
calloc(MAX_DELAY * ((Echo *)ptr)->sample_rate / 1000,
sizeof(LADSPA_Data))) == NULL)
exit(1);
if ((((Echo *)ptr)->ringbuffer_R =
calloc(MAX_DELAY * ((Echo *)ptr)->sample_rate / 1000,
sizeof(LADSPA_Data))) == NULL)
exit(1);
if ((((Echo *)ptr)->buffer_pos_L = calloc(1, sizeof(unsigned long))) == NULL)
exit(1);
if ((((Echo *)ptr)->buffer_pos_R = calloc(1, sizeof(unsigned long))) == NULL)
exit(1);
*(((Echo *)ptr)->buffer_pos_L) = 0;
*(((Echo *)ptr)->buffer_pos_R) = 0;
return ptr;
}
return NULL;
}
/* activate a plugin instance */
void
activate_Echo(LADSPA_Handle Instance) {
Echo * ptr = (Echo *)Instance;
unsigned int i;
ptr->mpx_out_L = 0;
ptr->mpx_out_R = 0;
*(ptr->buffer_pos_L) = 0;
*(ptr->buffer_pos_R) = 0;
for (i = 0; i < MAX_DELAY * ptr->sample_rate / 1000; i++) {
ptr->ringbuffer_L[i] = 0.0f;
ptr->ringbuffer_R[i] = 0.0f;
}
}
/* Connect a port to a data location. */
void
connect_port_Echo(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * DataLocation) {
Echo * ptr;
ptr = (Echo *)Instance;
switch (Port) {
case DELAYTIME_L:
ptr->delaytime_L = DataLocation;
break;
case DELAYTIME_R:
ptr->delaytime_R = DataLocation;
break;
case FEEDBACK_L:
ptr->feedback_L = DataLocation;
break;
case FEEDBACK_R:
ptr->feedback_R = DataLocation;
break;
case STRENGTH_L:
ptr->strength_L = DataLocation;
break;
case STRENGTH_R:
ptr->strength_R = DataLocation;
break;
case MODE:
ptr->mode = DataLocation;
break;
case HAAS:
ptr->haas = DataLocation;
break;
case REV_OUTCH:
ptr->rev_outch = DataLocation;
break;
case DRYLEVEL:
ptr->drylevel = DataLocation;
break;
case INPUT_L:
ptr->input_L = DataLocation;
break;
case OUTPUT_L:
ptr->output_L = DataLocation;
break;
case INPUT_R:
ptr->input_R = DataLocation;
break;
case OUTPUT_R:
ptr->output_R = DataLocation;
break;
}
}
#define EPS 0.00000001f
static inline float
M(float x) {
if ((x > EPS) || (x < -EPS))
return x;
else
return 0.0f;
}
void
run_Echo(LADSPA_Handle Instance,
unsigned long SampleCount) {
Echo * ptr;
unsigned long sample_index;
LADSPA_Data delaytime_L;
LADSPA_Data delaytime_R;
LADSPA_Data feedback_L;
LADSPA_Data feedback_R;
LADSPA_Data strength_L;
LADSPA_Data strength_R;
LADSPA_Data drylevel;
LADSPA_Data mode;
LADSPA_Data haas;
LADSPA_Data rev_outch;
LADSPA_Data * input_L;
LADSPA_Data * output_L;
LADSPA_Data * input_R;
LADSPA_Data * output_R;
unsigned long sample_rate;
unsigned long buflen_L;
unsigned long buflen_R;
LADSPA_Data out_L = 0;
LADSPA_Data out_R = 0;
LADSPA_Data in_L = 0;
LADSPA_Data in_R = 0;
ptr = (Echo *)Instance;
delaytime_L = LIMIT(*(ptr->delaytime_L),0.0f,2000.0f);
delaytime_R = LIMIT(*(ptr->delaytime_R),0.0f,2000.0f);
feedback_L = LIMIT(*(ptr->feedback_L) / 100.0, 0.0f, 100.0f);
feedback_R = LIMIT(*(ptr->feedback_R) / 100.0, 0.0f, 100.0f);
strength_L = db2lin(LIMIT(*(ptr->strength_L),-70.0f,10.0f));
strength_R = db2lin(LIMIT(*(ptr->strength_R),-70.0f,10.0f));
drylevel = db2lin(LIMIT(*(ptr->drylevel),-70.0f,10.0f));
mode = LIMIT(*(ptr->mode),-2.0f,2.0f);
haas = LIMIT(*(ptr->haas),-2.0f,2.0f);
rev_outch = LIMIT(*(ptr->rev_outch),-2.0f,2.0f);
input_L = ptr->input_L;
output_L = ptr->output_L;
input_R = ptr->input_R;
output_R = ptr->output_R;
sample_rate = ptr->sample_rate;
buflen_L = delaytime_L * sample_rate / 1000;
buflen_R = delaytime_R * sample_rate / 1000;
for (sample_index = 0; sample_index < SampleCount; sample_index++) {
in_L = *(input_L++);
in_R = *(input_R++);
out_L = in_L * drylevel + ptr->mpx_out_L * strength_L;
out_R = in_R * drylevel + ptr->mpx_out_R * strength_R;
if (haas > 0.0f)
in_R = 0.0f;
if (mode <= 0.0f) {
ptr->mpx_out_L =
M(push_buffer(in_L + ptr->mpx_out_L * feedback_L,
ptr->ringbuffer_L, buflen_L, ptr->buffer_pos_L));
ptr->mpx_out_R =
M(push_buffer(in_R + ptr->mpx_out_R * feedback_R,
ptr->ringbuffer_R, buflen_R, ptr->buffer_pos_R));
} else {
ptr->mpx_out_R =
M(push_buffer(in_L + ptr->mpx_out_L * feedback_L,
ptr->ringbuffer_L, buflen_L, ptr->buffer_pos_L));
ptr->mpx_out_L =
M(push_buffer(in_R + ptr->mpx_out_R * feedback_R,
ptr->ringbuffer_R, buflen_R, ptr->buffer_pos_R));
}
if (rev_outch <= 0.0f) {
*(output_L++) = out_L;
*(output_R++) = out_R;
} else {
*(output_L++) = out_R;
*(output_R++) = out_L;
}
}
}
void
set_run_adding_gain(LADSPA_Handle Instance, LADSPA_Data gain){
Echo * ptr;
ptr = (Echo *)Instance;
ptr->run_adding_gain = gain;
}
void
run_adding_gain_Echo(LADSPA_Handle Instance,
unsigned long SampleCount) {
Echo * ptr;
unsigned long sample_index;
LADSPA_Data delaytime_L;
LADSPA_Data delaytime_R;
LADSPA_Data feedback_L;
LADSPA_Data feedback_R;
LADSPA_Data strength_L;
LADSPA_Data strength_R;
LADSPA_Data drylevel;
LADSPA_Data mode;
LADSPA_Data haas;
LADSPA_Data rev_outch;
LADSPA_Data * input_L;
LADSPA_Data * output_L;
LADSPA_Data * input_R;
LADSPA_Data * output_R;
unsigned long sample_rate;
unsigned long buflen_L;
unsigned long buflen_R;
LADSPA_Data out_L = 0;
LADSPA_Data out_R = 0;
LADSPA_Data in_L = 0;
LADSPA_Data in_R = 0;
ptr = (Echo *)Instance;
delaytime_L = LIMIT(*(ptr->delaytime_L),0.0f,2000.0f);
delaytime_R = LIMIT(*(ptr->delaytime_R),0.0f,2000.0f);
feedback_L = LIMIT(*(ptr->feedback_L) / 100.0, 0.0f, 100.0f);
feedback_R = LIMIT(*(ptr->feedback_R) / 100.0, 0.0f, 100.0f);
strength_L = db2lin(LIMIT(*(ptr->strength_L),-70.0f,10.0f));
strength_R = db2lin(LIMIT(*(ptr->strength_R),-70.0f,10.0f));
drylevel = db2lin(LIMIT(*(ptr->drylevel),-70.0f,10.0f));
mode = LIMIT(*(ptr->mode),-2.0f,2.0f);
haas = LIMIT(*(ptr->haas),-2.0f,2.0f);
rev_outch = LIMIT(*(ptr->rev_outch),-2.0f,2.0f);
input_L = ptr->input_L;
output_L = ptr->output_L;
input_R = ptr->input_R;
output_R = ptr->output_R;
sample_rate = ptr->sample_rate;
buflen_L = delaytime_L * sample_rate / 1000;
buflen_R = delaytime_R * sample_rate / 1000;
for (sample_index = 0; sample_index < SampleCount; sample_index++) {
in_L = *(input_L++);
in_R = *(input_R++);
out_L = in_L * drylevel + ptr->mpx_out_L * strength_L;
out_R = in_R * drylevel + ptr->mpx_out_R * strength_R;
if (haas > 0.0f)
in_R = 0.0f;
if (mode <= 0.0f) {
ptr->mpx_out_L =
M(push_buffer(in_L + ptr->mpx_out_L * feedback_L,
ptr->ringbuffer_L, buflen_L, ptr->buffer_pos_L));
ptr->mpx_out_R =
M(push_buffer(in_R + ptr->mpx_out_R * feedback_R,
ptr->ringbuffer_R, buflen_R, ptr->buffer_pos_R));
} else {
ptr->mpx_out_R =
M(push_buffer(in_L + ptr->mpx_out_L * feedback_L,
ptr->ringbuffer_L, buflen_L, ptr->buffer_pos_L));
ptr->mpx_out_L =
M(push_buffer(in_R + ptr->mpx_out_R * feedback_R,
ptr->ringbuffer_R, buflen_R, ptr->buffer_pos_R));
}
if (rev_outch <= 0.0f) {
*(output_L++) += out_L * ptr->run_adding_gain;
*(output_R++) += out_R * ptr->run_adding_gain;
} else {
*(output_L++) += out_R * ptr->run_adding_gain;
*(output_R++) += out_L * ptr->run_adding_gain;
}
}
}
/* Throw away an Echo effect instance. */
void
cleanup_Echo(LADSPA_Handle Instance) {
Echo * ptr = (Echo *)Instance;
free(ptr->ringbuffer_L);
free(ptr->ringbuffer_R);
free(ptr->buffer_pos_L);
free(ptr->buffer_pos_R);
free(Instance);
}
LADSPA_Descriptor * stereo_descriptor = NULL;
/* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
loaded. */
void
__attribute__((constructor)) tap_init() {
char ** port_names;
LADSPA_PortDescriptor * port_descriptors;
LADSPA_PortRangeHint * port_range_hints;
if ((stereo_descriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
exit(1);
/* init the stereo Echo */
stereo_descriptor->UniqueID = ID_STEREO;
stereo_descriptor->Label = strdup("tap_stereo_echo");
stereo_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
stereo_descriptor->Name = strdup("TAP Stereo Echo");
stereo_descriptor->Maker = strdup("Tom Szilagyi");
stereo_descriptor->Copyright = strdup("GPL");
stereo_descriptor->PortCount = PORTCOUNT_STEREO;
if ((port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortDescriptor))) == NULL)
exit(1);
stereo_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
port_descriptors[DELAYTIME_L] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[DELAYTIME_R] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[FEEDBACK_L] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[FEEDBACK_R] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[STRENGTH_L] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[STRENGTH_R] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[DRYLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[MODE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[HAAS] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[REV_OUTCH] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[INPUT_L] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT_L] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
port_descriptors[INPUT_R] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT_R] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
if ((port_names =
(char **)calloc(PORTCOUNT_STEREO, sizeof(char *))) == NULL)
exit(1);
stereo_descriptor->PortNames = (const char **)port_names;
port_names[DELAYTIME_L] = strdup("L Delay [ms]");
port_names[DELAYTIME_R] = strdup("R/Haas Delay [ms]");
port_names[FEEDBACK_L] = strdup("L Feedback [%]");
port_names[FEEDBACK_R] = strdup("R/Haas Feedback [%]");
port_names[STRENGTH_L] = strdup("L Echo Level [dB]");
port_names[STRENGTH_R] = strdup("R Echo Level [dB]");
port_names[DRYLEVEL] = strdup("Dry Level [dB]");
port_names[MODE] = strdup("Cross Mode");
port_names[HAAS] = strdup("Haas Effect");
port_names[REV_OUTCH] = strdup("Swap Outputs");
port_names[INPUT_L] = strdup("Input Left");
port_names[OUTPUT_L] = strdup("Output Left");
port_names[INPUT_R] = strdup("Input Right");
port_names[OUTPUT_R] = strdup("Output Right");
if ((port_range_hints =
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortRangeHint)))) == NULL)
exit(1);
stereo_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
port_range_hints[DELAYTIME_L].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_100);
port_range_hints[DELAYTIME_L].LowerBound = 0;
port_range_hints[DELAYTIME_L].UpperBound = MAX_DELAY;
port_range_hints[DELAYTIME_R].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_100);
port_range_hints[DELAYTIME_R].LowerBound = 0;
port_range_hints[DELAYTIME_R].UpperBound = MAX_DELAY;
port_range_hints[FEEDBACK_L].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[FEEDBACK_L].LowerBound = 0;
port_range_hints[FEEDBACK_L].UpperBound = 100;
port_range_hints[FEEDBACK_R].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[FEEDBACK_R].LowerBound = 0;
port_range_hints[FEEDBACK_R].UpperBound = 100;
port_range_hints[STRENGTH_L].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[STRENGTH_L].LowerBound = -70;
port_range_hints[STRENGTH_L].UpperBound = 10;
port_range_hints[STRENGTH_R].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[STRENGTH_R].LowerBound = -70;
port_range_hints[STRENGTH_R].UpperBound = 10;
port_range_hints[MODE].HintDescriptor =
(LADSPA_HINT_TOGGLED |
LADSPA_HINT_DEFAULT_0);
port_range_hints[HAAS].HintDescriptor =
(LADSPA_HINT_TOGGLED |
LADSPA_HINT_DEFAULT_0);
port_range_hints[REV_OUTCH].HintDescriptor =
(LADSPA_HINT_TOGGLED |
LADSPA_HINT_DEFAULT_0);
port_range_hints[DRYLEVEL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[DRYLEVEL].LowerBound = -70;
port_range_hints[DRYLEVEL].UpperBound = 10;
port_range_hints[INPUT_L].HintDescriptor = 0;
port_range_hints[OUTPUT_L].HintDescriptor = 0;
port_range_hints[INPUT_R].HintDescriptor = 0;
port_range_hints[OUTPUT_R].HintDescriptor = 0;
stereo_descriptor->instantiate = instantiate_Echo;
stereo_descriptor->connect_port = connect_port_Echo;
stereo_descriptor->activate = activate_Echo;
stereo_descriptor->run = run_Echo;
stereo_descriptor->run_adding = run_adding_gain_Echo;
stereo_descriptor->set_run_adding_gain = set_run_adding_gain;
stereo_descriptor->deactivate = NULL;
stereo_descriptor->cleanup = cleanup_Echo;
}
void
delete_descriptor(LADSPA_Descriptor * descriptor) {
unsigned long index;
if (descriptor) {
free((char *)descriptor->Label);
free((char *)descriptor->Name);
free((char *)descriptor->Maker);
free((char *)descriptor->Copyright);
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
for (index = 0; index < descriptor->PortCount; index++)
free((char *)(descriptor->PortNames[index]));
free((char **)descriptor->PortNames);
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
free(descriptor);
}
}
/* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
void
__attribute__((destructor)) tap_fini() {
delete_descriptor(stereo_descriptor);
}
/* Return a descriptor of the requested plugin type. */
const
LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index) {
switch (Index) {
case 0:
return stereo_descriptor;
default:
return NULL;
}
}

View File

@@ -1,778 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_eq.c,v 1.7 2006/08/09 12:03:24 tszilagyi Exp $
*/
/* Please note that this plugin was inspired by and its code based
upon Steve Harris's "DJ EQ" plugin (no. 1901). While I give him
credit for his excellent work, I reserve myself to be blamed for any
bugs or malfunction. */
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ladspa.h>
#include "tap_utils.h"
/* The Unique ID of the plugin */
#define ID_MONO 2141
/* Bandwidth of EQ filters in octaves */
#define BWIDTH 1.0f
/* Port numbers */
#define EQ_CH0G 0
#define EQ_CH1G 1
#define EQ_CH2G 2
#define EQ_CH3G 3
#define EQ_CH4G 4
#define EQ_CH5G 5
#define EQ_CH6G 6
#define EQ_CH7G 7
#define EQ_CH0F 8
#define EQ_CH1F 9
#define EQ_CH2F 10
#define EQ_CH3F 11
#define EQ_CH4F 12
#define EQ_CH5F 13
#define EQ_CH6F 14
#define EQ_CH7F 15
#define EQ_INPUT 16
#define EQ_OUTPUT 17
/* Total number of ports */
#define PORTCOUNT_MONO 18
static LADSPA_Descriptor *eqDescriptor = NULL;
typedef struct {
LADSPA_Data *ch0f;
LADSPA_Data *ch0g;
LADSPA_Data *ch1f;
LADSPA_Data *ch1g;
LADSPA_Data *ch2f;
LADSPA_Data *ch2g;
LADSPA_Data *ch3f;
LADSPA_Data *ch3g;
LADSPA_Data *ch4f;
LADSPA_Data *ch4g;
LADSPA_Data *ch5f;
LADSPA_Data *ch5g;
LADSPA_Data *ch6f;
LADSPA_Data *ch6g;
LADSPA_Data *ch7f;
LADSPA_Data *ch7g;
LADSPA_Data *input;
LADSPA_Data *output;
biquad * filters;
float fs;
LADSPA_Data old_ch0f;
LADSPA_Data old_ch0g;
LADSPA_Data old_ch1f;
LADSPA_Data old_ch1g;
LADSPA_Data old_ch2f;
LADSPA_Data old_ch2g;
LADSPA_Data old_ch3f;
LADSPA_Data old_ch3g;
LADSPA_Data old_ch4f;
LADSPA_Data old_ch4g;
LADSPA_Data old_ch5f;
LADSPA_Data old_ch5g;
LADSPA_Data old_ch6f;
LADSPA_Data old_ch6g;
LADSPA_Data old_ch7f;
LADSPA_Data old_ch7g;
LADSPA_Data run_adding_gain;
} eq;
const
LADSPA_Descriptor *
ladspa_descriptor(unsigned long index) {
switch (index) {
case 0:
return eqDescriptor;
default:
return NULL;
}
}
static
void
activate_eq(LADSPA_Handle instance) {
eq *ptr = (eq *)instance;
biquad *filters = ptr->filters;
biquad_init(&filters[0]);
biquad_init(&filters[1]);
biquad_init(&filters[2]);
biquad_init(&filters[3]);
biquad_init(&filters[4]);
biquad_init(&filters[5]);
biquad_init(&filters[6]);
biquad_init(&filters[7]);
}
static
void
cleanup_eq(LADSPA_Handle instance) {
eq *plugin_data = (eq *)instance;
free(plugin_data->filters);
free(instance);
}
static
void
connectPort_eq(LADSPA_Handle instance, unsigned long port, LADSPA_Data *data) {
eq *plugin;
plugin = (eq *)instance;
switch (port) {
case EQ_CH0F:
plugin->ch0f = data;
break;
case EQ_CH0G:
plugin->ch0g = data;
break;
case EQ_CH1F:
plugin->ch1f = data;
break;
case EQ_CH1G:
plugin->ch1g = data;
break;
case EQ_CH2F:
plugin->ch2f = data;
break;
case EQ_CH2G:
plugin->ch2g = data;
break;
case EQ_CH3F:
plugin->ch3f = data;
break;
case EQ_CH3G:
plugin->ch3g = data;
break;
case EQ_CH4F:
plugin->ch4f = data;
break;
case EQ_CH4G:
plugin->ch4g = data;
break;
case EQ_CH5F:
plugin->ch5f = data;
break;
case EQ_CH5G:
plugin->ch5g = data;
break;
case EQ_CH6F:
plugin->ch6f = data;
break;
case EQ_CH6G:
plugin->ch6g = data;
break;
case EQ_CH7F:
plugin->ch7f = data;
break;
case EQ_CH7G:
plugin->ch7g = data;
break;
case EQ_INPUT:
plugin->input = data;
break;
case EQ_OUTPUT:
plugin->output = data;
break;
}
}
static
LADSPA_Handle
instantiate_eq(const LADSPA_Descriptor *descriptor, unsigned long s_rate) {
eq *ptr = (eq *)malloc(sizeof(eq));
biquad *filters = NULL;
float fs;
fs = s_rate;
memset(ptr, 0, sizeof(eq));
filters = calloc(8, sizeof(biquad));
ptr->filters = filters;
ptr->fs = fs;
ptr->run_adding_gain = 1.0f;
ptr->old_ch0f = 100.0f;
ptr->old_ch0g = 0;
ptr->old_ch1f = 200.0f;
ptr->old_ch1g = 0;
ptr->old_ch2f = 400.0f;
ptr->old_ch2g = 0;
ptr->old_ch3f = 1000.0f;
ptr->old_ch3g = 0;
ptr->old_ch4f = 3000.0f;
ptr->old_ch4g = 0;
ptr->old_ch5f = 6000.0f;
ptr->old_ch5g = 0;
ptr->old_ch6f = 12000.0f;
ptr->old_ch6g = 0;
ptr->old_ch7f = 15000.0f;
ptr->old_ch7g = 0;
eq_set_params(&filters[0], 100.0f, 0.0f, BWIDTH, fs);
eq_set_params(&filters[1], 200.0f, 0.0f, BWIDTH, fs);
eq_set_params(&filters[2], 400.0f, 0.0f, BWIDTH, fs);
eq_set_params(&filters[3], 1000.0f, 0.0f, BWIDTH, fs);
eq_set_params(&filters[4], 3000.0f, 0.0f, BWIDTH, fs);
eq_set_params(&filters[5], 6000.0f, 0.0f, BWIDTH, fs);
eq_set_params(&filters[6], 12000.0f, 0.0f, BWIDTH, fs);
eq_set_params(&filters[7], 15000.0f, 0.0f, BWIDTH, fs);
return (LADSPA_Handle)ptr;
}
static
void
run_eq(LADSPA_Handle instance, unsigned long sample_count) {
eq * ptr = (eq *)instance;
const LADSPA_Data ch0f = LIMIT(*(ptr->ch0f),40.0f,280.0f);
const LADSPA_Data ch0g = LIMIT(*(ptr->ch0g),-50.0f,20.0f);
const LADSPA_Data ch1f = LIMIT(*(ptr->ch1f),100.0f,500.0f);
const LADSPA_Data ch1g = LIMIT(*(ptr->ch1g),-50.0f,20.0f);
const LADSPA_Data ch2f = LIMIT(*(ptr->ch2f),200.0f,1000.0f);
const LADSPA_Data ch2g = LIMIT(*(ptr->ch2g),-50.0f,20.0f);
const LADSPA_Data ch3f = LIMIT(*(ptr->ch3f),400.0f,2800.0f);
const LADSPA_Data ch3g = LIMIT(*(ptr->ch3g),-50.0f,20.0f);
const LADSPA_Data ch4f = LIMIT(*(ptr->ch4f),1000.0f,5000.0f);
const LADSPA_Data ch4g = LIMIT(*(ptr->ch4g),-50.0f,20.0f);
const LADSPA_Data ch5f = LIMIT(*(ptr->ch5f),3000.0f,9000.0f);
const LADSPA_Data ch5g = LIMIT(*(ptr->ch5g),-50.0f,20.0f);
const LADSPA_Data ch6f = LIMIT(*(ptr->ch6f),6000.0f,18000.0f);
const LADSPA_Data ch6g = LIMIT(*(ptr->ch6g),-50.0f,20.0f);
const LADSPA_Data ch7f = LIMIT(*(ptr->ch7f),10000.0f,20000.0f);
const LADSPA_Data ch7g = LIMIT(*(ptr->ch7g),-50.0f,20.0f);
const LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
biquad * filters = ptr->filters;
float fs = ptr->fs;
unsigned long pos;
float samp;
if ((ch0f != ptr->old_ch0f) ||
(ch0g != ptr->old_ch0g)) {
ptr->old_ch0f = ch0f;
ptr->old_ch0g = ch0g;
eq_set_params(&filters[0], ch0f, ch0g, BWIDTH, fs);
}
if ((ch1f != ptr->old_ch1f) ||
(ch1g != ptr->old_ch1g)) {
ptr->old_ch1f = ch1f;
ptr->old_ch1g = ch1g;
eq_set_params(&filters[1], ch1f, ch1g, BWIDTH, fs);
}
if ((ch2f != ptr->old_ch2f) ||
(ch2g != ptr->old_ch2g)) {
ptr->old_ch2f = ch2f;
ptr->old_ch2g = ch2g;
eq_set_params(&filters[2], ch2f, ch2g, BWIDTH, fs);
}
if ((ch3f != ptr->old_ch3f) ||
(ch3g != ptr->old_ch3g)) {
ptr->old_ch3f = ch3f;
ptr->old_ch3g = ch3g;
eq_set_params(&filters[3], ch3f, ch3g, BWIDTH, fs);
}
if ((ch4f != ptr->old_ch4f) ||
(ch4g != ptr->old_ch4g)) {
ptr->old_ch4f = ch4f;
ptr->old_ch4g = ch4g;
eq_set_params(&filters[4], ch4f, ch4g, BWIDTH, fs);
}
if ((ch5f != ptr->old_ch5f) ||
(ch5g != ptr->old_ch5g)) {
ptr->old_ch5f = ch5f;
ptr->old_ch5g = ch5g;
eq_set_params(&filters[5], ch5f, ch5g, BWIDTH, fs);
}
if ((ch6f != ptr->old_ch6f) ||
(ch6g != ptr->old_ch6g)) {
ptr->old_ch6f = ch6f;
ptr->old_ch6g = ch6g;
eq_set_params(&filters[6], ch6f, ch6g, BWIDTH, fs);
}
if ((ch7f != ptr->old_ch7f) ||
(ch7g != ptr->old_ch7g)) {
ptr->old_ch7f = ch7f;
ptr->old_ch7g = ch7g;
eq_set_params(&filters[7], ch7f, ch7g, BWIDTH, fs);
}
for (pos = 0; pos < sample_count; pos++) {
samp = input[pos];
if (ch0g != 0.0f)
samp = biquad_run(&filters[0], samp);
if (ch1g != 0.0f)
samp = biquad_run(&filters[1], samp);
if (ch2g != 0.0f)
samp = biquad_run(&filters[2], samp);
if (ch3g != 0.0f)
samp = biquad_run(&filters[3], samp);
if (ch4g != 0.0f)
samp = biquad_run(&filters[4], samp);
if (ch5g != 0.0f)
samp = biquad_run(&filters[5], samp);
if (ch6g != 0.0f)
samp = biquad_run(&filters[6], samp);
if (ch7g != 0.0f)
samp = biquad_run(&filters[7], samp);
output[pos] = samp;
}
}
void
set_run_adding_gain(LADSPA_Handle instance, LADSPA_Data gain) {
eq * ptr = (eq *)instance;
ptr->run_adding_gain = gain;
}
static
void
run_adding_eq(LADSPA_Handle instance, unsigned long sample_count) {
eq * ptr = (eq *)instance;
const LADSPA_Data ch0f = LIMIT(*(ptr->ch0f),40.0f,280.0f);
const LADSPA_Data ch0g = LIMIT(*(ptr->ch0g),-50.0f,20.0f);
const LADSPA_Data ch1f = LIMIT(*(ptr->ch1f),100.0f,500.0f);
const LADSPA_Data ch1g = LIMIT(*(ptr->ch1g),-50.0f,20.0f);
const LADSPA_Data ch2f = LIMIT(*(ptr->ch2f),200.0f,1000.0f);
const LADSPA_Data ch2g = LIMIT(*(ptr->ch2g),-50.0f,20.0f);
const LADSPA_Data ch3f = LIMIT(*(ptr->ch3f),400.0f,2800.0f);
const LADSPA_Data ch3g = LIMIT(*(ptr->ch3g),-50.0f,20.0f);
const LADSPA_Data ch4f = LIMIT(*(ptr->ch4f),1000.0f,5000.0f);
const LADSPA_Data ch4g = LIMIT(*(ptr->ch4g),-50.0f,20.0f);
const LADSPA_Data ch5f = LIMIT(*(ptr->ch5f),3000.0f,9000.0f);
const LADSPA_Data ch5g = LIMIT(*(ptr->ch5g),-50.0f,20.0f);
const LADSPA_Data ch6f = LIMIT(*(ptr->ch6f),6000.0f,18000.0f);
const LADSPA_Data ch6g = LIMIT(*(ptr->ch6g),-50.0f,20.0f);
const LADSPA_Data ch7f = LIMIT(*(ptr->ch7f),10000.0f,20000.0f);
const LADSPA_Data ch7g = LIMIT(*(ptr->ch7g),-50.0f,20.0f);
const LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
biquad * filters = ptr->filters;
float fs = ptr->fs;
unsigned long pos;
float samp;
if ((ch0f != ptr->old_ch0f) ||
(ch0g != ptr->old_ch0g)) {
ptr->old_ch0f = ch0f;
ptr->old_ch0g = ch0g;
eq_set_params(&filters[0], ch0f, ch0g, BWIDTH, fs);
}
if ((ch1f != ptr->old_ch1f) ||
(ch1g != ptr->old_ch1g)) {
ptr->old_ch1f = ch1f;
ptr->old_ch1g = ch1g;
eq_set_params(&filters[1], ch1f, ch1g, BWIDTH, fs);
}
if ((ch2f != ptr->old_ch2f) ||
(ch2g != ptr->old_ch2g)) {
ptr->old_ch2f = ch2f;
ptr->old_ch2g = ch2g;
eq_set_params(&filters[2], ch2f, ch2g, BWIDTH, fs);
}
if ((ch3f != ptr->old_ch3f) ||
(ch3g != ptr->old_ch3g)) {
ptr->old_ch3f = ch3f;
ptr->old_ch3g = ch3g;
eq_set_params(&filters[3], ch3f, ch3g, BWIDTH, fs);
}
if ((ch4f != ptr->old_ch4f) ||
(ch4g != ptr->old_ch4g)) {
ptr->old_ch4f = ch4f;
ptr->old_ch4g = ch4g;
eq_set_params(&filters[4], ch4f, ch4g, BWIDTH, fs);
}
if ((ch5f != ptr->old_ch5f) ||
(ch5g != ptr->old_ch5g)) {
ptr->old_ch5f = ch5f;
ptr->old_ch5g = ch5g;
eq_set_params(&filters[5], ch5f, ch5g, BWIDTH, fs);
}
if ((ch6f != ptr->old_ch6f) ||
(ch6g != ptr->old_ch6g)) {
ptr->old_ch6f = ch6f;
ptr->old_ch6g = ch6g;
eq_set_params(&filters[6], ch6f, ch6g, BWIDTH, fs);
}
if ((ch7f != ptr->old_ch7f) ||
(ch7g != ptr->old_ch7g)) {
ptr->old_ch7f = ch7f;
ptr->old_ch7g = ch7g;
eq_set_params(&filters[7], ch7f, ch7g, BWIDTH, fs);
}
for (pos = 0; pos < sample_count; pos++) {
samp = input[pos];
if (ch0g != 0.0f)
samp = biquad_run(&filters[0], samp);
if (ch1g != 0.0f)
samp = biquad_run(&filters[1], samp);
if (ch2g != 0.0f)
samp = biquad_run(&filters[2], samp);
if (ch3g != 0.0f)
samp = biquad_run(&filters[3], samp);
if (ch4g != 0.0f)
samp = biquad_run(&filters[4], samp);
if (ch5g != 0.0f)
samp = biquad_run(&filters[5], samp);
if (ch6g != 0.0f)
samp = biquad_run(&filters[6], samp);
if (ch7g != 0.0f)
samp = biquad_run(&filters[7], samp);
output[pos] += ptr->run_adding_gain * samp;
}
}
void
__attribute__((constructor)) tap_init() {
char **port_names;
LADSPA_PortDescriptor *port_descriptors;
LADSPA_PortRangeHint *port_range_hints;
eqDescriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor));
if (eqDescriptor) {
eqDescriptor->UniqueID = ID_MONO;
eqDescriptor->Label = "tap_equalizer";
eqDescriptor->Properties = 0;
eqDescriptor->Name = "TAP Equalizer";
eqDescriptor->Maker = "Tom Szilagyi";
eqDescriptor->Copyright = "GPL";
eqDescriptor->PortCount = PORTCOUNT_MONO;
port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO,
sizeof(LADSPA_PortDescriptor));
eqDescriptor->PortDescriptors =
(const LADSPA_PortDescriptor *)port_descriptors;
port_range_hints =
(LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO,
sizeof(LADSPA_PortRangeHint));
eqDescriptor->PortRangeHints =
(const LADSPA_PortRangeHint *)port_range_hints;
port_names = (char **)calloc(PORTCOUNT_MONO, sizeof(char*));
eqDescriptor->PortNames =
(const char **)port_names;
/* Parameters for CH0 freq [Hz] */
port_descriptors[EQ_CH0F] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH0F] =
"Band 1 Freq [Hz]";
port_range_hints[EQ_CH0F].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_LOW;
port_range_hints[EQ_CH0F].LowerBound = 40;
port_range_hints[EQ_CH0F].UpperBound = 280;
/* Parameters for CH0 gain [dB] */
port_descriptors[EQ_CH0G] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH0G] =
"Band 1 Gain [dB]";
port_range_hints[EQ_CH0G].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0;
port_range_hints[EQ_CH0G].LowerBound = -50;
port_range_hints[EQ_CH0G].UpperBound = +20;
/* Parameters for CH1 freq [Hz] */
port_descriptors[EQ_CH1F] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH1F] =
"Band 2 Freq [Hz]";
port_range_hints[EQ_CH1F].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_LOW;
port_range_hints[EQ_CH1F].LowerBound = 100;
port_range_hints[EQ_CH1F].UpperBound = 500;
/* Parameters for CH1 gain [dB] */
port_descriptors[EQ_CH1G] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH1G] =
"Band 2 Gain [dB]";
port_range_hints[EQ_CH1G].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0;
port_range_hints[EQ_CH1G].LowerBound = -50;
port_range_hints[EQ_CH1G].UpperBound = +20;
/* Parameters for CH2 freq [Hz] */
port_descriptors[EQ_CH2F] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH2F] =
"Band 3 Freq [Hz]";
port_range_hints[EQ_CH2F].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_LOW;
port_range_hints[EQ_CH2F].LowerBound = 200;
port_range_hints[EQ_CH2F].UpperBound = 1000;
/* Parameters for CH2 gain [dB] */
port_descriptors[EQ_CH2G] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH2G] =
"Band 3 Gain [dB]";
port_range_hints[EQ_CH2G].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0;
port_range_hints[EQ_CH2G].LowerBound = -50;
port_range_hints[EQ_CH2G].UpperBound = +20;
/* Parameters for CH3 freq [Hz] */
port_descriptors[EQ_CH3F] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH3F] =
"Band 4 Freq [Hz]";
port_range_hints[EQ_CH3F].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_LOW;
port_range_hints[EQ_CH3F].LowerBound = 400;
port_range_hints[EQ_CH3F].UpperBound = 2800;
/* Parameters for CH3 gain [dB] */
port_descriptors[EQ_CH3G] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH3G] =
"Band 4 Gain [dB]";
port_range_hints[EQ_CH3G].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0;
port_range_hints[EQ_CH3G].LowerBound = -50;
port_range_hints[EQ_CH3G].UpperBound = +20;
/* Parameters for CH4 freq [Hz] */
port_descriptors[EQ_CH4F] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH4F] =
"Band 5 Freq [Hz]";
port_range_hints[EQ_CH4F].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MIDDLE;
port_range_hints[EQ_CH4F].LowerBound = 1000;
port_range_hints[EQ_CH4F].UpperBound = 5000;
/* Parameters for CH4 gain [dB] */
port_descriptors[EQ_CH4G] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH4G] =
"Band 5 Gain [dB]";
port_range_hints[EQ_CH4G].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0;
port_range_hints[EQ_CH4G].LowerBound = -50;
port_range_hints[EQ_CH4G].UpperBound = +20;
/* Parameters for CH5 freq [Hz] */
port_descriptors[EQ_CH5F] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH5F] =
"Band 6 Freq [Hz]";
port_range_hints[EQ_CH5F].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MIDDLE;
port_range_hints[EQ_CH5F].LowerBound = 3000;
port_range_hints[EQ_CH5F].UpperBound = 9000;
/* Parameters for CH5 gain [dB] */
port_descriptors[EQ_CH5G] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH5G] =
"Band 6 Gain [dB]";
port_range_hints[EQ_CH5G].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0;
port_range_hints[EQ_CH5G].LowerBound = -50;
port_range_hints[EQ_CH5G].UpperBound = +20;
/* Parameters for CH6 freq [Hz] */
port_descriptors[EQ_CH6F] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH6F] =
"Band 7 Freq [Hz]";
port_range_hints[EQ_CH6F].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MIDDLE;
port_range_hints[EQ_CH6F].LowerBound = 6000;
port_range_hints[EQ_CH6F].UpperBound = 18000;
/* Parameters for CH6 gain [dB] */
port_descriptors[EQ_CH6G] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH6G] =
"Band 7 Gain [dB]";
port_range_hints[EQ_CH6G].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0;
port_range_hints[EQ_CH6G].LowerBound = -50;
port_range_hints[EQ_CH6G].UpperBound = +20;
/* Parameters for CH7 freq [Hz] */
port_descriptors[EQ_CH7F] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH7F] =
"Band 8 Freq [Hz]";
port_range_hints[EQ_CH7F].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MIDDLE;
port_range_hints[EQ_CH7F].LowerBound = 10000;
port_range_hints[EQ_CH7F].UpperBound = 20000;
/* Parameters for CH7 gain [dB] */
port_descriptors[EQ_CH7G] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH7G] =
"Band 8 Gain [dB]";
port_range_hints[EQ_CH7G].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0;
port_range_hints[EQ_CH7G].LowerBound = -50;
port_range_hints[EQ_CH7G].UpperBound = +20;
/* Parameters for Input */
port_descriptors[EQ_INPUT] =
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_names[EQ_INPUT] =
"Input";
port_range_hints[EQ_INPUT].HintDescriptor = 0;
/* Parameters for Output */
port_descriptors[EQ_OUTPUT] =
LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
port_names[EQ_OUTPUT] =
"Output";
port_range_hints[EQ_OUTPUT].HintDescriptor = 0;
eqDescriptor->activate = activate_eq;
eqDescriptor->cleanup = cleanup_eq;
eqDescriptor->connect_port = connectPort_eq;
eqDescriptor->deactivate = NULL;
eqDescriptor->instantiate = instantiate_eq;
eqDescriptor->run = run_eq;
eqDescriptor->run_adding = run_adding_eq;
eqDescriptor->set_run_adding_gain = set_run_adding_gain;
}
}
void
__attribute__((destructor)) tap_fini() {
if (eqDescriptor) {
free((LADSPA_PortDescriptor *)eqDescriptor->PortDescriptors);
free((char **)eqDescriptor->PortNames);
free((LADSPA_PortRangeHint *)eqDescriptor->PortRangeHints);
free(eqDescriptor);
}
}

View File

@@ -1,968 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_eqbw.c,v 1.5 2006/08/09 12:03:24 tszilagyi Exp $
*/
/* This plugin is identical to TAP Equalizer (2141), but it has
* separate user controls for setting the bandwidth of every filter.
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ladspa.h>
#include "tap_utils.h"
/* The Unique ID of the plugin */
#define ID_MONO 2151
/* Default bandwidth of EQ filters in octaves */
#define BWIDTH 1.0f
/* Port numbers */
#define EQ_CH0G 0
#define EQ_CH1G 1
#define EQ_CH2G 2
#define EQ_CH3G 3
#define EQ_CH4G 4
#define EQ_CH5G 5
#define EQ_CH6G 6
#define EQ_CH7G 7
#define EQ_CH0F 8
#define EQ_CH1F 9
#define EQ_CH2F 10
#define EQ_CH3F 11
#define EQ_CH4F 12
#define EQ_CH5F 13
#define EQ_CH6F 14
#define EQ_CH7F 15
#define EQ_CH0B 16
#define EQ_CH1B 17
#define EQ_CH2B 18
#define EQ_CH3B 19
#define EQ_CH4B 20
#define EQ_CH5B 21
#define EQ_CH6B 22
#define EQ_CH7B 23
#define EQ_INPUT 24
#define EQ_OUTPUT 25
/* Total number of ports */
#define PORTCOUNT_MONO 26
static LADSPA_Descriptor *eqDescriptor = NULL;
typedef struct {
LADSPA_Data *ch0f;
LADSPA_Data *ch0g;
LADSPA_Data *ch0b;
LADSPA_Data *ch1f;
LADSPA_Data *ch1g;
LADSPA_Data *ch1b;
LADSPA_Data *ch2f;
LADSPA_Data *ch2g;
LADSPA_Data *ch2b;
LADSPA_Data *ch3f;
LADSPA_Data *ch3g;
LADSPA_Data *ch3b;
LADSPA_Data *ch4f;
LADSPA_Data *ch4g;
LADSPA_Data *ch4b;
LADSPA_Data *ch5f;
LADSPA_Data *ch5g;
LADSPA_Data *ch5b;
LADSPA_Data *ch6f;
LADSPA_Data *ch6g;
LADSPA_Data *ch6b;
LADSPA_Data *ch7f;
LADSPA_Data *ch7g;
LADSPA_Data *ch7b;
LADSPA_Data *input;
LADSPA_Data *output;
biquad * filters;
float fs;
LADSPA_Data old_ch0f;
LADSPA_Data old_ch0g;
LADSPA_Data old_ch0b;
LADSPA_Data old_ch1f;
LADSPA_Data old_ch1g;
LADSPA_Data old_ch1b;
LADSPA_Data old_ch2f;
LADSPA_Data old_ch2g;
LADSPA_Data old_ch2b;
LADSPA_Data old_ch3f;
LADSPA_Data old_ch3g;
LADSPA_Data old_ch3b;
LADSPA_Data old_ch4f;
LADSPA_Data old_ch4g;
LADSPA_Data old_ch4b;
LADSPA_Data old_ch5f;
LADSPA_Data old_ch5g;
LADSPA_Data old_ch5b;
LADSPA_Data old_ch6f;
LADSPA_Data old_ch6g;
LADSPA_Data old_ch6b;
LADSPA_Data old_ch7f;
LADSPA_Data old_ch7g;
LADSPA_Data old_ch7b;
LADSPA_Data run_adding_gain;
} eq;
const
LADSPA_Descriptor *
ladspa_descriptor(unsigned long index) {
switch (index) {
case 0:
return eqDescriptor;
default:
return NULL;
}
}
static
void
activate_eq(LADSPA_Handle instance) {
eq *ptr = (eq *)instance;
biquad *filters = ptr->filters;
biquad_init(&filters[0]);
biquad_init(&filters[1]);
biquad_init(&filters[2]);
biquad_init(&filters[3]);
biquad_init(&filters[4]);
biquad_init(&filters[5]);
biquad_init(&filters[6]);
biquad_init(&filters[7]);
}
static
void
cleanup_eq(LADSPA_Handle instance) {
eq *plugin_data = (eq *)instance;
free(plugin_data->filters);
free(instance);
}
static
void
connectPort_eq(LADSPA_Handle instance, unsigned long port, LADSPA_Data *data) {
eq *plugin;
plugin = (eq *)instance;
switch (port) {
case EQ_CH0F:
plugin->ch0f = data;
break;
case EQ_CH0G:
plugin->ch0g = data;
break;
case EQ_CH0B:
plugin->ch0b = data;
break;
case EQ_CH1F:
plugin->ch1f = data;
break;
case EQ_CH1G:
plugin->ch1g = data;
break;
case EQ_CH1B:
plugin->ch1b = data;
break;
case EQ_CH2F:
plugin->ch2f = data;
break;
case EQ_CH2G:
plugin->ch2g = data;
break;
case EQ_CH2B:
plugin->ch2b = data;
break;
case EQ_CH3F:
plugin->ch3f = data;
break;
case EQ_CH3G:
plugin->ch3g = data;
break;
case EQ_CH3B:
plugin->ch3b = data;
break;
case EQ_CH4F:
plugin->ch4f = data;
break;
case EQ_CH4G:
plugin->ch4g = data;
break;
case EQ_CH4B:
plugin->ch4b = data;
break;
case EQ_CH5F:
plugin->ch5f = data;
break;
case EQ_CH5G:
plugin->ch5g = data;
break;
case EQ_CH5B:
plugin->ch5b = data;
break;
case EQ_CH6F:
plugin->ch6f = data;
break;
case EQ_CH6G:
plugin->ch6g = data;
break;
case EQ_CH6B:
plugin->ch6b = data;
break;
case EQ_CH7F:
plugin->ch7f = data;
break;
case EQ_CH7G:
plugin->ch7g = data;
break;
case EQ_CH7B:
plugin->ch7b = data;
break;
case EQ_INPUT:
plugin->input = data;
break;
case EQ_OUTPUT:
plugin->output = data;
break;
}
}
static
LADSPA_Handle
instantiate_eq(const LADSPA_Descriptor *descriptor, unsigned long s_rate) {
eq *ptr = (eq *)malloc(sizeof(eq));
biquad *filters = NULL;
float fs;
fs = s_rate;
memset(ptr, 0, sizeof(eq));
filters = calloc(8, sizeof(biquad));
ptr->filters = filters;
ptr->fs = fs;
ptr->run_adding_gain = 1.0f;
ptr->old_ch0f = 100.0f;
ptr->old_ch0g = 0.0f;
ptr->old_ch0b = BWIDTH;
ptr->old_ch1f = 200.0f;
ptr->old_ch1g = 0.0f;
ptr->old_ch1b = BWIDTH;
ptr->old_ch2f = 400.0f;
ptr->old_ch2g = 0.0f;
ptr->old_ch2b = BWIDTH;
ptr->old_ch3f = 1000.0f;
ptr->old_ch3g = 0.0f;
ptr->old_ch3b = BWIDTH;
ptr->old_ch4f = 3000.0f;
ptr->old_ch4g = 0.0f;
ptr->old_ch4b = BWIDTH;
ptr->old_ch5f = 6000.0f;
ptr->old_ch5g = 0.0f;
ptr->old_ch5b = BWIDTH;
ptr->old_ch6f = 12000.0f;
ptr->old_ch6g = 0.0f;
ptr->old_ch6b = BWIDTH;
ptr->old_ch7f = 15000.0f;
ptr->old_ch7g = 0.0f;
ptr->old_ch7b = BWIDTH;
eq_set_params(&filters[0], 100.0f, 0.0f, BWIDTH, fs);
eq_set_params(&filters[1], 200.0f, 0.0f, BWIDTH, fs);
eq_set_params(&filters[2], 400.0f, 0.0f, BWIDTH, fs);
eq_set_params(&filters[3], 1000.0f, 0.0f, BWIDTH, fs);
eq_set_params(&filters[4], 3000.0f, 0.0f, BWIDTH, fs);
eq_set_params(&filters[5], 6000.0f, 0.0f, BWIDTH, fs);
eq_set_params(&filters[6], 12000.0f, 0.0f, BWIDTH, fs);
eq_set_params(&filters[7], 15000.0f, 0.0f, BWIDTH, fs);
return (LADSPA_Handle)ptr;
}
static
void
run_eq(LADSPA_Handle instance, unsigned long sample_count) {
eq * ptr = (eq *)instance;
const LADSPA_Data ch0f = LIMIT(*(ptr->ch0f),40.0f,280.0f);
const LADSPA_Data ch0g = LIMIT(*(ptr->ch0g),-50.0f,20.0f);
const LADSPA_Data ch0b = LIMIT(*(ptr->ch0b),0.1f,5.0f);
const LADSPA_Data ch1f = LIMIT(*(ptr->ch1f),100.0f,500.0f);
const LADSPA_Data ch1g = LIMIT(*(ptr->ch1g),-50.0f,20.0f);
const LADSPA_Data ch1b = LIMIT(*(ptr->ch1b),0.1f,5.0f);
const LADSPA_Data ch2f = LIMIT(*(ptr->ch2f),200.0f,1000.0f);
const LADSPA_Data ch2g = LIMIT(*(ptr->ch2g),-50.0f,20.0f);
const LADSPA_Data ch2b = LIMIT(*(ptr->ch2b),0.1f,5.0f);
const LADSPA_Data ch3f = LIMIT(*(ptr->ch3f),400.0f,2800.0f);
const LADSPA_Data ch3g = LIMIT(*(ptr->ch3g),-50.0f,20.0f);
const LADSPA_Data ch3b = LIMIT(*(ptr->ch3b),0.1f,5.0f);
const LADSPA_Data ch4f = LIMIT(*(ptr->ch4f),1000.0f,5000.0f);
const LADSPA_Data ch4g = LIMIT(*(ptr->ch4g),-50.0f,20.0f);
const LADSPA_Data ch4b = LIMIT(*(ptr->ch4b),0.1f,5.0f);
const LADSPA_Data ch5f = LIMIT(*(ptr->ch5f),3000.0f,9000.0f);
const LADSPA_Data ch5g = LIMIT(*(ptr->ch5g),-50.0f,20.0f);
const LADSPA_Data ch5b = LIMIT(*(ptr->ch5b),0.1f,5.0f);
const LADSPA_Data ch6f = LIMIT(*(ptr->ch6f),6000.0f,18000.0f);
const LADSPA_Data ch6g = LIMIT(*(ptr->ch6g),-50.0f,20.0f);
const LADSPA_Data ch6b = LIMIT(*(ptr->ch6b),0.1f,5.0f);
const LADSPA_Data ch7f = LIMIT(*(ptr->ch7f),10000.0f,20000.0f);
const LADSPA_Data ch7g = LIMIT(*(ptr->ch7g),-50.0f,20.0f);
const LADSPA_Data ch7b = LIMIT(*(ptr->ch7b),0.1f,5.0f);
const LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
biquad * filters = ptr->filters;
float fs = ptr->fs;
unsigned long pos;
float samp;
if ((ch0f != ptr->old_ch0f) ||
(ch0g != ptr->old_ch0g) ||
(ch0b != ptr->old_ch0b)) {
ptr->old_ch0f = ch0f;
ptr->old_ch0g = ch0g;
ptr->old_ch0b = ch0b;
eq_set_params(&filters[0], ch0f, ch0g, ch0b, fs);
}
if ((ch1f != ptr->old_ch1f) ||
(ch1g != ptr->old_ch1g) ||
(ch1b != ptr->old_ch1b)) {
ptr->old_ch1f = ch1f;
ptr->old_ch1g = ch1g;
ptr->old_ch1b = ch1b;
eq_set_params(&filters[1], ch1f, ch1g, ch1b, fs);
}
if ((ch2f != ptr->old_ch2f) ||
(ch2g != ptr->old_ch2g) ||
(ch2b != ptr->old_ch2b)) {
ptr->old_ch2f = ch2f;
ptr->old_ch2g = ch2g;
ptr->old_ch2b = ch2b;
eq_set_params(&filters[2], ch2f, ch2g, ch2b, fs);
}
if ((ch3f != ptr->old_ch3f) ||
(ch3g != ptr->old_ch3g) ||
(ch3b != ptr->old_ch3b)) {
ptr->old_ch3f = ch3f;
ptr->old_ch3g = ch3g;
ptr->old_ch3b = ch3b;
eq_set_params(&filters[3], ch3f, ch3g, ch3b, fs);
}
if ((ch4f != ptr->old_ch4f) ||
(ch4g != ptr->old_ch4g) ||
(ch4b != ptr->old_ch4b)) {
ptr->old_ch4f = ch4f;
ptr->old_ch4g = ch4g;
ptr->old_ch4b = ch4b;
eq_set_params(&filters[4], ch4f, ch4g, ch4b, fs);
}
if ((ch5f != ptr->old_ch5f) ||
(ch5g != ptr->old_ch5g) ||
(ch5b != ptr->old_ch5b)) {
ptr->old_ch5f = ch5f;
ptr->old_ch5g = ch5g;
ptr->old_ch5b = ch5b;
eq_set_params(&filters[5], ch5f, ch5g, ch5b, fs);
}
if ((ch6f != ptr->old_ch6f) ||
(ch6g != ptr->old_ch6g) ||
(ch6b != ptr->old_ch6b)) {
ptr->old_ch6f = ch6f;
ptr->old_ch6g = ch6g;
ptr->old_ch6b = ch6b;
eq_set_params(&filters[6], ch6f, ch6g, ch6b, fs);
}
if ((ch7f != ptr->old_ch7f) ||
(ch7g != ptr->old_ch7g) ||
(ch7b != ptr->old_ch7b)) {
ptr->old_ch7f = ch7f;
ptr->old_ch7g = ch7g;
ptr->old_ch7b = ch7b;
eq_set_params(&filters[7], ch7f, ch7g, ch7b, fs);
}
for (pos = 0; pos < sample_count; pos++) {
samp = input[pos];
if (ch0g != 0.0f)
samp = biquad_run(&filters[0], samp);
if (ch1g != 0.0f)
samp = biquad_run(&filters[1], samp);
if (ch2g != 0.0f)
samp = biquad_run(&filters[2], samp);
if (ch3g != 0.0f)
samp = biquad_run(&filters[3], samp);
if (ch4g != 0.0f)
samp = biquad_run(&filters[4], samp);
if (ch5g != 0.0f)
samp = biquad_run(&filters[5], samp);
if (ch6g != 0.0f)
samp = biquad_run(&filters[6], samp);
if (ch7g != 0.0f)
samp = biquad_run(&filters[7], samp);
output[pos] = samp;
}
}
void
set_run_adding_gain(LADSPA_Handle instance, LADSPA_Data gain) {
eq * ptr = (eq *)instance;
ptr->run_adding_gain = gain;
}
static
void
run_adding_eq(LADSPA_Handle instance, unsigned long sample_count) {
eq * ptr = (eq *)instance;
const LADSPA_Data ch0f = LIMIT(*(ptr->ch0f),40.0f,280.0f);
const LADSPA_Data ch0g = LIMIT(*(ptr->ch0g),-50.0f,20.0f);
const LADSPA_Data ch0b = LIMIT(*(ptr->ch0b),0.1f,5.0f);
const LADSPA_Data ch1f = LIMIT(*(ptr->ch1f),100.0f,500.0f);
const LADSPA_Data ch1g = LIMIT(*(ptr->ch1g),-50.0f,20.0f);
const LADSPA_Data ch1b = LIMIT(*(ptr->ch1b),0.1f,5.0f);
const LADSPA_Data ch2f = LIMIT(*(ptr->ch2f),200.0f,1000.0f);
const LADSPA_Data ch2g = LIMIT(*(ptr->ch2g),-50.0f,20.0f);
const LADSPA_Data ch2b = LIMIT(*(ptr->ch2b),0.1f,5.0f);
const LADSPA_Data ch3f = LIMIT(*(ptr->ch3f),400.0f,2800.0f);
const LADSPA_Data ch3g = LIMIT(*(ptr->ch3g),-50.0f,20.0f);
const LADSPA_Data ch3b = LIMIT(*(ptr->ch3b),0.1f,5.0f);
const LADSPA_Data ch4f = LIMIT(*(ptr->ch4f),1000.0f,5000.0f);
const LADSPA_Data ch4g = LIMIT(*(ptr->ch4g),-50.0f,20.0f);
const LADSPA_Data ch4b = LIMIT(*(ptr->ch4b),0.1f,5.0f);
const LADSPA_Data ch5f = LIMIT(*(ptr->ch5f),3000.0f,9000.0f);
const LADSPA_Data ch5g = LIMIT(*(ptr->ch5g),-50.0f,20.0f);
const LADSPA_Data ch5b = LIMIT(*(ptr->ch5b),0.1f,5.0f);
const LADSPA_Data ch6f = LIMIT(*(ptr->ch6f),6000.0f,18000.0f);
const LADSPA_Data ch6g = LIMIT(*(ptr->ch6g),-50.0f,20.0f);
const LADSPA_Data ch6b = LIMIT(*(ptr->ch6b),0.1f,5.0f);
const LADSPA_Data ch7f = LIMIT(*(ptr->ch7f),10000.0f,20000.0f);
const LADSPA_Data ch7g = LIMIT(*(ptr->ch7g),-50.0f,20.0f);
const LADSPA_Data ch7b = LIMIT(*(ptr->ch7b),0.1f,5.0f);
const LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
biquad * filters = ptr->filters;
float fs = ptr->fs;
unsigned long pos;
float samp;
if ((ch0f != ptr->old_ch0f) ||
(ch0g != ptr->old_ch0g) ||
(ch0b != ptr->old_ch0b)) {
ptr->old_ch0f = ch0f;
ptr->old_ch0g = ch0g;
ptr->old_ch0b = ch0b;
eq_set_params(&filters[0], ch0f, ch0g, ch0b, fs);
}
if ((ch1f != ptr->old_ch1f) ||
(ch1g != ptr->old_ch1g) ||
(ch1b != ptr->old_ch1b)) {
ptr->old_ch1f = ch1f;
ptr->old_ch1g = ch1g;
ptr->old_ch1b = ch1b;
eq_set_params(&filters[1], ch1f, ch1g, ch1b, fs);
}
if ((ch2f != ptr->old_ch2f) ||
(ch2g != ptr->old_ch2g) ||
(ch2b != ptr->old_ch2b)) {
ptr->old_ch2f = ch2f;
ptr->old_ch2g = ch2g;
ptr->old_ch2b = ch2b;
eq_set_params(&filters[2], ch2f, ch2g, ch2b, fs);
}
if ((ch3f != ptr->old_ch3f) ||
(ch3g != ptr->old_ch3g) ||
(ch3b != ptr->old_ch3b)) {
ptr->old_ch3f = ch3f;
ptr->old_ch3g = ch3g;
ptr->old_ch3b = ch3b;
eq_set_params(&filters[3], ch3f, ch3g, ch3b, fs);
}
if ((ch4f != ptr->old_ch4f) ||
(ch4g != ptr->old_ch4g) ||
(ch4b != ptr->old_ch4b)) {
ptr->old_ch4f = ch4f;
ptr->old_ch4g = ch4g;
ptr->old_ch4b = ch4b;
eq_set_params(&filters[4], ch4f, ch4g, ch4b, fs);
}
if ((ch5f != ptr->old_ch5f) ||
(ch5g != ptr->old_ch5g) ||
(ch5b != ptr->old_ch5b)) {
ptr->old_ch5f = ch5f;
ptr->old_ch5g = ch5g;
ptr->old_ch5b = ch5b;
eq_set_params(&filters[5], ch5f, ch5g, ch5b, fs);
}
if ((ch6f != ptr->old_ch6f) ||
(ch6g != ptr->old_ch6g) ||
(ch6b != ptr->old_ch6b)) {
ptr->old_ch6f = ch6f;
ptr->old_ch6g = ch6g;
ptr->old_ch6b = ch6b;
eq_set_params(&filters[6], ch6f, ch6g, ch6b, fs);
}
if ((ch7f != ptr->old_ch7f) ||
(ch7g != ptr->old_ch7g) ||
(ch7b != ptr->old_ch7b)) {
ptr->old_ch7f = ch7f;
ptr->old_ch7g = ch7g;
ptr->old_ch7b = ch7b;
eq_set_params(&filters[7], ch7f, ch7g, ch7b, fs);
}
for (pos = 0; pos < sample_count; pos++) {
samp = input[pos];
if (ch0g != 0.0f)
samp = biquad_run(&filters[0], samp);
if (ch1g != 0.0f)
samp = biquad_run(&filters[1], samp);
if (ch2g != 0.0f)
samp = biquad_run(&filters[2], samp);
if (ch3g != 0.0f)
samp = biquad_run(&filters[3], samp);
if (ch4g != 0.0f)
samp = biquad_run(&filters[4], samp);
if (ch5g != 0.0f)
samp = biquad_run(&filters[5], samp);
if (ch6g != 0.0f)
samp = biquad_run(&filters[6], samp);
if (ch7g != 0.0f)
samp = biquad_run(&filters[7], samp);
output[pos] += ptr->run_adding_gain * samp;
}
}
void
__attribute__((constructor)) tap_init() {
char **port_names;
LADSPA_PortDescriptor *port_descriptors;
LADSPA_PortRangeHint *port_range_hints;
eqDescriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor));
if (eqDescriptor) {
eqDescriptor->UniqueID = ID_MONO;
eqDescriptor->Label = "tap_equalizer_bw";
eqDescriptor->Properties = 0;
eqDescriptor->Name = "TAP Equalizer/BW";
eqDescriptor->Maker = "Tom Szilagyi";
eqDescriptor->Copyright = "GPL";
eqDescriptor->PortCount = PORTCOUNT_MONO;
port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO,
sizeof(LADSPA_PortDescriptor));
eqDescriptor->PortDescriptors =
(const LADSPA_PortDescriptor *)port_descriptors;
port_range_hints =
(LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO,
sizeof(LADSPA_PortRangeHint));
eqDescriptor->PortRangeHints =
(const LADSPA_PortRangeHint *)port_range_hints;
port_names = (char **)calloc(PORTCOUNT_MONO, sizeof(char*));
eqDescriptor->PortNames =
(const char **)port_names;
/* Parameters for CH0 freq [Hz] */
port_descriptors[EQ_CH0F] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH0F] =
"Band 1 Freq [Hz]";
port_range_hints[EQ_CH0F].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_LOW;
port_range_hints[EQ_CH0F].LowerBound = 40;
port_range_hints[EQ_CH0F].UpperBound = 280;
/* Parameters for CH0 gain [dB] */
port_descriptors[EQ_CH0G] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH0G] =
"Band 1 Gain [dB]";
port_range_hints[EQ_CH0G].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0;
port_range_hints[EQ_CH0G].LowerBound = -50;
port_range_hints[EQ_CH0G].UpperBound = +20;
/* Parameters for CH0 bandwidth [octaves] */
port_descriptors[EQ_CH0B] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH0B] =
"Band 1 Bandwidth [octaves]";
port_range_hints[EQ_CH0B].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_1;
port_range_hints[EQ_CH0B].LowerBound = 0.1f;
port_range_hints[EQ_CH0B].UpperBound = 5.0f;
/* Parameters for CH1 freq [Hz] */
port_descriptors[EQ_CH1F] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH1F] =
"Band 2 Freq [Hz]";
port_range_hints[EQ_CH1F].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_LOW;
port_range_hints[EQ_CH1F].LowerBound = 100;
port_range_hints[EQ_CH1F].UpperBound = 500;
/* Parameters for CH1 gain [dB] */
port_descriptors[EQ_CH1G] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH1G] =
"Band 2 Gain [dB]";
port_range_hints[EQ_CH1G].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0;
port_range_hints[EQ_CH1G].LowerBound = -50;
port_range_hints[EQ_CH1G].UpperBound = +20;
/* Parameters for CH1 bandwidth [octaves] */
port_descriptors[EQ_CH1B] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH1B] =
"Band 2 Bandwidth [octaves]";
port_range_hints[EQ_CH1B].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_1;
port_range_hints[EQ_CH1B].LowerBound = 0.1f;
port_range_hints[EQ_CH1B].UpperBound = 5.0f;
/* Parameters for CH2 freq [Hz] */
port_descriptors[EQ_CH2F] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH2F] =
"Band 3 Freq [Hz]";
port_range_hints[EQ_CH2F].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_LOW;
port_range_hints[EQ_CH2F].LowerBound = 200;
port_range_hints[EQ_CH2F].UpperBound = 1000;
/* Parameters for CH2 gain [dB] */
port_descriptors[EQ_CH2G] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH2G] =
"Band 3 Gain [dB]";
port_range_hints[EQ_CH2G].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0;
port_range_hints[EQ_CH2G].LowerBound = -50;
port_range_hints[EQ_CH2G].UpperBound = +20;
/* Parameters for CH2 bandwidth [octaves] */
port_descriptors[EQ_CH2B] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH2B] =
"Band 3 Bandwidth [octaves]";
port_range_hints[EQ_CH2B].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_1;
port_range_hints[EQ_CH2B].LowerBound = 0.1f;
port_range_hints[EQ_CH2B].UpperBound = 5.0f;
/* Parameters for CH3 freq [Hz] */
port_descriptors[EQ_CH3F] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH3F] =
"Band 4 Freq [Hz]";
port_range_hints[EQ_CH3F].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_LOW;
port_range_hints[EQ_CH3F].LowerBound = 400;
port_range_hints[EQ_CH3F].UpperBound = 2800;
/* Parameters for CH3 gain [dB] */
port_descriptors[EQ_CH3G] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH3G] =
"Band 4 Gain [dB]";
port_range_hints[EQ_CH3G].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0;
port_range_hints[EQ_CH3G].LowerBound = -50;
port_range_hints[EQ_CH3G].UpperBound = +20;
/* Parameters for CH3 bandwidth [octaves] */
port_descriptors[EQ_CH3B] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH3B] =
"Band 4 Bandwidth [octaves]";
port_range_hints[EQ_CH3B].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_1;
port_range_hints[EQ_CH3B].LowerBound = 0.1f;
port_range_hints[EQ_CH3B].UpperBound = 5.0f;
/* Parameters for CH4 freq [Hz] */
port_descriptors[EQ_CH4F] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH4F] =
"Band 5 Freq [Hz]";
port_range_hints[EQ_CH4F].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MIDDLE;
port_range_hints[EQ_CH4F].LowerBound = 1000;
port_range_hints[EQ_CH4F].UpperBound = 5000;
/* Parameters for CH4 gain [dB] */
port_descriptors[EQ_CH4G] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH4G] =
"Band 5 Gain [dB]";
port_range_hints[EQ_CH4G].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0;
port_range_hints[EQ_CH4G].LowerBound = -50;
port_range_hints[EQ_CH4G].UpperBound = +20;
/* Parameters for CH4 bandwidth [octaves] */
port_descriptors[EQ_CH4B] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH4B] =
"Band 5 Bandwidth [octaves]";
port_range_hints[EQ_CH4B].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_1;
port_range_hints[EQ_CH4B].LowerBound = 0.1f;
port_range_hints[EQ_CH4B].UpperBound = 5.0f;
/* Parameters for CH5 freq [Hz] */
port_descriptors[EQ_CH5F] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH5F] =
"Band 6 Freq [Hz]";
port_range_hints[EQ_CH5F].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MIDDLE;
port_range_hints[EQ_CH5F].LowerBound = 3000;
port_range_hints[EQ_CH5F].UpperBound = 9000;
/* Parameters for CH5 gain [dB] */
port_descriptors[EQ_CH5G] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH5G] =
"Band 6 Gain [dB]";
port_range_hints[EQ_CH5G].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0;
port_range_hints[EQ_CH5G].LowerBound = -50;
port_range_hints[EQ_CH5G].UpperBound = +20;
/* Parameters for CH5 bandwidth [octaves] */
port_descriptors[EQ_CH5B] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH5B] =
"Band 6 Bandwidth [octaves]";
port_range_hints[EQ_CH5B].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_1;
port_range_hints[EQ_CH5B].LowerBound = 0.1f;
port_range_hints[EQ_CH5B].UpperBound = 5.0f;
/* Parameters for CH6 freq [Hz] */
port_descriptors[EQ_CH6F] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH6F] =
"Band 7 Freq [Hz]";
port_range_hints[EQ_CH6F].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MIDDLE;
port_range_hints[EQ_CH6F].LowerBound = 6000;
port_range_hints[EQ_CH6F].UpperBound = 18000;
/* Parameters for CH6 gain [dB] */
port_descriptors[EQ_CH6G] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH6G] =
"Band 7 Gain [dB]";
port_range_hints[EQ_CH6G].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0;
port_range_hints[EQ_CH6G].LowerBound = -50;
port_range_hints[EQ_CH6G].UpperBound = +20;
/* Parameters for CH6 bandwidth [octaves] */
port_descriptors[EQ_CH6B] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH6B] =
"Band 7 Bandwidth [octaves]";
port_range_hints[EQ_CH6B].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_1;
port_range_hints[EQ_CH6B].LowerBound = 0.1f;
port_range_hints[EQ_CH6B].UpperBound = 5.0f;
/* Parameters for CH7 freq [Hz] */
port_descriptors[EQ_CH7F] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH7F] =
"Band 8 Freq [Hz]";
port_range_hints[EQ_CH7F].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MIDDLE;
port_range_hints[EQ_CH7F].LowerBound = 10000;
port_range_hints[EQ_CH7F].UpperBound = 20000;
/* Parameters for CH7 gain [dB] */
port_descriptors[EQ_CH7G] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH7G] =
"Band 8 Gain [dB]";
port_range_hints[EQ_CH7G].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0;
port_range_hints[EQ_CH7G].LowerBound = -50;
port_range_hints[EQ_CH7G].UpperBound = +20;
/* Parameters for CH7 bandwidth [octaves] */
port_descriptors[EQ_CH7B] =
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_names[EQ_CH7B] =
"Band 8 Bandwidth [octaves]";
port_range_hints[EQ_CH7B].HintDescriptor =
LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_1;
port_range_hints[EQ_CH7B].LowerBound = 0.1f;
port_range_hints[EQ_CH7B].UpperBound = 5.0f;
/* Parameters for Input */
port_descriptors[EQ_INPUT] =
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_names[EQ_INPUT] =
"Input";
port_range_hints[EQ_INPUT].HintDescriptor = 0;
/* Parameters for Output */
port_descriptors[EQ_OUTPUT] =
LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
port_names[EQ_OUTPUT] =
"Output";
port_range_hints[EQ_OUTPUT].HintDescriptor = 0;
eqDescriptor->activate = activate_eq;
eqDescriptor->cleanup = cleanup_eq;
eqDescriptor->connect_port = connectPort_eq;
eqDescriptor->deactivate = NULL;
eqDescriptor->instantiate = instantiate_eq;
eqDescriptor->run = run_eq;
eqDescriptor->run_adding = run_adding_eq;
eqDescriptor->set_run_adding_gain = set_run_adding_gain;
}
}
void
__attribute__((destructor)) tap_fini() {
if (eqDescriptor) {
free((LADSPA_PortDescriptor *)eqDescriptor->PortDescriptors);
free((char **)eqDescriptor->PortNames);
free((LADSPA_PortRangeHint *)eqDescriptor->PortRangeHints);
free(eqDescriptor);
}
}

View File

@@ -1,443 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_limiter.c,v 1.5 2004/02/21 17:33:36 tszilagyi Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ladspa.h>
#include "tap_utils.h"
/* The Unique ID of the plugin: */
#define ID_MONO 2145
/* The port numbers for the plugin: */
#define LIMIT_VOL 0
#define OUT_VOL 1
#define LATENCY 2
#define INPUT 3
#define OUTPUT 4
/* Total number of ports */
#define PORTCOUNT_MONO 5
/* Size of a ringbuffer that must be large enough to hold audio
* between two zero-crosses in any case (or you'll hear
* distortion). 40 Hz sound at 192kHz yields a half-period of 2400
* samples, so this should be enough.
*/
#define RINGBUF_SIZE 2500
/* The structure used to hold port connection information and state */
typedef struct {
LADSPA_Data * limit_vol;
LADSPA_Data * out_vol;
LADSPA_Data * latency;
LADSPA_Data * input;
LADSPA_Data * output;
LADSPA_Data * ringbuffer;
unsigned long buflen;
unsigned long pos;
unsigned long ready_num;
unsigned long sample_rate;
LADSPA_Data run_adding_gain;
} Limiter;
/* Construct a new plugin instance. */
LADSPA_Handle
instantiate_Limiter(const LADSPA_Descriptor * Descriptor,
unsigned long sample_rate) {
LADSPA_Handle * ptr;
if ((ptr = malloc(sizeof(Limiter))) != NULL) {
((Limiter *)ptr)->sample_rate = sample_rate;
((Limiter *)ptr)->run_adding_gain = 1.0f;
if ((((Limiter *)ptr)->ringbuffer =
calloc(RINGBUF_SIZE, sizeof(LADSPA_Data))) == NULL)
return NULL;
/* 80 Hz is the lowest frequency with which zero-crosses were
* observed to occur (this corresponds to 40 Hz signal frequency).
*/
((Limiter *)ptr)->buflen = ((Limiter *)ptr)->sample_rate / 80;
((Limiter *)ptr)->pos = 0;
((Limiter *)ptr)->ready_num = 0;
return ptr;
}
return NULL;
}
void
activate_Limiter(LADSPA_Handle Instance) {
Limiter * ptr = (Limiter *)Instance;
unsigned long i;
for (i = 0; i < RINGBUF_SIZE; i++)
ptr->ringbuffer[i] = 0.0f;
}
/* Connect a port to a data location. */
void
connect_port_Limiter(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * DataLocation) {
Limiter * ptr = (Limiter *)Instance;
switch (Port) {
case LIMIT_VOL:
ptr->limit_vol = DataLocation;
break;
case OUT_VOL:
ptr->out_vol = DataLocation;
break;
case LATENCY:
ptr->latency = DataLocation;
*(ptr->latency) = ptr->buflen; /* IS THIS LEGAL? */
break;
case INPUT:
ptr->input = DataLocation;
break;
case OUTPUT:
ptr->output = DataLocation;
break;
}
}
void
run_Limiter(LADSPA_Handle Instance,
unsigned long SampleCount) {
Limiter * ptr = (Limiter *)Instance;
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
LADSPA_Data limit_vol = db2lin(LIMIT(*(ptr->limit_vol),-30.0f,20.0f));
LADSPA_Data out_vol = db2lin(LIMIT(*(ptr->out_vol),-30.0f,20.0f));
unsigned long sample_index;
unsigned long sample_count = SampleCount;
unsigned long index_offs = 0;
unsigned long i;
LADSPA_Data max_value = 0;
LADSPA_Data section_gain = 0;
unsigned long run_length;
unsigned long total_length = 0;
while (total_length < sample_count) {
run_length = ptr->buflen;
if (total_length + run_length > sample_count)
run_length = sample_count - total_length;
while (ptr->ready_num < run_length) {
if (read_buffer(ptr->ringbuffer, ptr->buflen,
ptr->pos, ptr->ready_num) >= 0.0f) {
index_offs = 0;
while ((read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos,
ptr->ready_num + index_offs) >= 0.0f) &&
(ptr->ready_num + index_offs < run_length)) {
index_offs++;
}
} else {
index_offs = 0;
while ((read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos,
ptr->ready_num + index_offs) <= 0.0f) &&
(ptr->ready_num + index_offs < run_length)) {
index_offs++;
}
}
/* search for max value in scanned halfcycle */
max_value = 0;
for (i = ptr->ready_num; i < ptr->ready_num + index_offs; i++) {
if (fabs(read_buffer(ptr->ringbuffer, ptr->buflen,
ptr->pos, i)) > max_value)
max_value = fabs(read_buffer(ptr->ringbuffer,
ptr->buflen, ptr->pos, i));
}
section_gain = limit_vol / max_value;
if (max_value > limit_vol)
for (i = ptr->ready_num; i < ptr->ready_num + index_offs; i++) {
write_buffer(read_buffer(ptr->ringbuffer, ptr->buflen,
ptr->pos, i) * section_gain,
ptr->ringbuffer, ptr->buflen, ptr->pos, i);
}
ptr->ready_num += index_offs;
}
/* push run_length values out of ringbuffer, feed with input */
for (sample_index = 0; sample_index < run_length; sample_index++) {
*(output++) = out_vol *
push_buffer(*(input++), ptr->ringbuffer,
ptr->buflen, &(ptr->pos));
}
ptr->ready_num -= run_length;
total_length += run_length;
}
*(ptr->latency) = ptr->buflen;
}
void
set_run_adding_gain_Limiter(LADSPA_Handle Instance, LADSPA_Data gain) {
Limiter * ptr = (Limiter *)Instance;
ptr->run_adding_gain = gain;
}
void
run_adding_Limiter(LADSPA_Handle Instance,
unsigned long SampleCount) {
Limiter * ptr = (Limiter *)Instance;
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
LADSPA_Data limit_vol = db2lin(LIMIT(*(ptr->limit_vol),-30.0f,20.0f));
LADSPA_Data out_vol = db2lin(LIMIT(*(ptr->out_vol),-30.0f,20.0f));
unsigned long sample_index;
unsigned long sample_count = SampleCount;
unsigned long index_offs = 0;
unsigned long i;
LADSPA_Data max_value = 0;
LADSPA_Data section_gain = 0;
unsigned long run_length;
unsigned long total_length = 0;
while (total_length < sample_count) {
run_length = ptr->buflen;
if (total_length + run_length > sample_count)
run_length = sample_count - total_length;
while (ptr->ready_num < run_length) {
if (read_buffer(ptr->ringbuffer, ptr->buflen,
ptr->pos, ptr->ready_num) >= 0.0f) {
index_offs = 0;
while ((read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos,
ptr->ready_num + index_offs) >= 0.0f) &&
(ptr->ready_num + index_offs < run_length)) {
index_offs++;
}
} else {
index_offs = 0;
while ((read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos,
ptr->ready_num + index_offs) <= 0.0f) &&
(ptr->ready_num + index_offs < run_length)) {
index_offs++;
}
}
/* search for max value in scanned halfcycle */
max_value = 0;
for (i = ptr->ready_num; i < ptr->ready_num + index_offs; i++) {
if (fabs(read_buffer(ptr->ringbuffer, ptr->buflen,
ptr->pos, i)) > max_value)
max_value = fabs(read_buffer(ptr->ringbuffer,
ptr->buflen, ptr->pos, i));
}
section_gain = limit_vol / max_value;
if (max_value > limit_vol)
for (i = ptr->ready_num; i < ptr->ready_num + index_offs; i++) {
write_buffer(read_buffer(ptr->ringbuffer, ptr->buflen,
ptr->pos, i) * section_gain,
ptr->ringbuffer, ptr->buflen, ptr->pos, i);
}
ptr->ready_num += index_offs;
}
/* push run_length values out of ringbuffer, feed with input */
for (sample_index = 0; sample_index < run_length; sample_index++) {
*(output++) += ptr->run_adding_gain * out_vol *
push_buffer(*(input++), ptr->ringbuffer,
ptr->buflen, &(ptr->pos));
}
ptr->ready_num -= run_length;
total_length += run_length;
}
*(ptr->latency) = ptr->buflen;
}
/* Throw away a Limiter effect instance. */
void
cleanup_Limiter(LADSPA_Handle Instance) {
Limiter * ptr = (Limiter *)Instance;
free(ptr->ringbuffer);
free(Instance);
}
LADSPA_Descriptor * mono_descriptor = NULL;
/* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
loaded. */
void
__attribute__((constructor)) tap_init() {
char ** port_names;
LADSPA_PortDescriptor * port_descriptors;
LADSPA_PortRangeHint * port_range_hints;
if ((mono_descriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
exit(1);
mono_descriptor->UniqueID = ID_MONO;
mono_descriptor->Label = strdup("tap_limiter");
mono_descriptor->Properties = 0;
mono_descriptor->Name = strdup("TAP Scaling Limiter");
mono_descriptor->Maker = strdup("Tom Szilagyi");
mono_descriptor->Copyright = strdup("GPL");
mono_descriptor->PortCount = PORTCOUNT_MONO;
if ((port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
exit(1);
mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
port_descriptors[LIMIT_VOL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[OUT_VOL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[LATENCY] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
port_descriptors[INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
if ((port_names =
(char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
exit(1);
mono_descriptor->PortNames = (const char **)port_names;
port_names[LIMIT_VOL] = strdup("Limit Level [dB]");
port_names[OUT_VOL] = strdup("Output Volume [dB]");
port_names[LATENCY] = strdup("latency");
port_names[INPUT] = strdup("Input");
port_names[OUTPUT] = strdup("Output");
if ((port_range_hints =
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
exit(1);
mono_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
port_range_hints[LIMIT_VOL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[OUT_VOL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[LATENCY].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MAXIMUM);
port_range_hints[LIMIT_VOL].LowerBound = -30;
port_range_hints[LIMIT_VOL].UpperBound = +20;
port_range_hints[OUT_VOL].LowerBound = -30;
port_range_hints[OUT_VOL].UpperBound = +20;
port_range_hints[LATENCY].LowerBound = 0;
port_range_hints[LATENCY].UpperBound = RINGBUF_SIZE + 0.1f;
port_range_hints[INPUT].HintDescriptor = 0;
port_range_hints[OUTPUT].HintDescriptor = 0;
mono_descriptor->instantiate = instantiate_Limiter;
mono_descriptor->connect_port = connect_port_Limiter;
mono_descriptor->activate = activate_Limiter;
mono_descriptor->run = run_Limiter;
mono_descriptor->run_adding = run_adding_Limiter;
mono_descriptor->set_run_adding_gain = set_run_adding_gain_Limiter;
mono_descriptor->deactivate = NULL;
mono_descriptor->cleanup = cleanup_Limiter;
}
void
delete_descriptor(LADSPA_Descriptor * descriptor) {
unsigned long index;
if (descriptor) {
free((char *)descriptor->Label);
free((char *)descriptor->Name);
free((char *)descriptor->Maker);
free((char *)descriptor->Copyright);
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
for (index = 0; index < descriptor->PortCount; index++)
free((char *)(descriptor->PortNames[index]));
free((char **)descriptor->PortNames);
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
free(descriptor);
}
}
/* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
void
__attribute__((destructor)) tap_fini() {
delete_descriptor(mono_descriptor);
}
/* Return a descriptor of the requested plugin type. */
const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index) {
switch (Index) {
case 0:
return mono_descriptor;
default:
return NULL;
}
}

View File

@@ -1,345 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_pinknoise.c,v 1.2 2004/08/13 18:34:31 tszilagyi Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <ladspa.h>
#include "tap_utils.h"
/* The Unique ID of the plugin: */
#define ID_MONO 2155
/* The port numbers for the plugin: */
#define HURST 0
#define SIGNAL 1
#define NOISE 2
#define INPUT 3
#define OUTPUT 4
/* Total number of ports */
#define PORTCOUNT_MONO 5
#define NOISE_LEN 1024
/* The structure used to hold port connection information and state */
typedef struct {
LADSPA_Data * hurst;
LADSPA_Data * signal;
LADSPA_Data * noise;
LADSPA_Data * input;
LADSPA_Data * output;
LADSPA_Data * ring;
unsigned long buflen;
unsigned long pos;
unsigned long sample_rate;
LADSPA_Data run_adding_gain;
} Pinknoise;
/* generate fractal pattern using Midpoint Displacement Method
* v: buffer of floats to output fractal pattern to
* N: length of v, MUST be integer power of 2 (ie 128, 256, ...)
* H: Hurst constant, between 0 and 0.9999 (fractal dimension)
*/
void
fractal(LADSPA_Data * v, int N, float H) {
int l = N;
int k;
float r = 2.0f * H*H + 0.3f;
int c;
v[0] = 0;
while (l > 1) {
k = N / l;
for (c = 0; c < k; c++) {
v[c*l + l/2] = (v[c*l] + v[((c+1) * l) % N]) / 2.0f +
2.0f * r * (rand() - (float)RAND_MAX/2.0f) / (float)RAND_MAX;
v[c*l + l/2] = LIMIT(v[c*l + l/2], -1.0f, 1.0f);
}
l /= 2;
r /= powf(2, H);
}
}
/* Construct a new plugin instance. */
LADSPA_Handle
instantiate_Pinknoise(const LADSPA_Descriptor * Descriptor,
unsigned long SampleRate) {
LADSPA_Handle * ptr;
if ((ptr = malloc(sizeof(Pinknoise))) != NULL) {
((Pinknoise *)ptr)->sample_rate = SampleRate;
((Pinknoise *)ptr)->run_adding_gain = 1.0;
if ((((Pinknoise *)ptr)->ring =
calloc(NOISE_LEN, sizeof(LADSPA_Data))) == NULL)
return NULL;
((Pinknoise *)ptr)->buflen = NOISE_LEN;
((Pinknoise *)ptr)->pos = 0;
return ptr;
}
return NULL;
}
/* Connect a port to a data location. */
void
connect_port_Pinknoise(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * data) {
Pinknoise * ptr;
ptr = (Pinknoise *)Instance;
switch (Port) {
case HURST:
ptr->hurst = data;
break;
case SIGNAL:
ptr->signal = data;
break;
case NOISE:
ptr->noise = data;
break;
case INPUT:
ptr->input = data;
break;
case OUTPUT:
ptr->output = data;
break;
}
}
void
run_Pinknoise(LADSPA_Handle Instance,
unsigned long SampleCount) {
Pinknoise * ptr = (Pinknoise *)Instance;
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
LADSPA_Data hurst = LIMIT(*(ptr->hurst), 0.0f, 1.0f);
LADSPA_Data signal = db2lin(LIMIT(*(ptr->signal), -90.0f, 20.0f));
LADSPA_Data noise = db2lin(LIMIT(*(ptr->noise), -90.0f, 20.0f));
unsigned long sample_index;
for (sample_index = 0; sample_index < SampleCount; sample_index++) {
if (!ptr->pos)
fractal(ptr->ring, NOISE_LEN, hurst);
*(output++) = signal * *(input++) +
noise * push_buffer(0.0f, ptr->ring, ptr->buflen, &(ptr->pos));
}
}
void
set_run_adding_gain_Pinknoise(LADSPA_Handle Instance, LADSPA_Data gain) {
Pinknoise * ptr;
ptr = (Pinknoise *)Instance;
ptr->run_adding_gain = gain;
}
void
run_adding_Pinknoise(LADSPA_Handle Instance,
unsigned long SampleCount) {
Pinknoise * ptr = (Pinknoise *)Instance;
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
LADSPA_Data hurst = LIMIT(*(ptr->hurst), 0.0f, 1.0f);
LADSPA_Data signal = db2lin(LIMIT(*(ptr->signal), -90.0f, 20.0f));
LADSPA_Data noise = db2lin(LIMIT(*(ptr->noise), -90.0f, 20.0f));
unsigned long sample_index;
for (sample_index = 0; sample_index < SampleCount; sample_index++) {
if (!ptr->pos)
fractal(ptr->ring, NOISE_LEN, hurst);
*(output++) += ptr->run_adding_gain * (signal * *(input++) +
noise * push_buffer(0.0f, ptr->ring,
ptr->buflen, &(ptr->pos)));
}
}
/* Throw away a Pinknoise effect instance. */
void
cleanup_Pinknoise(LADSPA_Handle Instance) {
Pinknoise * ptr = (Pinknoise *)Instance;
free(ptr->ring);
free(Instance);
}
LADSPA_Descriptor * mono_descriptor = NULL;
/* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
loaded. */
void
__attribute__((constructor)) tap_init() {
char ** port_names;
LADSPA_PortDescriptor * port_descriptors;
LADSPA_PortRangeHint * port_range_hints;
if ((mono_descriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
exit(1);
/* initialize RNG */
// srand(time(0));
mono_descriptor->UniqueID = ID_MONO;
mono_descriptor->Label = strdup("tap_pinknoise");
mono_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
mono_descriptor->Name = strdup("TAP Pink/Fractal Noise");
mono_descriptor->Maker = strdup("Tom Szilagyi");
mono_descriptor->Copyright = strdup("GPL");
mono_descriptor->PortCount = PORTCOUNT_MONO;
if ((port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
exit(1);
mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
port_descriptors[HURST] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[SIGNAL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[NOISE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
if ((port_names =
(char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
exit(1);
mono_descriptor->PortNames = (const char **)port_names;
port_names[HURST] = strdup("Fractal Dimension");
port_names[SIGNAL] = strdup("Signal Level [dB]");
port_names[NOISE] = strdup("Noise Level [dB]");
port_names[INPUT] = strdup("Input");
port_names[OUTPUT] = strdup("Output");
if ((port_range_hints =
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
exit(1);
mono_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
port_range_hints[HURST].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MIDDLE);
port_range_hints[SIGNAL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[NOISE].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MINIMUM);
port_range_hints[HURST].LowerBound = 0.0f;
port_range_hints[HURST].UpperBound = 1.0f;
port_range_hints[SIGNAL].LowerBound = -90.0f;
port_range_hints[SIGNAL].UpperBound = 20.0f;
port_range_hints[NOISE].LowerBound = -90.0f;
port_range_hints[NOISE].UpperBound = 20.0f;
port_range_hints[INPUT].HintDescriptor = 0;
port_range_hints[OUTPUT].HintDescriptor = 0;
mono_descriptor->instantiate = instantiate_Pinknoise;
mono_descriptor->connect_port = connect_port_Pinknoise;
mono_descriptor->activate = NULL;
mono_descriptor->run = run_Pinknoise;
mono_descriptor->run_adding = run_adding_Pinknoise;
mono_descriptor->set_run_adding_gain = set_run_adding_gain_Pinknoise;
mono_descriptor->deactivate = NULL;
mono_descriptor->cleanup = cleanup_Pinknoise;
}
void
delete_descriptor(LADSPA_Descriptor * descriptor) {
unsigned long index;
if (descriptor) {
free((char *)descriptor->Label);
free((char *)descriptor->Name);
free((char *)descriptor->Maker);
free((char *)descriptor->Copyright);
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
for (index = 0; index < descriptor->PortCount; index++)
free((char *)(descriptor->PortNames[index]));
free((char **)descriptor->PortNames);
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
free(descriptor);
}
}
/* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
void
__attribute__((destructor)) tap_fini() {
delete_descriptor(mono_descriptor);
}
/* Return a descriptor of the requested plugin type. */
const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index) {
switch (Index) {
case 0:
return mono_descriptor;
default:
return NULL;
}
}

View File

@@ -1,556 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_pitch.c,v 1.2 2004/02/21 17:33:36 tszilagyi Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ladspa.h>
#include "tap_utils.h"
/* The Unique ID of the plugin: */
#define ID_MONO 2150
/* The port numbers for the plugin: */
#define SEMITONE 0
#define RATE 1
#define DRYLEVEL 2
#define WETLEVEL 3
#define LATENCY 4
#define INPUT 5
#define OUTPUT 6
/* Total number of ports */
#define PORTCOUNT_MONO 7
/* depth of phase mod (yes, this is a magic number) */
#define PM_DEPTH 3681.0f
/* another magic number, derived from the above one */
#define PM_BUFLEN 16027
/* frequency of the modulation signal (Hz) */
#define PM_FREQ 6.0f
#define COS_TABLE_SIZE 1024
LADSPA_Data cos_table[COS_TABLE_SIZE];
/* \sqrt{12}{2} used for key frequency computing */
#define ROOT_12_2 1.059463094f
/* The structure used to hold port connection information and state */
typedef struct {
LADSPA_Data * rate;
LADSPA_Data * semitone;
LADSPA_Data * drylevel;
LADSPA_Data * wetlevel;
LADSPA_Data * latency;
LADSPA_Data * input;
LADSPA_Data * output;
LADSPA_Data * ringbuffer;
unsigned long buflen;
unsigned long pos;
LADSPA_Data phase;
unsigned long sample_rate;
LADSPA_Data run_adding_gain;
} Pitch;
/* Construct a new plugin instance. */
LADSPA_Handle
instantiate_Pitch(const LADSPA_Descriptor * Descriptor,
unsigned long sample_rate) {
LADSPA_Handle * ptr;
if ((ptr = malloc(sizeof(Pitch))) != NULL) {
((Pitch *)ptr)->sample_rate = sample_rate;
((Pitch *)ptr)->run_adding_gain = 1.0f;
if ((((Pitch *)ptr)->ringbuffer =
calloc(2 * PM_BUFLEN, sizeof(LADSPA_Data))) == NULL)
return NULL;
((Pitch *)ptr)->buflen = 2 * PM_BUFLEN * sample_rate / 192000;
((Pitch *)ptr)->pos = 0;
return ptr;
}
return NULL;
}
void
activate_Pitch(LADSPA_Handle Instance) {
Pitch * ptr = (Pitch *)Instance;
unsigned long i;
for (i = 0; i < ptr->buflen; i++)
ptr->ringbuffer[i] = 0.0f;
ptr->phase = 0.0f;
}
/* Connect a port to a data location. */
void
connect_port_Pitch(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * DataLocation) {
Pitch * ptr = (Pitch *)Instance;
switch (Port) {
case RATE:
ptr->rate = DataLocation;
break;
case SEMITONE:
ptr->semitone = DataLocation;
break;
case DRYLEVEL:
ptr->drylevel = DataLocation;
break;
case WETLEVEL:
ptr->wetlevel = DataLocation;
break;
case LATENCY:
ptr->latency = DataLocation;
*(ptr->latency) = ptr->buflen / 2; /* IS THIS LEGAL? */
break;
case INPUT:
ptr->input = DataLocation;
break;
case OUTPUT:
ptr->output = DataLocation;
break;
}
}
void
run_Pitch(LADSPA_Handle Instance,
unsigned long SampleCount) {
Pitch * ptr = (Pitch *)Instance;
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
LADSPA_Data wetlevel = 0.333333f * db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
LADSPA_Data buflen = ptr->buflen / 2.0f;
LADSPA_Data semitone = LIMIT(*(ptr->semitone),-12.0f,12.0f);
LADSPA_Data rate;
LADSPA_Data r;
LADSPA_Data depth;
unsigned long sample_index;
unsigned long sample_count = SampleCount;
LADSPA_Data in = 0.0f;
LADSPA_Data sign = 1.0f;
LADSPA_Data phase_0 = 0.0f;
LADSPA_Data phase_am_0 = 0.0f;
LADSPA_Data phase_1 = 0.0f;
LADSPA_Data phase_am_1 = 0.0f;
LADSPA_Data phase_2 = 0.0f;
LADSPA_Data phase_am_2 = 0.0f;
LADSPA_Data fpos_0 = 0.0f, fpos_1 = 0.0f, fpos_2 = 0.0f;
LADSPA_Data n_0 = 0.0f, n_1 = 0.0f, n_2 = 0.0f;
LADSPA_Data rem_0 = 0.0f, rem_1 = 0.0f, rem_2 = 0.0f;
LADSPA_Data sa_0, sb_0, sa_1, sb_1, sa_2, sb_2;
if (semitone == 0.0f)
rate = LIMIT(*(ptr->rate),-50.0f,100.0f);
else
rate = 100.0f * (powf(ROOT_12_2,semitone) - 1.0f);
r = -1.0f * ABS(rate);
depth = buflen * LIMIT(ABS(r) / 100.0f, 0.0f, 1.0f);
if (rate > 0.0f)
sign = -1.0f;
for (sample_index = 0; sample_index < sample_count; sample_index++) {
in = *(input++);
phase_0 = COS_TABLE_SIZE * PM_FREQ * sample_index / ptr->sample_rate + ptr->phase;
while (phase_0 >= COS_TABLE_SIZE)
phase_0 -= COS_TABLE_SIZE;
phase_am_0 = phase_0 + COS_TABLE_SIZE/2;
while (phase_am_0 >= COS_TABLE_SIZE)
phase_am_0 -= COS_TABLE_SIZE;
phase_1 = phase_0 + COS_TABLE_SIZE/3.0f;
while (phase_1 >= COS_TABLE_SIZE)
phase_1 -= COS_TABLE_SIZE;
phase_am_1 = phase_1 + COS_TABLE_SIZE/2;
while (phase_am_1 >= COS_TABLE_SIZE)
phase_am_1 -= COS_TABLE_SIZE;
phase_2 = phase_0 + 2.0f*COS_TABLE_SIZE/3.0f;
while (phase_2 >= COS_TABLE_SIZE)
phase_2 -= COS_TABLE_SIZE;
phase_am_2 = phase_2 + COS_TABLE_SIZE/2;
while (phase_am_2 >= COS_TABLE_SIZE)
phase_am_2 -= COS_TABLE_SIZE;
push_buffer(in, ptr->ringbuffer, ptr->buflen, &(ptr->pos));
fpos_0 = depth * (1.0f - sign * (2.0f * phase_0 / COS_TABLE_SIZE - 1.0f));
n_0 = floorf(fpos_0);
rem_0 = fpos_0 - n_0;
fpos_1 = depth * (1.0f - sign * (2.0f * phase_1 / COS_TABLE_SIZE - 1.0f));
n_1 = floorf(fpos_1);
rem_1 = fpos_1 - n_1;
fpos_2 = depth * (1.0f - sign * (2.0f * phase_2 / COS_TABLE_SIZE - 1.0f));
n_2 = floorf(fpos_2);
rem_2 = fpos_2 - n_2;
sa_0 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_0);
sb_0 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_0 + 1);
sa_1 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_1);
sb_1 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_1 + 1);
sa_2 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_2);
sb_2 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_2 + 1);
*(output++) =
wetlevel *
((1.0f + cos_table[(unsigned long) phase_am_0]) *
((1 - rem_0) * sa_0 + rem_0 * sb_0) +
(1.0f + cos_table[(unsigned long) phase_am_1]) *
((1 - rem_1) * sa_1 + rem_1 * sb_1) +
(1.0f + cos_table[(unsigned long) phase_am_2]) *
((1 - rem_2) * sa_2 + rem_2 * sb_2)) +
drylevel *
read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) depth);
}
ptr->phase += COS_TABLE_SIZE * PM_FREQ * sample_index / ptr->sample_rate;
while (ptr->phase >= COS_TABLE_SIZE)
ptr->phase -= COS_TABLE_SIZE;
*(ptr->latency) = buflen - (unsigned long) depth;
}
void
set_run_adding_gain_Pitch(LADSPA_Handle Instance, LADSPA_Data gain) {
Pitch * ptr = (Pitch *)Instance;
ptr->run_adding_gain = gain;
}
void
run_adding_Pitch(LADSPA_Handle Instance,
unsigned long SampleCount) {
Pitch * ptr = (Pitch *)Instance;
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
LADSPA_Data wetlevel = 0.333333f * db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
LADSPA_Data buflen = ptr->buflen / 2.0f;
LADSPA_Data semitone = LIMIT(*(ptr->semitone),-12.0f,12.0f);
LADSPA_Data rate;
LADSPA_Data r;
LADSPA_Data depth;
unsigned long sample_index;
unsigned long sample_count = SampleCount;
LADSPA_Data in = 0.0f;
LADSPA_Data sign = 1.0f;
LADSPA_Data phase_0 = 0.0f;
LADSPA_Data phase_am_0 = 0.0f;
LADSPA_Data phase_1 = 0.0f;
LADSPA_Data phase_am_1 = 0.0f;
LADSPA_Data phase_2 = 0.0f;
LADSPA_Data phase_am_2 = 0.0f;
LADSPA_Data fpos_0 = 0.0f, fpos_1 = 0.0f, fpos_2 = 0.0f;
LADSPA_Data n_0 = 0.0f, n_1 = 0.0f, n_2 = 0.0f;
LADSPA_Data rem_0 = 0.0f, rem_1 = 0.0f, rem_2 = 0.0f;
LADSPA_Data sa_0, sb_0, sa_1, sb_1, sa_2, sb_2;
if (semitone == 0.0f)
rate = LIMIT(*(ptr->rate),-50.0f,100.0f);
else
rate = 100.0f * (powf(ROOT_12_2,semitone) - 1.0f);
r = -1.0f * ABS(rate);
depth = buflen * LIMIT(ABS(r) / 100.0f, 0.0f, 1.0f);
if (rate > 0.0f)
sign = -1.0f;
for (sample_index = 0; sample_index < sample_count; sample_index++) {
in = *(input++);
phase_0 = COS_TABLE_SIZE * PM_FREQ * sample_index / ptr->sample_rate + ptr->phase;
while (phase_0 >= COS_TABLE_SIZE)
phase_0 -= COS_TABLE_SIZE;
phase_am_0 = phase_0 + COS_TABLE_SIZE/2;
while (phase_am_0 >= COS_TABLE_SIZE)
phase_am_0 -= COS_TABLE_SIZE;
phase_1 = phase_0 + COS_TABLE_SIZE/3.0f;
while (phase_1 >= COS_TABLE_SIZE)
phase_1 -= COS_TABLE_SIZE;
phase_am_1 = phase_1 + COS_TABLE_SIZE/2;
while (phase_am_1 >= COS_TABLE_SIZE)
phase_am_1 -= COS_TABLE_SIZE;
phase_2 = phase_0 + 2.0f*COS_TABLE_SIZE/3.0f;
while (phase_2 >= COS_TABLE_SIZE)
phase_2 -= COS_TABLE_SIZE;
phase_am_2 = phase_2 + COS_TABLE_SIZE/2;
while (phase_am_2 >= COS_TABLE_SIZE)
phase_am_2 -= COS_TABLE_SIZE;
push_buffer(in, ptr->ringbuffer, ptr->buflen, &(ptr->pos));
fpos_0 = depth * (1.0f - sign * (2.0f * phase_0 / COS_TABLE_SIZE - 1.0f));
n_0 = floorf(fpos_0);
rem_0 = fpos_0 - n_0;
fpos_1 = depth * (1.0f - sign * (2.0f * phase_1 / COS_TABLE_SIZE - 1.0f));
n_1 = floorf(fpos_1);
rem_1 = fpos_1 - n_1;
fpos_2 = depth * (1.0f - sign * (2.0f * phase_2 / COS_TABLE_SIZE - 1.0f));
n_2 = floorf(fpos_2);
rem_2 = fpos_2 - n_2;
sa_0 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_0);
sb_0 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_0 + 1);
sa_1 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_1);
sb_1 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_1 + 1);
sa_2 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_2);
sb_2 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_2 + 1);
*(output++) += ptr->run_adding_gain *
wetlevel *
((1.0f + cos_table[(unsigned long) phase_am_0]) *
((1 - rem_0) * sa_0 + rem_0 * sb_0) +
(1.0f + cos_table[(unsigned long) phase_am_1]) *
((1 - rem_1) * sa_1 + rem_1 * sb_1) +
(1.0f + cos_table[(unsigned long) phase_am_2]) *
((1 - rem_2) * sa_2 + rem_2 * sb_2)) +
drylevel *
read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) depth);
}
ptr->phase += COS_TABLE_SIZE * PM_FREQ * sample_index / ptr->sample_rate;
while (ptr->phase >= COS_TABLE_SIZE)
ptr->phase -= COS_TABLE_SIZE;
*(ptr->latency) = buflen - (unsigned long) depth;
}
/* Throw away a Pitch effect instance. */
void
cleanup_Pitch(LADSPA_Handle Instance) {
Pitch * ptr = (Pitch *)Instance;
free(ptr->ringbuffer);
free(Instance);
}
LADSPA_Descriptor * mono_descriptor = NULL;
/* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
loaded. */
void
__attribute__((constructor)) tap_init() {
int i;
char ** port_names;
LADSPA_PortDescriptor * port_descriptors;
LADSPA_PortRangeHint * port_range_hints;
if ((mono_descriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
exit(1);
for (i = 0; i < COS_TABLE_SIZE; i++)
cos_table[i] = cosf(i * 2.0f * M_PI / COS_TABLE_SIZE);
mono_descriptor->UniqueID = ID_MONO;
mono_descriptor->Label = strdup("tap_pitch");
mono_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
mono_descriptor->Name = strdup("TAP Pitch Shifter");
mono_descriptor->Maker = strdup("Tom Szilagyi");
mono_descriptor->Copyright = strdup("GPL");
mono_descriptor->PortCount = PORTCOUNT_MONO;
if ((port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
exit(1);
mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
port_descriptors[RATE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[SEMITONE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[DRYLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[WETLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[LATENCY] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
port_descriptors[INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
if ((port_names =
(char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
exit(1);
mono_descriptor->PortNames = (const char **)port_names;
port_names[SEMITONE] = strdup("Semitone Shift");
port_names[RATE] = strdup("Rate Shift [%]");
port_names[DRYLEVEL] = strdup("Dry Level [dB]");
port_names[WETLEVEL] = strdup("Wet Level [dB]");
port_names[LATENCY] = strdup("latency");
port_names[INPUT] = strdup("Input");
port_names[OUTPUT] = strdup("Output");
if ((port_range_hints =
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
exit(1);
mono_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
port_range_hints[RATE].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[SEMITONE].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[DRYLEVEL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MINIMUM);
port_range_hints[WETLEVEL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[LATENCY].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MAXIMUM);
port_range_hints[RATE].LowerBound = -50.0f;
port_range_hints[RATE].UpperBound = 100.0f;
port_range_hints[SEMITONE].LowerBound = -12.0f;
port_range_hints[SEMITONE].UpperBound = 12.0f;
port_range_hints[DRYLEVEL].LowerBound = -90.0f;
port_range_hints[DRYLEVEL].UpperBound = 20.0f;
port_range_hints[WETLEVEL].LowerBound = -90.0f;
port_range_hints[WETLEVEL].UpperBound = 20.0f;
port_range_hints[LATENCY].LowerBound = 0;
port_range_hints[LATENCY].UpperBound = PM_BUFLEN;
port_range_hints[INPUT].HintDescriptor = 0;
port_range_hints[OUTPUT].HintDescriptor = 0;
mono_descriptor->instantiate = instantiate_Pitch;
mono_descriptor->connect_port = connect_port_Pitch;
mono_descriptor->activate = activate_Pitch;
mono_descriptor->run = run_Pitch;
mono_descriptor->run_adding = run_adding_Pitch;
mono_descriptor->set_run_adding_gain = set_run_adding_gain_Pitch;
mono_descriptor->deactivate = NULL;
mono_descriptor->cleanup = cleanup_Pitch;
}
void
delete_descriptor(LADSPA_Descriptor * descriptor) {
unsigned long index;
if (descriptor) {
free((char *)descriptor->Label);
free((char *)descriptor->Name);
free((char *)descriptor->Maker);
free((char *)descriptor->Copyright);
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
for (index = 0; index < descriptor->PortCount; index++)
free((char *)(descriptor->PortNames[index]));
free((char **)descriptor->PortNames);
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
free(descriptor);
}
}
/* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
void
__attribute__((destructor)) tap_fini() {
delete_descriptor(mono_descriptor);
}
/* Return a descriptor of the requested plugin type. */
const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index) {
switch (Index) {
case 0:
return mono_descriptor;
default:
return NULL;
}
}

View File

@@ -1,500 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_reflector.c,v 1.1 2004/06/18 20:12:41 tszilagyi Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ladspa.h>
#include "tap_utils.h"
/* The Unique ID of the plugin: */
#define ID_MONO 2154
/* The port numbers for the plugin: */
#define FRAGMENT 0
#define DRYLEVEL 1
#define WETLEVEL 2
#define INPUT 3
#define OUTPUT 4
/* Total number of ports */
#define PORTCOUNT_MONO 5
/* minimum & maximum fragment length [ms] */
#define MIN_FRAGMENT_LEN 20
#define MAX_FRAGMENT_LEN 1600
/* in kHz */
#define MAX_SAMPLE_RATE 192
#define COS_TABLE_SIZE 1024
LADSPA_Data cos_table[COS_TABLE_SIZE];
/* The structure used to hold port connection information and state */
typedef struct {
LADSPA_Data * fragment;
LADSPA_Data * drylevel;
LADSPA_Data * wetlevel;
LADSPA_Data * input;
LADSPA_Data * output;
LADSPA_Data * ring0;
unsigned long buflen0;
unsigned long pos0;
LADSPA_Data * ring1;
unsigned long buflen1;
unsigned long pos1;
LADSPA_Data * delay1;
unsigned long delay_buflen1;
unsigned long delay_pos1;
LADSPA_Data * ring2;
unsigned long buflen2;
unsigned long pos2;
LADSPA_Data * delay2;
unsigned long delay_buflen2;
unsigned long delay_pos2;
unsigned long fragment_pos;
unsigned long sample_rate;
LADSPA_Data run_adding_gain;
} Reflector;
/* Construct a new plugin instance. */
LADSPA_Handle
instantiate_Reflector(const LADSPA_Descriptor * Descriptor,
unsigned long sample_rate) {
LADSPA_Handle * ptr;
if ((ptr = malloc(sizeof(Reflector))) != NULL) {
((Reflector *)ptr)->sample_rate = sample_rate;
((Reflector *)ptr)->run_adding_gain = 1.0f;
if ((((Reflector *)ptr)->ring0 =
calloc(2 * MAX_FRAGMENT_LEN * MAX_SAMPLE_RATE, sizeof(LADSPA_Data))) == NULL)
return NULL;
((Reflector *)ptr)->buflen0 = 2 * MAX_FRAGMENT_LEN * sample_rate / 1000;
((Reflector *)ptr)->pos0 = 0;
if ((((Reflector *)ptr)->ring1 =
calloc(2 * MAX_FRAGMENT_LEN * MAX_SAMPLE_RATE, sizeof(LADSPA_Data))) == NULL)
return NULL;
((Reflector *)ptr)->buflen1 = 2 * MAX_FRAGMENT_LEN * sample_rate / 1000;
((Reflector *)ptr)->pos1 = 0;
if ((((Reflector *)ptr)->delay1 =
calloc(2 * MAX_FRAGMENT_LEN * MAX_SAMPLE_RATE, sizeof(LADSPA_Data))) == NULL)
return NULL;
((Reflector *)ptr)->delay_buflen1 = 2 * MAX_FRAGMENT_LEN * sample_rate / 3000;
((Reflector *)ptr)->pos1 = 0;
if ((((Reflector *)ptr)->ring2 =
calloc(2 * MAX_FRAGMENT_LEN * MAX_SAMPLE_RATE, sizeof(LADSPA_Data))) == NULL)
return NULL;
((Reflector *)ptr)->buflen2 = 2 * MAX_FRAGMENT_LEN * sample_rate / 1000;
((Reflector *)ptr)->pos2 = 0;
if ((((Reflector *)ptr)->delay2 =
calloc(2 * MAX_FRAGMENT_LEN * MAX_SAMPLE_RATE, sizeof(LADSPA_Data))) == NULL)
return NULL;
((Reflector *)ptr)->delay_buflen2 = 4 * MAX_FRAGMENT_LEN * sample_rate / 3000;
((Reflector *)ptr)->pos2 = 0;
return ptr;
}
return NULL;
}
void
activate_Reflector(LADSPA_Handle Instance) {
Reflector * ptr = (Reflector *)Instance;
unsigned long i;
for (i = 0; i < ptr->buflen0; i++)
ptr->ring0[i] = 0.0f;
ptr->pos0 = 0;
for (i = 0; i < ptr->buflen1; i++)
ptr->ring1[i] = 0.0f;
ptr->pos1 = 0;
for (i = 0; i < ptr->buflen2; i++)
ptr->ring2[i] = 0.0f;
ptr->pos2 = 0;
for (i = 0; i < ptr->delay_buflen1; i++)
ptr->delay1[i] = 0.0f;
ptr->delay_pos1 = 0;
for (i = 0; i < ptr->delay_buflen2; i++)
ptr->delay2[i] = 0.0f;
ptr->delay_pos2 = 0;
ptr->fragment_pos = 0;
}
/* Connect a port to a data location. */
void
connect_port_Reflector(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * DataLocation) {
Reflector * ptr = (Reflector *)Instance;
switch (Port) {
case FRAGMENT:
ptr->fragment = DataLocation;
break;
case DRYLEVEL:
ptr->drylevel = DataLocation;
break;
case WETLEVEL:
ptr->wetlevel = DataLocation;
break;
case INPUT:
ptr->input = DataLocation;
break;
case OUTPUT:
ptr->output = DataLocation;
break;
}
}
void
run_Reflector(LADSPA_Handle Instance,
unsigned long SampleCount) {
Reflector * ptr = (Reflector *)Instance;
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
LADSPA_Data wetlevel = 0.333333f * db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
LADSPA_Data fragment = LIMIT(*(ptr->fragment),(float)MIN_FRAGMENT_LEN,(float)MAX_FRAGMENT_LEN);
unsigned long sample_index;
unsigned long sample_count = SampleCount;
LADSPA_Data in = 0.0f;
LADSPA_Data in1 = 0.0f;
LADSPA_Data in2 = 0.0f;
LADSPA_Data out_0 = 0.0f;
LADSPA_Data out_1 = 0.0f;
LADSPA_Data out_2 = 0.0f;
unsigned long fragment_pos1 = 0;
unsigned long fragment_pos2 = 0;
unsigned long arg_0 = 0;
LADSPA_Data am_0 = 0.0f;
unsigned long arg_1 = 0;
LADSPA_Data am_1 = 0.0f;
unsigned long arg_2 = 0;
LADSPA_Data am_2 = 0.0f;
ptr->buflen0 = 2 * fragment * ptr->sample_rate / 1000.0f;
ptr->buflen1 = ptr->buflen0;
ptr->buflen2 = ptr->buflen0;
ptr->delay_buflen1 = ptr->buflen0 / 3;
ptr->delay_buflen2 = 2 * ptr->buflen0 / 3;
for (sample_index = 0; sample_index < sample_count; sample_index++) {
in = *(input++);
in1 = push_buffer(in, ptr->delay1, ptr->delay_buflen1, &(ptr->delay_pos1));
in2 = push_buffer(in, ptr->delay2, ptr->delay_buflen2, &(ptr->delay_pos2));
push_buffer(in2, ptr->ring0, ptr->buflen0, &(ptr->pos0));
push_buffer(in1, ptr->ring1, ptr->buflen1, &(ptr->pos1));
push_buffer(in, ptr->ring2, ptr->buflen2, &(ptr->pos2));
fragment_pos1 = (ptr->fragment_pos + ptr->buflen0 / 3) % ptr->buflen0;
fragment_pos2 = (ptr->fragment_pos + 2 * ptr->buflen1 / 3) % ptr->buflen1;
out_0 = read_buffer(ptr->ring0, ptr->buflen0, ptr->pos0,
ptr->buflen0 - ptr->fragment_pos - 1);
out_1 = read_buffer(ptr->ring1, ptr->buflen1, ptr->pos1,
ptr->buflen1 - fragment_pos1 - 1);
out_2 = read_buffer(ptr->ring2, ptr->buflen2, ptr->pos2,
ptr->buflen2 - fragment_pos2 - 1);
ptr->fragment_pos += 2;
if (ptr->fragment_pos >= ptr->buflen0)
ptr->fragment_pos = 0;
arg_0 = (float)ptr->fragment_pos / (float)ptr->buflen0 * COS_TABLE_SIZE;
am_0 = 1.0f - cos_table[arg_0];
arg_1 = (float)fragment_pos1 / (float)ptr->buflen1 * COS_TABLE_SIZE;
am_1 = 1.0f - cos_table[arg_1];
arg_2 = (float)fragment_pos2 / (float)ptr->buflen2 * COS_TABLE_SIZE;
am_2 = 1.0f - cos_table[arg_2];
*(output++) = drylevel * in + wetlevel *
(am_0 * out_0 + am_1 * out_1 + am_2 * out_2);
}
}
void
set_run_adding_gain_Reflector(LADSPA_Handle Instance, LADSPA_Data gain) {
Reflector * ptr = (Reflector *)Instance;
ptr->run_adding_gain = gain;
}
void
run_adding_Reflector(LADSPA_Handle Instance,
unsigned long SampleCount) {
Reflector * ptr = (Reflector *)Instance;
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
LADSPA_Data wetlevel = 0.333333f * db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
LADSPA_Data fragment = LIMIT(*(ptr->fragment),(float)MIN_FRAGMENT_LEN,(float)MAX_FRAGMENT_LEN);
unsigned long sample_index;
unsigned long sample_count = SampleCount;
LADSPA_Data in = 0.0f;
LADSPA_Data in1 = 0.0f;
LADSPA_Data in2 = 0.0f;
LADSPA_Data out_0 = 0.0f;
LADSPA_Data out_1 = 0.0f;
LADSPA_Data out_2 = 0.0f;
unsigned long fragment_pos1 = 0;
unsigned long fragment_pos2 = 0;
unsigned long arg_0 = 0;
LADSPA_Data am_0 = 0.0f;
unsigned long arg_1 = 0;
LADSPA_Data am_1 = 0.0f;
unsigned long arg_2 = 0;
LADSPA_Data am_2 = 0.0f;
ptr->buflen0 = 2 * fragment * ptr->sample_rate / 1000.0f;
ptr->buflen1 = ptr->buflen0;
ptr->buflen2 = ptr->buflen0;
ptr->delay_buflen1 = ptr->buflen0 / 3;
ptr->delay_buflen2 = 2 * ptr->buflen0 / 3;
for (sample_index = 0; sample_index < sample_count; sample_index++) {
in = *(input++);
in1 = push_buffer(in, ptr->delay1, ptr->delay_buflen1, &(ptr->delay_pos1));
in2 = push_buffer(in, ptr->delay2, ptr->delay_buflen2, &(ptr->delay_pos2));
push_buffer(in2, ptr->ring0, ptr->buflen0, &(ptr->pos0));
push_buffer(in1, ptr->ring1, ptr->buflen1, &(ptr->pos1));
push_buffer(in, ptr->ring2, ptr->buflen2, &(ptr->pos2));
fragment_pos1 = (ptr->fragment_pos + ptr->buflen0 / 3) % ptr->buflen0;
fragment_pos2 = (ptr->fragment_pos + 2 * ptr->buflen1 / 3) % ptr->buflen1;
out_0 = read_buffer(ptr->ring0, ptr->buflen0, ptr->pos0,
ptr->buflen0 - ptr->fragment_pos - 1);
out_1 = read_buffer(ptr->ring1, ptr->buflen1, ptr->pos1,
ptr->buflen1 - fragment_pos1 - 1);
out_2 = read_buffer(ptr->ring2, ptr->buflen2, ptr->pos2,
ptr->buflen2 - fragment_pos2 - 1);
ptr->fragment_pos += 2;
if (ptr->fragment_pos >= ptr->buflen0)
ptr->fragment_pos = 0;
arg_0 = (float)ptr->fragment_pos / (float)ptr->buflen0 * COS_TABLE_SIZE;
am_0 = 1.0f - cos_table[arg_0];
arg_1 = (float)fragment_pos1 / (float)ptr->buflen1 * COS_TABLE_SIZE;
am_1 = 1.0f - cos_table[arg_1];
arg_2 = (float)fragment_pos2 / (float)ptr->buflen2 * COS_TABLE_SIZE;
am_2 = 1.0f - cos_table[arg_2];
*(output++) += ptr->run_adding_gain *
(drylevel * in + wetlevel * (am_0 * out_0 + am_1 * out_1 + am_2 * out_2));
}
}
/* Throw away a Reflector effect instance. */
void
cleanup_Reflector(LADSPA_Handle Instance) {
Reflector * ptr = (Reflector *)Instance;
free(ptr->ring0);
free(ptr->ring1);
free(ptr->ring2);
free(ptr->delay1);
free(ptr->delay2);
free(Instance);
}
LADSPA_Descriptor * mono_descriptor = NULL;
/* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
loaded. */
void
__attribute__((constructor)) tap_init() {
int i;
char ** port_names;
LADSPA_PortDescriptor * port_descriptors;
LADSPA_PortRangeHint * port_range_hints;
if ((mono_descriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
exit(1);
for (i = 0; i < COS_TABLE_SIZE; i++)
cos_table[i] = cosf(i * 2.0f * M_PI / COS_TABLE_SIZE);
mono_descriptor->UniqueID = ID_MONO;
mono_descriptor->Label = strdup("tap_reflector");
mono_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
mono_descriptor->Name = strdup("TAP Reflector");
mono_descriptor->Maker = strdup("Tom Szilagyi");
mono_descriptor->Copyright = strdup("GPL");
mono_descriptor->PortCount = PORTCOUNT_MONO;
if ((port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
exit(1);
mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
port_descriptors[FRAGMENT] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[DRYLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[WETLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
if ((port_names =
(char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
exit(1);
mono_descriptor->PortNames = (const char **)port_names;
port_names[FRAGMENT] = strdup("Fragment Length [ms]");
port_names[DRYLEVEL] = strdup("Dry Level [dB]");
port_names[WETLEVEL] = strdup("Wet Level [dB]");
port_names[INPUT] = strdup("Input");
port_names[OUTPUT] = strdup("Output");
if ((port_range_hints =
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
exit(1);
mono_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
port_range_hints[FRAGMENT].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_LOW);
port_range_hints[DRYLEVEL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MINIMUM);
port_range_hints[WETLEVEL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[FRAGMENT].LowerBound = (float)MIN_FRAGMENT_LEN;
port_range_hints[FRAGMENT].UpperBound = (float)MAX_FRAGMENT_LEN;
port_range_hints[DRYLEVEL].LowerBound = -90.0f;
port_range_hints[DRYLEVEL].UpperBound = 20.0f;
port_range_hints[WETLEVEL].LowerBound = -90.0f;
port_range_hints[WETLEVEL].UpperBound = 20.0f;
port_range_hints[INPUT].HintDescriptor = 0;
port_range_hints[OUTPUT].HintDescriptor = 0;
mono_descriptor->instantiate = instantiate_Reflector;
mono_descriptor->connect_port = connect_port_Reflector;
mono_descriptor->activate = activate_Reflector;
mono_descriptor->run = run_Reflector;
mono_descriptor->run_adding = run_adding_Reflector;
mono_descriptor->set_run_adding_gain = set_run_adding_gain_Reflector;
mono_descriptor->deactivate = NULL;
mono_descriptor->cleanup = cleanup_Reflector;
}
void
delete_descriptor(LADSPA_Descriptor * descriptor) {
unsigned long index;
if (descriptor) {
free((char *)descriptor->Label);
free((char *)descriptor->Name);
free((char *)descriptor->Maker);
free((char *)descriptor->Copyright);
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
for (index = 0; index < descriptor->PortCount; index++)
free((char *)(descriptor->PortNames[index]));
free((char **)descriptor->PortNames);
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
free(descriptor);
}
}
/* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
void
__attribute__((destructor)) tap_fini() {
delete_descriptor(mono_descriptor);
}
/* Return a descriptor of the requested plugin type. */
const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index) {
switch (Index) {
case 0:
return mono_descriptor;
default:
return NULL;
}
}

View File

@@ -1,835 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_reverb.c,v 1.13 2004/06/15 14:50:55 tszilagyi Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ladspa.h>
/* ***** VERY IMPORTANT! *****
*
* If you enable this, the plugin will use float arithmetics in DSP
* calculations. This usually yields lower average CPU usage, but
* occasionaly may result in high CPU peaks which cause trouble to you
* and your JACK server. The default is to use fixpoint arithmetics
* (with the following #define commented out). But (depending on the
* processor on which you run the code) you may find floating point
* mode usable.
*/
/* #define REVERB_CALC_FLOAT */
#ifndef REVERB_CALC_FLOAT
typedef signed int sample;
#endif
#ifndef REVERB_CALC_FLOAT
typedef sample rev_t;
#else
typedef LADSPA_Data rev_t;
#endif
#include "tap_reverb_presets.h"
#ifdef REVERB_CALC_FLOAT
#define DENORM(x) (((unsigned char)(((*(unsigned int*)&(x))&0x7f800000)>>23))<103)?0.0f:(x)
#else
/* coefficient for float to sample (signed int) conversion */
/* this allows for about 60 dB headroom above 0dB, if 0 dB is equivalent to 1.0f */
/* As 2^31 equals more than 180 dB, about 120 dB dynamics remains below 0 dB */
#define F2S 2147483
#endif
/* load plugin data from reverb_data[] into an instance */
void
load_plugin_data(LADSPA_Handle Instance) {
Reverb * ptr = (Reverb *)Instance;
unsigned long m;
unsigned int i;
m = LIMIT(*(ptr->mode),0,NUM_MODES-1);
/* load combs data */
ptr->num_combs = 2 * reverb_data[m].num_combs;
for (i = 0; i < reverb_data[m].num_combs; i++) {
((COMB_FILTER *)(ptr->combs + 2*i))->buflen =
reverb_data[m].combs[i].delay * ptr->sample_rate;
((COMB_FILTER *)(ptr->combs + 2*i))->feedback =
reverb_data[m].combs[i].feedback;
((COMB_FILTER *)(ptr->combs + 2*i))->freq_resp =
LIMIT(reverb_data[m].combs[i].freq_resp
* powf(ptr->sample_rate / 44100.0f, 0.8f),
0.0f, 1.0f);
((COMB_FILTER *)(ptr->combs + 2*i+1))->buflen =
((COMB_FILTER *)(ptr->combs + 2*i))->buflen;
((COMB_FILTER *)(ptr->combs + 2*i+1))->feedback =
((COMB_FILTER *)(ptr->combs + 2*i))->feedback;
((COMB_FILTER *)(ptr->combs + 2*i+1))->feedback =
((COMB_FILTER *)(ptr->combs + 2*i))->freq_resp;
/* set initial values: */
*(((COMB_FILTER *)(ptr->combs + 2*i))->buffer_pos) = 0;
*(((COMB_FILTER *)(ptr->combs + 2*i+1))->buffer_pos) = 0;
((COMB_FILTER *)(ptr->combs + 2*i))->last_out = 0;
((COMB_FILTER *)(ptr->combs + 2*i+1))->last_out = 0;
lp_set_params(((COMB_FILTER *)(ptr->combs + 2*i))->filter,
2000.0f + 13000.0f * (1 - reverb_data[m].combs[i].freq_resp)
* ptr->sample_rate / 44100.0f,
BANDPASS_BWIDTH, ptr->sample_rate);
lp_set_params(((COMB_FILTER *)(ptr->combs + 2*i+1))->filter,
2000.0f + 13000.0f * (1 - reverb_data[m].combs[i].freq_resp)
* ptr->sample_rate / 44100.0f,
BANDPASS_BWIDTH, ptr->sample_rate);
}
/* load allps data */
ptr->num_allps = 2 * reverb_data[m].num_allps;
for (i = 0; i < reverb_data[m].num_allps; i++) {
((ALLP_FILTER *)(ptr->allps + 2*i))->buflen =
reverb_data[m].allps[i].delay * ptr->sample_rate;
((ALLP_FILTER *)(ptr->allps + 2*i))->feedback =
reverb_data[m].allps[i].feedback;
((ALLP_FILTER *)(ptr->allps + 2*i+1))->buflen =
((ALLP_FILTER *)(ptr->allps + 2*i))->buflen;
((ALLP_FILTER *)(ptr->allps + 2*i+1))->feedback =
((ALLP_FILTER *)(ptr->allps + 2*i))->feedback;
/* set initial values: */
*(((ALLP_FILTER *)(ptr->allps + 2*i))->buffer_pos) = 0;
*(((ALLP_FILTER *)(ptr->allps + 2*i+1))->buffer_pos) = 0;
((ALLP_FILTER *)(ptr->allps + 2*i))->last_out = 0;
((ALLP_FILTER *)(ptr->allps + 2*i+1))->last_out = 0;
}
/* init bandpass filters */
lp_set_params((biquad *)(ptr->low_pass), reverb_data[m].bandpass_high,
BANDPASS_BWIDTH, ptr->sample_rate);
hp_set_params((biquad *)(ptr->high_pass), reverb_data[m].bandpass_low,
BANDPASS_BWIDTH, ptr->sample_rate);
lp_set_params((biquad *)(ptr->low_pass + 1), reverb_data[m].bandpass_high,
BANDPASS_BWIDTH, ptr->sample_rate);
hp_set_params((biquad *)(ptr->high_pass + 1), reverb_data[m].bandpass_low,
BANDPASS_BWIDTH, ptr->sample_rate);
}
/* push a sample into a comb filter and return the sample falling out */
rev_t
comb_run(rev_t insample, COMB_FILTER * comb) {
rev_t outsample;
rev_t pushin;
pushin = comb->fb_gain * insample + biquad_run(comb->filter, comb->fb_gain * comb->last_out);
#ifdef REVERB_CALC_FLOAT
pushin = DENORM(pushin);
#endif
outsample = push_buffer(pushin,
comb->ringbuffer, comb->buflen, comb->buffer_pos);
#ifdef REVERB_CALC_FLOAT
outsample = DENORM(outsample);
#endif
comb->last_out = outsample;
return outsample;
}
/* push a sample into an allpass filter and return the sample falling out */
rev_t
allp_run(rev_t insample, ALLP_FILTER * allp) {
rev_t outsample;
rev_t pushin;
pushin = allp->in_gain * allp->fb_gain * insample + allp->fb_gain * allp->last_out;
#ifdef REVERB_CALC_FLOAT
pushin = DENORM(pushin);
#endif
outsample = push_buffer(pushin,
allp->ringbuffer, allp->buflen, allp->buffer_pos);
#ifdef REVERB_CALC_FLOAT
outsample = DENORM(outsample);
#endif
allp->last_out = outsample;
return outsample;
}
/* compute user-input-dependent reverberator coefficients */
void
comp_coeffs(LADSPA_Handle Instance) {
Reverb * ptr = (Reverb *)Instance;
unsigned int i;
if (*(ptr->mode) != ptr->old_mode)
load_plugin_data(Instance);
for (i = 0; i < ptr->num_combs / 2; i++) {
((COMB_FILTER *)(ptr->combs + 2*i))->fb_gain =
powf(0.001f,
1000.0f * ((COMB_FILTER *)(ptr->combs + 2*i))->buflen
* (1 + FR_R_COMP * ((COMB_FILTER *)(ptr->combs + 2*i))->freq_resp)
/ powf(((COMB_FILTER *)(ptr->combs + 2*i))->feedback/100.0f, 0.89f)
/ *(ptr->decay)
/ ptr->sample_rate);
((COMB_FILTER *)(ptr->combs + 2*i+1))->fb_gain =
((COMB_FILTER *)(ptr->combs + 2*i))->fb_gain;
if (*(ptr->stereo_enh) > 0.0f) {
if (i % 2 == 0)
((COMB_FILTER *)(ptr->combs + 2*i+1))->buflen =
ENH_STEREO_RATIO * ((COMB_FILTER *)(ptr->combs + 2*i))->buflen;
else
((COMB_FILTER *)(ptr->combs + 2*i))->buflen =
ENH_STEREO_RATIO * ((COMB_FILTER *)(ptr->combs + 2*i+1))->buflen;
} else {
if (i % 2 == 0)
((COMB_FILTER *)(ptr->combs + 2*i+1))->buflen =
((COMB_FILTER *)(ptr->combs + 2*i))->buflen;
else
((COMB_FILTER *)(ptr->combs + 2*i))->buflen =
((COMB_FILTER *)(ptr->combs + 2*i+1))->buflen;
}
}
for (i = 0; i < ptr->num_allps / 2; i++) {
((ALLP_FILTER *)(ptr->allps + 2*i))->fb_gain =
powf(0.001f, 11000.0f * ((ALLP_FILTER *)(ptr->allps + 2*i))->buflen
/ powf(((ALLP_FILTER *)(ptr->allps + 2*i))->feedback/100.0f, 0.88f)
/ *(ptr->decay)
/ ptr->sample_rate);
((ALLP_FILTER *)(ptr->allps + 2*i+1))->fb_gain =
((ALLP_FILTER *)(ptr->allps + 2*i))->fb_gain;
((ALLP_FILTER *)(ptr->allps + 2*i))->in_gain = -0.06f
/ (((ALLP_FILTER *)(ptr->allps + 2 * i))->feedback/100.0f)
/ powf((*(ptr->decay) + 3500.0f) / 10000.0f, 1.5f);
((ALLP_FILTER *)(ptr->allps + 2*i+1))->in_gain =
((ALLP_FILTER *)(ptr->allps + 2*i))->in_gain;
if (*(ptr->stereo_enh) > 0.0f) {
if (i % 2 == 0)
((ALLP_FILTER *)(ptr->allps + 2*i+1))->buflen =
ENH_STEREO_RATIO * ((ALLP_FILTER *)(ptr->allps + 2*i))->buflen;
else
((ALLP_FILTER *)(ptr->allps + 2*i))->buflen =
ENH_STEREO_RATIO * ((ALLP_FILTER *)(ptr->allps + 2*i+1))->buflen;
} else {
if (i % 2 == 0)
((ALLP_FILTER *)(ptr->allps + 2*i+1))->buflen =
((ALLP_FILTER *)(ptr->allps + 2*i))->buflen;
else
((ALLP_FILTER *)(ptr->allps + 2*i))->buflen =
((ALLP_FILTER *)(ptr->allps + 2*i+1))->buflen;
}
}
}
/* Construct a new plugin instance. */
LADSPA_Handle
instantiate_Reverb(const LADSPA_Descriptor * Descriptor,
unsigned long SampleRate) {
unsigned long i;
LADSPA_Handle * p;
Reverb * ptr = NULL;
if ((p = malloc(sizeof(Reverb))) != NULL) {
((Reverb *)p)->sample_rate = SampleRate;
((Reverb *)p)->run_adding_gain = 1.0f;
ptr = (Reverb *)p;
/* allocate memory for comb/allpass filters and other dynamic vars */
if ((ptr->combs =
calloc(2 * MAX_COMBS, sizeof(COMB_FILTER))) == NULL)
return NULL;
for (i = 0; i < 2 * MAX_COMBS; i++) {
if ((((COMB_FILTER *)(ptr->combs + i))->ringbuffer =
calloc((unsigned long)MAX_COMB_DELAY * ptr->sample_rate / 1000,
sizeof(LADSPA_Data))) == NULL)
return NULL;
if ((((COMB_FILTER *)(ptr->combs + i))->buffer_pos =
calloc(1, sizeof(unsigned long))) == NULL)
return NULL;
if ((((COMB_FILTER *)(ptr->combs + i))->filter =
calloc(1, sizeof(biquad))) == NULL)
return NULL;
}
if ((ptr->allps =
calloc(2 * MAX_ALLPS, sizeof(ALLP_FILTER))) == NULL)
return NULL;
for (i = 0; i < 2 * MAX_ALLPS; i++) {
if ((((ALLP_FILTER *)(ptr->allps + i))->ringbuffer =
calloc((unsigned long)MAX_ALLP_DELAY * ptr->sample_rate / 1000,
sizeof(LADSPA_Data))) == NULL)
return NULL;
if ((((ALLP_FILTER *)(ptr->allps + i))->buffer_pos =
calloc(1, sizeof(unsigned long))) == NULL)
return NULL;
}
if ((ptr->low_pass =
calloc(2, sizeof(biquad))) == NULL)
return NULL;
if ((ptr->high_pass =
calloc(2, sizeof(biquad))) == NULL)
return NULL;
return p;
}
return NULL;
}
/* activate a plugin instance */
void
activate_Reverb(LADSPA_Handle Instance) {
Reverb * ptr = (Reverb *)Instance;
unsigned long i,j;
for (i = 0; i < 2 * MAX_COMBS; i++) {
for (j = 0; j < (unsigned long)MAX_COMB_DELAY * ptr->sample_rate / 1000; j++)
((COMB_FILTER *)(ptr->combs + i))->ringbuffer[j] = 0.0f;
*(((COMB_FILTER *)(ptr->combs + i))->buffer_pos) = 0;
((COMB_FILTER *)(ptr->combs + i))->last_out = 0;
biquad_init(((COMB_FILTER *)(ptr->combs + i))->filter);
}
for (i = 0; i < 2 * MAX_ALLPS; i++) {
for (j = 0; j < (unsigned long)MAX_ALLP_DELAY * ptr->sample_rate / 1000; j++)
((ALLP_FILTER *)(ptr->allps + i))->ringbuffer[j] = 0.0f;
*(((ALLP_FILTER *)(ptr->allps + i))->buffer_pos) = 0;
((ALLP_FILTER *)(ptr->allps + i))->last_out = 0;
}
biquad_init(ptr->low_pass);
biquad_init((biquad *)(ptr->low_pass + 1));
biquad_init(ptr->high_pass);
biquad_init((biquad *)(ptr->high_pass + 1));
ptr->old_decay = -10.0f;
ptr->old_stereo_enh = -10.0f;
ptr->old_mode = -10.0f;
}
/* Connect a port to a data location. */
void
connect_port_Reverb(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * DataLocation) {
Reverb * ptr = (Reverb *)Instance;
switch (Port) {
case DECAY:
ptr->decay = DataLocation;
break;
case DRYLEVEL:
ptr->drylevel = DataLocation;
break;
case WETLEVEL:
ptr->wetlevel = DataLocation;
break;
case COMBS_EN:
ptr->combs_en = DataLocation;
break;
case ALLPS_EN:
ptr->allps_en = DataLocation;
break;
case BANDPASS_EN:
ptr->bandpass_en = DataLocation;
break;
case STEREO_ENH:
ptr->stereo_enh = DataLocation;
break;
case MODE:
ptr->mode = DataLocation;
break;
case INPUT_L:
ptr->input_L = DataLocation;
break;
case OUTPUT_L:
ptr->output_L = DataLocation;
break;
case INPUT_R:
ptr->input_R = DataLocation;
break;
case OUTPUT_R:
ptr->output_R = DataLocation;
break;
}
}
void
run_Reverb(LADSPA_Handle Instance,
unsigned long SampleCount) {
Reverb * ptr = (Reverb *)Instance;
unsigned long sample_index;
unsigned int i;
LADSPA_Data decay = LIMIT(*(ptr->decay),0.0f,10000.0f);
LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-70.0f,10.0f));
LADSPA_Data wetlevel = db2lin(LIMIT(*(ptr->wetlevel),-70.0f,10.0f));
LADSPA_Data combs_en = LIMIT(*(ptr->combs_en),-2.0f,2.0f);
LADSPA_Data allps_en = LIMIT(*(ptr->allps_en),-2.0f,2.0f);
LADSPA_Data bandpass_en = LIMIT(*(ptr->bandpass_en),-2.0f,2.0f);
LADSPA_Data stereo_enh = LIMIT(*(ptr->stereo_enh),-2.0f,2.0f);
LADSPA_Data mode = LIMIT(*(ptr->mode),0,NUM_MODES-1);
LADSPA_Data * input_L = ptr->input_L;
LADSPA_Data * output_L = ptr->output_L;
LADSPA_Data * input_R = ptr->input_R;
LADSPA_Data * output_R = ptr->output_R;
rev_t out_L = 0;
rev_t out_R = 0;
rev_t in_L = 0;
rev_t in_R = 0;
rev_t combs_out_L = 0;
rev_t combs_out_R = 0;
/* see if the user changed any control since last run */
if ((ptr->old_decay != decay) ||
(ptr->old_stereo_enh != stereo_enh) ||
(ptr->old_mode != mode)) {
/* re-compute reverberator coefficients */
comp_coeffs(Instance);
/* save new values */
ptr->old_decay = decay;
ptr->old_stereo_enh = stereo_enh;
ptr->old_mode = mode;
}
for (sample_index = 0; sample_index < SampleCount; sample_index++) {
#ifdef REVERB_CALC_FLOAT
in_L = *(input_L++);
in_R = *(input_R++);
#else
in_L = (sample)((float)F2S * *(input_L++));
in_R = (sample)((float)F2S * *(input_R++));
#endif
combs_out_L = in_L;
combs_out_R = in_R;
/* process comb filters */
if (combs_en > 0.0f) {
for (i = 0; i < ptr->num_combs / 2; i++) {
combs_out_L +=
comb_run(in_L, ((COMB_FILTER *)(ptr->combs + 2*i)));
combs_out_R +=
comb_run(in_R, ((COMB_FILTER *)(ptr->combs + 2*i+1)));
}
}
/* process allpass filters */
if (allps_en > 0.0f) {
for (i = 0; i < ptr->num_allps / 2; i++) {
combs_out_L += allp_run(combs_out_L,
((ALLP_FILTER *)(ptr->allps + 2*i)));
combs_out_R += allp_run(combs_out_R,
((ALLP_FILTER *)(ptr->allps + 2*i+1)));
}
}
/* process bandpass filters */
if (bandpass_en > 0.0f) {
combs_out_L =
biquad_run(((biquad *)(ptr->low_pass)), combs_out_L);
combs_out_L =
biquad_run(((biquad *)(ptr->high_pass)), combs_out_L);
combs_out_R =
biquad_run(((biquad *)(ptr->low_pass + 1)), combs_out_R);
combs_out_R =
biquad_run(((biquad *)(ptr->high_pass + 1)), combs_out_R);
}
#ifdef REVERB_CALC_FLOAT
out_L = in_L * drylevel + combs_out_L * wetlevel;
out_R = in_R * drylevel + combs_out_R * wetlevel;
*(output_L++) = out_L;
*(output_R++) = out_R;
#else
out_L = (sample)((float)in_L * drylevel + (float)combs_out_L * wetlevel);
out_R = (sample)((float)in_R * drylevel + (float)combs_out_R * wetlevel);
*(output_L++) = (float)out_L / (float)F2S;
*(output_R++) = (float)out_R / (float)F2S;
#endif
}
}
void
set_run_adding_gain(LADSPA_Handle Instance, LADSPA_Data gain){
Reverb * ptr;
ptr = (Reverb *)Instance;
ptr->run_adding_gain = gain;
}
void
run_adding_gain_Reverb(LADSPA_Handle Instance,
unsigned long SampleCount) {
Reverb * ptr = (Reverb *)Instance;
unsigned long sample_index;
unsigned int i;
LADSPA_Data decay = LIMIT(*(ptr->decay),0.0f,10000.0f);
LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-70.0f,10.0f));
LADSPA_Data wetlevel = db2lin(LIMIT(*(ptr->wetlevel),-70.0f,10.0f));
LADSPA_Data combs_en = LIMIT(*(ptr->combs_en),-2.0f,2.0f);
LADSPA_Data allps_en = LIMIT(*(ptr->allps_en),-2.0f,2.0f);
LADSPA_Data bandpass_en = LIMIT(*(ptr->bandpass_en),-2.0f,2.0f);
LADSPA_Data stereo_enh = LIMIT(*(ptr->stereo_enh),-2.0f,2.0f);
LADSPA_Data mode = LIMIT(*(ptr->mode),0,NUM_MODES-1);
LADSPA_Data * input_L = ptr->input_L;
LADSPA_Data * output_L = ptr->output_L;
LADSPA_Data * input_R = ptr->input_R;
LADSPA_Data * output_R = ptr->output_R;
rev_t out_L = 0;
rev_t out_R = 0;
rev_t in_L = 0;
rev_t in_R = 0;
rev_t combs_out_L = 0;
rev_t combs_out_R = 0;
/* see if the user changed any control since last run */
if ((ptr->old_decay != decay) ||
(ptr->old_stereo_enh != stereo_enh) ||
(ptr->old_mode != mode)) {
/* re-compute reverberator coefficients */
comp_coeffs(Instance);
/* save new values */
ptr->old_decay = decay;
ptr->old_stereo_enh = stereo_enh;
ptr->old_mode = mode;
}
for (sample_index = 0; sample_index < SampleCount; sample_index++) {
#ifdef REVERB_CALC_FLOAT
in_L = *(input_L++);
in_R = *(input_R++);
#else
in_L = (sample)((float)F2S * *(input_L++));
in_R = (sample)((float)F2S * *(input_R++));
#endif
combs_out_L = in_L;
combs_out_R = in_R;
/* process comb filters */
if (combs_en > 0.0f) {
for (i = 0; i < ptr->num_combs / 2; i++) {
combs_out_L +=
comb_run(in_L, ((COMB_FILTER *)(ptr->combs + 2*i)));
combs_out_R +=
comb_run(in_R, ((COMB_FILTER *)(ptr->combs + 2*i+1)));
}
}
/* process allpass filters */
if (allps_en > 0.0f) {
for (i = 0; i < ptr->num_allps / 2; i++) {
combs_out_L += allp_run(combs_out_L,
((ALLP_FILTER *)(ptr->allps + 2*i)));
combs_out_R += allp_run(combs_out_R,
((ALLP_FILTER *)(ptr->allps + 2*i+1)));
}
}
/* process bandpass filters */
if (bandpass_en > 0.0f) {
combs_out_L =
biquad_run(((biquad *)(ptr->low_pass)), combs_out_L);
combs_out_L =
biquad_run(((biquad *)(ptr->high_pass)), combs_out_L);
combs_out_R =
biquad_run(((biquad *)(ptr->low_pass + 1)), combs_out_R);
combs_out_R =
biquad_run(((biquad *)(ptr->high_pass + 1)), combs_out_R);
}
#ifdef REVERB_CALC_FLOAT
out_L = in_L * drylevel + combs_out_L * wetlevel;
out_R = in_R * drylevel + combs_out_R * wetlevel;
*(output_L++) += out_L * ptr->run_adding_gain;
*(output_R++) += out_R * ptr->run_adding_gain;
#else
out_L = (sample)((float)in_L * drylevel + (float)combs_out_L * wetlevel);
out_R = (sample)((float)in_R * drylevel + (float)combs_out_R * wetlevel);
*(output_L++) += (float)out_L * ptr->run_adding_gain / (float)F2S;
*(output_R++) += (float)out_R * ptr->run_adding_gain / (float)F2S;
#endif
}
}
/* Throw away a Reverb effect instance. */
void
cleanup_Reverb(LADSPA_Handle Instance) {
int i;
Reverb * ptr = (Reverb *)Instance;
/* free memory allocated for comb/allpass filters & co. in instantiate_Reverb() */
for (i = 0; i < 2 * MAX_COMBS; i++) {
free(((COMB_FILTER *)(ptr->combs + i))->ringbuffer);
free(((COMB_FILTER *)(ptr->combs + i))->buffer_pos);
free(((COMB_FILTER *)(ptr->combs + i))->filter);
}
for (i = 0; i < 2 * MAX_ALLPS; i++) {
free(((ALLP_FILTER *)(ptr->allps + i))->ringbuffer);
free(((ALLP_FILTER *)(ptr->allps + i))->buffer_pos);
}
free(ptr->combs);
free(ptr->allps);
free(ptr->low_pass);
free(ptr->high_pass);
free(Instance);
}
LADSPA_Descriptor * stereo_descriptor = NULL;
/* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
loaded. */
void
__attribute__((constructor)) tap_init() {
char ** port_names;
LADSPA_PortDescriptor * port_descriptors;
LADSPA_PortRangeHint * port_range_hints;
if ((stereo_descriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
exit(1);
/* init the stereo Reverb */
stereo_descriptor->UniqueID = ID_STEREO;
stereo_descriptor->Label = strdup("tap_reverb");
stereo_descriptor->Properties = 0;
stereo_descriptor->Name = strdup("TAP Reverberator");
stereo_descriptor->Maker = strdup("Tom Szilagyi");
stereo_descriptor->Copyright = strdup("GPL");
stereo_descriptor->PortCount = PORTCOUNT_STEREO;
if ((port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortDescriptor))) == NULL)
exit(1);
stereo_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
port_descriptors[DECAY] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[DRYLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[WETLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[COMBS_EN] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[ALLPS_EN] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[BANDPASS_EN] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[STEREO_ENH] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[MODE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[INPUT_L] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT_L] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
port_descriptors[INPUT_R] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT_R] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
if ((port_names =
(char **)calloc(PORTCOUNT_STEREO, sizeof(char *))) == NULL)
exit(1);
stereo_descriptor->PortNames = (const char **)port_names;
port_names[DECAY] = strdup("Decay [ms]");
port_names[DRYLEVEL] = strdup("Dry Level [dB]");
port_names[WETLEVEL] = strdup("Wet Level [dB]");
port_names[COMBS_EN] = strdup("Comb Filters");
port_names[ALLPS_EN] = strdup("Allpass Filters");
port_names[BANDPASS_EN] = strdup("Bandpass Filter");
port_names[STEREO_ENH] = strdup("Enhanced Stereo");
port_names[MODE] = strdup("Reverb Type");
port_names[INPUT_L] = strdup("Input Left");
port_names[OUTPUT_L] = strdup("Output Left");
port_names[INPUT_R] = strdup("Input Right");
port_names[OUTPUT_R] = strdup("Output Right");
if ((port_range_hints =
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortRangeHint)))) == NULL)
exit(1);
stereo_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
port_range_hints[DECAY].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_LOW);
port_range_hints[DECAY].LowerBound = 0;
port_range_hints[DECAY].UpperBound = MAX_DECAY;
port_range_hints[DRYLEVEL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[DRYLEVEL].LowerBound = -70.0f;
port_range_hints[DRYLEVEL].UpperBound = +10.0f;
port_range_hints[WETLEVEL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[WETLEVEL].LowerBound = -70.0f;
port_range_hints[WETLEVEL].UpperBound = +10.0f;
port_range_hints[COMBS_EN].HintDescriptor =
(LADSPA_HINT_TOGGLED |
LADSPA_HINT_DEFAULT_1);
port_range_hints[ALLPS_EN].HintDescriptor =
(LADSPA_HINT_TOGGLED |
LADSPA_HINT_DEFAULT_1);
port_range_hints[BANDPASS_EN].HintDescriptor =
(LADSPA_HINT_TOGGLED |
LADSPA_HINT_DEFAULT_1);
port_range_hints[STEREO_ENH].HintDescriptor =
(LADSPA_HINT_TOGGLED |
LADSPA_HINT_DEFAULT_1);
port_range_hints[MODE].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_INTEGER |
LADSPA_HINT_DEFAULT_0);
port_range_hints[MODE].LowerBound = 0;
port_range_hints[MODE].UpperBound = NUM_MODES - 0.9f;
port_range_hints[INPUT_L].HintDescriptor = 0;
port_range_hints[OUTPUT_L].HintDescriptor = 0;
port_range_hints[INPUT_R].HintDescriptor = 0;
port_range_hints[OUTPUT_R].HintDescriptor = 0;
stereo_descriptor->instantiate = instantiate_Reverb;
stereo_descriptor->connect_port = connect_port_Reverb;
stereo_descriptor->activate = activate_Reverb;
stereo_descriptor->run = run_Reverb;
stereo_descriptor->run_adding = run_adding_gain_Reverb;
stereo_descriptor->set_run_adding_gain = set_run_adding_gain;
stereo_descriptor->deactivate = NULL;
stereo_descriptor->cleanup = cleanup_Reverb;
}
void
delete_descriptor(LADSPA_Descriptor * descriptor) {
unsigned long index;
if (descriptor) {
free((char *)descriptor->Label);
free((char *)descriptor->Name);
free((char *)descriptor->Maker);
free((char *)descriptor->Copyright);
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
for (index = 0; index < descriptor->PortCount; index++)
free((char *)(descriptor->PortNames[index]));
free((char **)descriptor->PortNames);
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
free(descriptor);
}
}
/* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
void
__attribute__((destructor)) tap_fini() {
delete_descriptor(stereo_descriptor);
}
/* Return a descriptor of the requested plugin type. */
const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index) {
switch (Index) {
case 0:
return stereo_descriptor;
default:
return NULL;
}
}

View File

@@ -1,295 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_reverb.h,v 1.10 2004/06/14 16:43:55 tszilagyi Exp $
*/
#ifndef _ISOC99_SOURCE
#define _ISOC99_SOURCE
#endif
#include <stdint.h>
/* The Unique ID of the plugin: */
#define ID_STEREO 2142
/* The port numbers for the plugin: */
#define DECAY 0
#define DRYLEVEL 1
#define WETLEVEL 2
#define COMBS_EN 3 /* comb filters on/off */
#define ALLPS_EN 4 /* allpass filters on/off */
#define BANDPASS_EN 5 /* bandpass filters on/off */
#define STEREO_ENH 6 /* stereo enhanced mode on/off */
#define MODE 7
#define INPUT_L 8
#define OUTPUT_L 9
#define INPUT_R 10
#define OUTPUT_R 11
/* Total number of ports */
#define PORTCOUNT_STEREO 12
/* Global constants (times in ms, bwidth in octaves) */
#define MAX_COMBS 20
#define MAX_ALLPS 20
#define MAX_DECAY 10000.0f
#define MAX_COMB_DELAY 250.0f
#define MAX_ALLP_DELAY 20.0f
#define BANDPASS_BWIDTH 1.5f
#define FREQ_RESP_BWIDTH 3.0f
#define ENH_STEREO_RATIO 0.998f
/* compensation ratio of freq_resp in fb_gain calc */
#define FR_R_COMP 0.75f
#ifndef M_PI
#define M_PI 3.14159265358979323846264338327
#endif
/* push a sample into a ringbuffer and return the sample falling out */
static inline
rev_t
push_buffer(rev_t insample, rev_t * buffer,
unsigned long buflen, unsigned long * pos) {
rev_t outsample;
outsample = buffer[*pos];
buffer[(*pos)++] = insample;
if (*pos >= buflen)
*pos = 0;
return outsample;
}
/* read a value from a ringbuffer.
* n == 0 returns the oldest sample from the buffer.
* n == buflen-1 returns the sample written to the buffer
* at the last push_buffer call.
* n must not exceed buflen-1, or your computer will explode.
*/
static inline
rev_t
read_buffer(rev_t * buffer, unsigned long buflen,
unsigned long pos, unsigned long n) {
while (n + pos >= buflen)
n -= buflen;
return buffer[n + pos];
}
/* overwrites a value in a ringbuffer, but pos stays the same.
* n == 0 overwrites the oldest sample pushed in the buffer.
* n == buflen-1 overwrites the sample written to the buffer
* at the last push_buffer call.
* n must not exceed buflen-1, or your computer... you know.
*/
static inline
void
write_buffer(rev_t insample, rev_t * buffer, unsigned long buflen,
unsigned long pos, unsigned long n) {
while (n + pos >= buflen)
n -= buflen;
buffer[n + pos] = insample;
}
#define db2lin(x) ((x) > -90.0f ? powf(10.0f, (x) * 0.05f) : 0.0f)
#define ABS(x) (x)>0.0f?(x):-1.0f*(x)
#define LN_2_2 0.34657359f
#define LIMIT(v,l,u) ((v)<(l)?(l):((v)>(u)?(u):(v)))
#define BIQUAD_TYPE float
typedef BIQUAD_TYPE bq_t;
typedef struct {
bq_t a1;
bq_t a2;
bq_t b0;
bq_t b1;
bq_t b2;
rev_t x1;
rev_t x2;
rev_t y1;
rev_t y2;
} biquad;
static inline void biquad_init(biquad *f) {
f->x1 = 0.0f;
f->x2 = 0.0f;
f->y1 = 0.0f;
f->y2 = 0.0f;
}
static inline
void
eq_set_params(biquad *f, bq_t fc, bq_t gain, bq_t bw, bq_t fs) {
bq_t w = 2.0f * M_PI * LIMIT(fc, 1.0f, fs/2.0f) / fs;
bq_t cw = cosf(w);
bq_t sw = sinf(w);
bq_t J = pow(10.0f, gain * 0.025f);
bq_t g = sw * sinhf(LN_2_2 * LIMIT(bw, 0.0001f, 4.0f) * w / sw);
bq_t a0r = 1.0f / (1.0f + (g / J));
f->b0 = (1.0f + (g * J)) * a0r;
f->b1 = (-2.0f * cw) * a0r;
f->b2 = (1.0f - (g * J)) * a0r;
f->a1 = -(f->b1);
f->a2 = ((g / J) - 1.0f) * a0r;
}
static inline void lp_set_params(biquad *f, bq_t fc, bq_t bw, bq_t fs) {
bq_t omega = 2.0 * M_PI * fc/fs;
bq_t sn = sin(omega);
bq_t cs = cos(omega);
bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
const float a0r = 1.0 / (1.0 + alpha);
f->b0 = a0r * (1.0 - cs) * 0.5;
f->b1 = a0r * (1.0 - cs);
f->b2 = a0r * (1.0 - cs) * 0.5;
f->a1 = a0r * (2.0 * cs);
f->a2 = a0r * (alpha - 1.0);
}
static inline
void
hp_set_params(biquad *f, bq_t fc, bq_t bw, bq_t fs)
{
bq_t omega = 2.0 * M_PI * fc/fs;
bq_t sn = sin(omega);
bq_t cs = cos(omega);
bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
const float a0r = 1.0 / (1.0 + alpha);
f->b0 = a0r * (1.0 + cs) * 0.5;
f->b1 = a0r * -(1.0 + cs);
f->b2 = a0r * (1.0 + cs) * 0.5;
f->a1 = a0r * (2.0 * cs);
f->a2 = a0r * (alpha - 1.0);
}
static inline
rev_t
biquad_run(biquad *f, rev_t x) {
union {
rev_t y;
uint32_t y_int;
} u;
u.y = f->b0 * x + f->b1 * f->x1 + f->b2 * f->x2
+ f->a1 * f->y1 + f->a2 * f->y2;
#ifdef REVERB_CALC_FLOAT
if ((u.y_int & 0x7f800000) == 0)
u.y = 0.0f;
#endif
f->x2 = f->x1;
f->x1 = x;
f->y2 = f->y1;
f->y1 = u.y;
return u.y;
}
typedef struct {
float feedback;
float fb_gain;
float freq_resp;
rev_t * ringbuffer;
unsigned long buflen;
unsigned long * buffer_pos;
biquad * filter;
rev_t last_out;
} COMB_FILTER;
typedef struct {
float feedback;
float fb_gain;
float in_gain;
rev_t * ringbuffer;
unsigned long buflen;
unsigned long * buffer_pos;
rev_t last_out;
} ALLP_FILTER;
/* The structure used to hold port connection information and state */
typedef struct {
unsigned long num_combs; /* total number of comb filters */
unsigned long num_allps; /* total number of allpass filters */
COMB_FILTER * combs;
ALLP_FILTER * allps;
biquad * low_pass; /* ptr to 2 low-pass filters */
biquad * high_pass; /* ptr to 2 high-pass filters */
unsigned long sample_rate;
LADSPA_Data * decay;
LADSPA_Data * drylevel;
LADSPA_Data * wetlevel;
LADSPA_Data * combs_en; /* on/off */
LADSPA_Data * allps_en; /* on/off */
LADSPA_Data * bandpass_en; /* on/off */
LADSPA_Data * stereo_enh; /* on/off */
LADSPA_Data * mode;
LADSPA_Data * input_L;
LADSPA_Data * output_L;
LADSPA_Data * input_R;
LADSPA_Data * output_R;
LADSPA_Data old_decay;
LADSPA_Data old_stereo_enh;
LADSPA_Data old_mode;
LADSPA_Data run_adding_gain;
} Reverb;
typedef struct {
LADSPA_Data delay;
LADSPA_Data feedback;
LADSPA_Data freq_resp;
} COMB_DATA;
typedef struct {
LADSPA_Data delay;
LADSPA_Data feedback;
} ALLP_DATA;
typedef struct {
unsigned long num_combs;
unsigned long num_allps;
COMB_DATA combs[MAX_COMBS];
ALLP_DATA allps[MAX_ALLPS];
LADSPA_Data bandpass_low;
LADSPA_Data bandpass_high;
} REVERB_DATA;

View File

@@ -1,914 +0,0 @@
/*
Copyright (C) 2004 Tom Szilagyi
This file is the output of TAP Reverb Editor, and is part of TAP Reverberator.
Please use TAP Reverb Editor to re-generate this file, rather than editing by hand.
Visit http://tap-plugins.sf.net for more info.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "tap_reverb.h"
/* Number of reverb presets */
#define NUM_MODES 43
/* Reverb Type data */
REVERB_DATA reverb_data[NUM_MODES] = {
{
5,
5,
{
{0.1015f, 70.22f, 0.4845f},
{0.1042f, 80.76f, 0.4000f},
{0.1108f, 65.25f, 0.4000f},
{0.1309f, 80.00f, 0.5342f},
{0.1386f, 52.84f, 0.4000f},
},
{
{0.0067f, 65.00f},
{0.0061f, 65.00f},
{0.0059f, 65.00f},
{0.0055f, 65.00f},
{0.0101f, 80.00f},
},
400.0f,
10000.0f,
},
{
5,
5,
{
{0.1077f, 70.22f, 0.4845f},
{0.1124f, 80.76f, 0.4000f},
{0.1185f, 65.25f, 0.4000f},
{0.1866f, 80.00f, 0.5342f},
{0.1943f, 52.84f, 0.4000f},
},
{
{0.0067f, 65.00f},
{0.0061f, 65.00f},
{0.0059f, 65.00f},
{0.0055f, 65.00f},
{0.0101f, 80.00f},
},
400.0f,
10000.0f,
},
{
6,
4,
{
{0.0251f, 64.80f, 0.2026f},
{0.0306f, 70.48f, 0.2731f},
{0.0350f, 67.40f, 0.5727f},
{0.0405f, 72.69f, 0.3128f},
{0.0449f, 61.23f, 0.7225f},
{0.0515f, 67.84f, 0.6167f},
},
{
{0.0056f, 75.00f},
{0.0051f, 90.00f},
{0.0048f, 85.00f},
{0.0044f, 70.00f},
},
80.0f,
15000.0f,
},
{
6,
8,
{
{0.0251f, 64.80f, 0.2026f},
{0.0306f, 70.48f, 0.2731f},
{0.0350f, 67.40f, 0.5727f},
{0.0405f, 72.69f, 0.3128f},
{0.0449f, 61.23f, 0.7225f},
{0.0515f, 67.84f, 0.6167f},
},
{
{0.0056f, 75.00f},
{0.0051f, 90.00f},
{0.0048f, 85.00f},
{0.0044f, 70.00f},
{0.0014f, 45.51f},
{0.0015f, 77.95f},
{0.0017f, 65.47f},
{0.0019f, 57.57f},
},
80.0f,
15000.0f,
},
{
8,
11,
{
{0.0251f, 64.80f, 0.2026f},
{0.0306f, 70.48f, 0.2731f},
{0.0350f, 67.40f, 0.5727f},
{0.0405f, 72.69f, 0.3128f},
{0.0449f, 61.23f, 0.7225f},
{0.0515f, 67.84f, 0.6167f},
{0.0800f, 53.77f, 0.7048f},
{0.0899f, 45.48f, 0.6960f},
},
{
{0.0056f, 75.00f},
{0.0051f, 90.00f},
{0.0048f, 85.00f},
{0.0044f, 70.00f},
{0.0014f, 45.51f},
{0.0015f, 77.95f},
{0.0017f, 65.47f},
{0.0019f, 57.57f},
{0.0071f, 60.00f},
{0.0111f, 80.00f},
{0.0126f, 70.00f},
},
80.0f,
15000.0f,
},
{
8,
4,
{
{0.2236f, 62.93f, 0.3416f},
{0.2329f, 75.14f, 0.3602f},
{0.2390f, 70.34f, 0.2687f},
{0.2438f, 82.99f, 0.5093f},
{0.2499f, 89.97f, 0.2467f},
{0.2282f, 60.75f, 0.3416f},
{0.1392f, 55.00f, 0.3744f},
{0.1348f, 75.00f, 0.2467f},
},
{
{0.0167f, 75.00f},
{0.0163f, 65.00f},
{0.0158f, 85.00f},
{0.0155f, 80.00f},
},
100.0f,
6500.0f,
},
{
10,
7,
{
{0.2236f, 62.93f, 0.3416f},
{0.2329f, 75.14f, 0.3602f},
{0.2390f, 70.34f, 0.2687f},
{0.2438f, 82.99f, 0.5093f},
{0.2499f, 89.97f, 0.2467f},
{0.2282f, 60.75f, 0.3416f},
{0.2352f, 52.90f, 0.3106f},
{0.1392f, 55.00f, 0.3744f},
{0.1469f, 68.00f, 0.5771f},
{0.1348f, 75.00f, 0.2467f},
},
{
{0.0167f, 75.00f},
{0.0163f, 65.00f},
{0.0158f, 85.00f},
{0.0155f, 80.00f},
{0.0064f, 85.00f},
{0.0068f, 75.00f},
{0.0072f, 65.00f},
},
100.0f,
6500.0f,
},
{
5,
7,
{
{0.0520f, 70.22f, 0.4720f},
{0.0598f, 80.76f, 0.4000f},
{0.0644f, 65.25f, 0.4000f},
{0.0737f, 80.00f, 0.6957f},
{0.0845f, 52.84f, 0.7205f},
},
{
{0.0049f, 67.11f},
{0.0069f, 59.05f},
{0.0073f, 87.59f},
{0.0079f, 59.67f},
{0.0085f, 65.87f},
{0.0095f, 75.18f},
{0.0100f, 71.46f},
},
400.0f,
10000.0f,
},
{
5,
4,
{
{0.0280f, 82.20f, 0.4720f},
{0.0303f, 80.20f, 0.5652f},
{0.0325f, 77.30f, 0.6211f},
{0.0389f, 75.30f, 0.5217f},
{0.0415f, 59.67f, 0.6522f},
},
{
{0.0067f, 65.00f},
{0.0061f, 65.00f},
{0.0059f, 65.00f},
{0.0055f, 65.00f},
},
100.0f,
10000.0f,
},
{
5,
5,
{
{0.0280f, 82.20f, 0.4720f},
{0.0303f, 80.20f, 0.5652f},
{0.0325f, 77.30f, 0.6211f},
{0.0389f, 75.30f, 0.5217f},
{0.0415f, 59.67f, 0.6522f},
},
{
{0.0067f, 75.00f},
{0.0061f, 65.00f},
{0.0059f, 65.00f},
{0.0055f, 65.00f},
{0.0071f, 75.00f},
},
200.0f,
15000.0f,
},
{
6,
5,
{
{0.1015f, 70.22f, 0.4845f},
{0.1042f, 80.76f, 0.4000f},
{0.1108f, 65.25f, 0.4000f},
{0.1309f, 80.00f, 0.5342f},
{0.1386f, 52.84f, 0.4000f},
{0.0520f, 72.08f, 0.4000f},
},
{
{0.0067f, 65.00f},
{0.0061f, 65.00f},
{0.0059f, 65.00f},
{0.0055f, 65.00f},
{0.0101f, 80.00f},
},
400.0f,
10000.0f,
},
{
7,
4,
{
{0.0536f, 82.20f, 0.3416f},
{0.0629f, 52.84f, 0.3602f},
{0.0690f, 77.30f, 0.3168f},
{0.0738f, 75.30f, 0.5093f},
{0.0799f, 59.67f, 0.3106f},
{0.1634f, 80.00f, 0.5652f},
{0.1680f, 80.00f, 0.5714f},
},
{
{0.0058f, 65.00f},
{0.0055f, 65.00f},
{0.0063f, 71.46f},
{0.0069f, 80.00f},
},
600.0f,
18000.0f,
},
{
7,
7,
{
{0.0536f, 82.20f, 0.3416f},
{0.0629f, 52.84f, 0.3602f},
{0.0690f, 77.30f, 0.3168f},
{0.0738f, 75.30f, 0.5093f},
{0.0799f, 59.67f, 0.3106f},
{0.1634f, 80.00f, 0.5652f},
{0.1680f, 80.00f, 0.5714f},
},
{
{0.0058f, 65.00f},
{0.0055f, 65.00f},
{0.0063f, 71.46f},
{0.0069f, 80.00f},
{0.0121f, 80.00f},
{0.0127f, 66.49f},
{0.0137f, 88.21f},
},
600.0f,
18000.0f,
},
{
5,
4,
{
{0.0536f, 82.20f, 0.4783f},
{0.0629f, 52.84f, 0.4348f},
{0.0690f, 77.30f, 0.5000f},
{0.0738f, 75.30f, 0.4500f},
{0.0799f, 59.67f, 0.4500f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
},
100.0f,
8000.0f,
},
{
5,
4,
{
{0.0536f, 82.20f, 0.4000f},
{0.0629f, 52.84f, 0.4348f},
{0.0690f, 77.30f, 0.5000f},
{0.0738f, 75.30f, 0.4500f},
{0.0799f, 59.67f, 0.4500f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
},
100.0f,
8000.0f,
},
{
5,
4,
{
{0.0586f, 82.20f, 0.4000f},
{0.0679f, 52.84f, 0.4348f},
{0.0740f, 77.30f, 0.5000f},
{0.0788f, 75.30f, 0.4500f},
{0.0849f, 59.67f, 0.4500f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
},
100.0f,
8000.0f,
},
{
5,
7,
{
{0.0586f, 82.20f, 0.4000f},
{0.0679f, 52.84f, 0.4348f},
{0.0740f, 77.30f, 0.5000f},
{0.0788f, 75.30f, 0.4500f},
{0.0849f, 59.67f, 0.4500f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
{0.0141f, 80.00f},
{0.0133f, 57.19f},
{0.0151f, 65.25f},
},
100.0f,
8000.0f,
},
{
5,
4,
{
{0.0506f, 82.20f, 0.3416f},
{0.0599f, 52.84f, 0.3602f},
{0.0660f, 77.30f, 0.3168f},
{0.0708f, 75.30f, 0.5093f},
{0.0769f, 59.67f, 0.3106f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
},
100.0f,
8000.0f,
},
{
5,
4,
{
{0.0536f, 82.20f, 0.3416f},
{0.0629f, 52.84f, 0.3602f},
{0.0690f, 77.30f, 0.3168f},
{0.0738f, 75.30f, 0.5093f},
{0.0799f, 59.67f, 0.3106f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
},
100.0f,
8000.0f,
},
{
7,
4,
{
{0.0536f, 82.20f, 0.3416f},
{0.0629f, 52.84f, 0.3602f},
{0.0690f, 77.30f, 0.3168f},
{0.0738f, 75.30f, 0.5093f},
{0.0799f, 59.67f, 0.3106f},
{0.0582f, 77.66f, 0.3416f},
{0.0652f, 68.35f, 0.3106f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
},
100.0f,
8000.0f,
},
{
7,
6,
{
{0.0536f, 82.20f, 0.3416f},
{0.0629f, 52.84f, 0.3602f},
{0.0690f, 77.30f, 0.3168f},
{0.0738f, 75.30f, 0.5093f},
{0.0799f, 59.67f, 0.3106f},
{0.0582f, 77.66f, 0.3416f},
{0.0652f, 68.35f, 0.3106f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
{0.0126f, 70.84f},
{0.0138f, 86.35f},
},
100.0f,
8000.0f,
},
{
4,
4,
{
{0.0752f, 61.53f, 0.4000f},
{0.0536f, 28.64f, 0.4000f},
{0.0907f, 85.11f, 0.4000f},
{0.0660f, 47.88f, 0.4000f},
},
{
{0.0039f, 80.00f},
{0.0043f, 70.84f},
{0.0045f, 58.43f},
{0.0049f, 43.53f},
},
50.0f,
10000.0f,
},
{
4,
4,
{
{0.1742f, 47.26f, 0.4783f},
{0.1526f, 23.06f, 0.1863f},
{0.2021f, 72.08f, 0.4000f},
{0.2175f, 90.07f, 0.4000f},
},
{
{0.0039f, 80.00f},
{0.0043f, 70.84f},
{0.0045f, 58.43f},
{0.0049f, 43.53f},
},
50.0f,
10000.0f,
},
{
4,
2,
{
{0.0969f, 52.22f, 0.6149f},
{0.0984f, 54.70f, 0.6025f},
{0.1000f, 80.00f, 0.5217f},
{0.1015f, 53.46f, 0.2671f},
},
{
{0.0017f, 46.64f},
{0.0021f, 47.88f},
},
100.0f,
13000.0f,
},
{
4,
2,
{
{0.1526f, 52.22f, 0.6149f},
{0.1541f, 65.87f, 0.6025f},
{0.1557f, 80.00f, 0.5217f},
{0.1572f, 53.46f, 0.2671f},
},
{
{0.0075f, 46.64f},
{0.0078f, 47.88f},
},
100.0f,
13000.0f,
},
{
4,
2,
{
{0.2082f, 52.22f, 0.6149f},
{0.2098f, 54.70f, 0.6025f},
{0.2113f, 80.00f, 0.5217f},
{0.2129f, 53.46f, 0.2671f},
},
{
{0.0075f, 46.64f},
{0.0078f, 47.88f},
},
100.0f,
13000.0f,
},
{
6,
4,
{
{0.0536f, 82.20f, 0.4000f},
{0.0629f, 75.80f, 0.5901f},
{0.0690f, 77.30f, 0.5000f},
{0.0738f, 75.30f, 0.4500f},
{0.0799f, 59.67f, 0.4500f},
{0.1170f, 74.56f, 0.4783f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
},
100.0f,
13000.0f,
},
{
6,
4,
{
{0.0536f, 82.20f, 0.4000f},
{0.0629f, 75.80f, 0.5901f},
{0.0690f, 77.30f, 0.5000f},
{0.0738f, 75.30f, 0.4500f},
{0.0799f, 59.67f, 0.4500f},
{0.1727f, 74.56f, 0.5590f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
},
100.0f,
13000.0f,
},
{
6,
4,
{
{0.0814f, 82.20f, 0.4000f},
{0.0892f, 75.80f, 0.5901f},
{0.0953f, 77.30f, 0.5000f},
{0.1046f, 75.30f, 0.5714f},
{0.1108f, 59.67f, 0.4500f},
{0.1912f, 39.81f, 0.6832f},
},
{
{0.0073f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
},
100.0f,
13000.0f,
},
{
6,
6,
{
{0.0814f, 82.20f, 0.4000f},
{0.0892f, 75.80f, 0.5901f},
{0.0953f, 77.30f, 0.5000f},
{0.1046f, 75.30f, 0.5714f},
{0.1108f, 59.67f, 0.4500f},
{0.1912f, 39.81f, 0.6832f},
},
{
{0.0073f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
{0.0164f, 66.49f},
{0.0181f, 56.57f},
},
100.0f,
13000.0f,
},
{
5,
4,
{
{0.1170f, 82.20f, 0.5466f},
{0.1232f, 75.18f, 0.4907f},
{0.1309f, 69.60f, 0.6335f},
{0.1417f, 49.74f, 0.6957f},
{0.1526f, 59.67f, 0.5528f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
},
1000.0f,
10000.0f,
},
{
5,
6,
{
{0.1170f, 82.20f, 0.5466f},
{0.1232f, 75.18f, 0.4907f},
{0.1309f, 69.60f, 0.6335f},
{0.1417f, 49.74f, 0.6957f},
{0.1526f, 59.67f, 0.5528f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
{0.0143f, 56.57f},
{0.0153f, 66.49f},
},
1000.0f,
10000.0f,
},
{
6,
4,
{
{0.1170f, 82.20f, 0.6398f},
{0.1232f, 75.18f, 0.7453f},
{0.1309f, 69.60f, 0.6398f},
{0.1417f, 49.74f, 0.6957f},
{0.1526f, 59.67f, 0.7205f},
{0.1634f, 84.49f, 0.7453f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
},
2000.0f,
15000.0f,
},
{
6,
6,
{
{0.1170f, 82.20f, 0.6398f},
{0.1232f, 75.18f, 0.7453f},
{0.1309f, 69.60f, 0.6398f},
{0.1417f, 49.74f, 0.6957f},
{0.1526f, 59.67f, 0.7205f},
{0.1634f, 84.49f, 0.7453f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
{0.0128f, 80.00f},
{0.0136f, 88.83f},
},
2000.0f,
15000.0f,
},
{
5,
4,
{
{0.0506f, 82.20f, 0.6832f},
{0.0599f, 73.94f, 0.6832f},
{0.0660f, 61.53f, 0.7453f},
{0.0708f, 75.30f, 0.7702f},
{0.0769f, 59.67f, 0.8012f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
},
1000.0f,
7000.0f,
},
{
5,
4,
{
{0.0536f, 82.20f, 0.6832f},
{0.0629f, 73.94f, 0.6832f},
{0.0690f, 61.53f, 0.7453f},
{0.0738f, 75.30f, 0.7702f},
{0.0799f, 59.67f, 0.8012f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
},
1000.0f,
7000.0f,
},
{
5,
4,
{
{0.0586f, 82.20f, 0.6832f},
{0.0679f, 73.94f, 0.6832f},
{0.0740f, 61.53f, 0.7453f},
{0.0788f, 75.30f, 0.7702f},
{0.0849f, 59.67f, 0.8012f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
},
1000.0f,
7000.0f,
},
{
5,
7,
{
{0.0586f, 82.20f, 0.6832f},
{0.0679f, 73.94f, 0.6832f},
{0.0740f, 61.53f, 0.7453f},
{0.0788f, 75.30f, 0.7702f},
{0.0849f, 59.67f, 0.8012f},
},
{
{0.0067f, 65.00f},
{0.0063f, 65.00f},
{0.0058f, 65.00f},
{0.0055f, 65.00f},
{0.0122f, 80.00f},
{0.0138f, 65.25f},
{0.0143f, 75.00f},
},
1000.0f,
7000.0f,
},
{
5,
4,
{
{0.0505f, 70.22f, 0.4720f},
{0.0582f, 80.76f, 0.4000f},
{0.0629f, 65.25f, 0.4000f},
{0.0892f, 80.00f, 0.6957f},
{0.0953f, 52.84f, 0.7205f},
},
{
{0.0044f, 65.00f},
{0.0037f, 67.11f},
{0.0057f, 80.00f},
{0.0060f, 56.57f},
},
400.0f,
10000.0f,
},
{
5,
6,
{
{0.0505f, 70.22f, 0.4720f},
{0.0582f, 80.76f, 0.4000f},
{0.0629f, 65.25f, 0.4000f},
{0.0892f, 80.00f, 0.6957f},
{0.0953f, 52.84f, 0.7205f},
},
{
{0.0044f, 65.00f},
{0.0037f, 67.11f},
{0.0057f, 80.00f},
{0.0060f, 56.57f},
{0.0142f, 80.00f},
{0.0151f, 59.67f},
},
400.0f,
10000.0f,
},
{
5,
4,
{
{0.2051f, 52.84f, 0.7826f},
{0.2082f, 68.35f, 0.7019f},
{0.2113f, 80.00f, 0.6832f},
{0.2206f, 83.25f, 0.7081f},
{0.2237f, 67.73f, 0.5280f},
},
{
{0.0067f, 65.00f},
{0.0061f, 65.00f},
{0.0059f, 65.00f},
{0.0055f, 65.00f},
},
400.0f,
10000.0f,
},
{
6,
5,
{
{0.0280f, 82.20f, 0.4720f},
{0.0304f, 80.20f, 0.5652f},
{0.0329f, 77.30f, 0.6211f},
{0.0389f, 75.30f, 0.5217f},
{0.0415f, 59.67f, 0.6522f},
{0.0768f, 80.00f, 0.7702f},
},
{
{0.0057f, 65.00f},
{0.0062f, 65.00f},
{0.0066f, 77.04f},
{0.0050f, 65.00f},
{0.0038f, 56.57f},
},
100.0f,
10000.0f,
},
{
6,
7,
{
{0.0280f, 82.20f, 0.4720f},
{0.0304f, 80.20f, 0.5652f},
{0.0329f, 77.30f, 0.6211f},
{0.0389f, 75.30f, 0.5217f},
{0.0415f, 59.67f, 0.6522f},
{0.0768f, 80.00f, 0.7702f},
},
{
{0.0057f, 65.00f},
{0.0062f, 65.00f},
{0.0137f, 77.04f},
{0.0050f, 65.00f},
{0.0038f, 56.57f},
{0.0147f, 60.91f},
{0.0164f, 52.84f},
},
100.0f,
10000.0f,
},
};

View File

@@ -1,768 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_rotspeak.c,v 1.3 2004/02/21 17:33:36 tszilagyi Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ladspa.h>
#include "tap_utils.h"
/* The Unique ID of the plugin: */
#define ID_STEREO 2149
/* The port numbers for the plugin: */
#define BASSFREQ 0
#define HORNFREQ 1
#define STWIDTH 2
#define HRBAL 3
#define LATENCY 4
#define INPUT_L 5
#define INPUT_R 6
#define OUTPUT_L 7
#define OUTPUT_R 8
/* Total number of ports */
#define PORTCOUNT_STEREO 9
/*
* This has to be bigger than 0.3f * sample_rate / (2*PI) for any sample rate.
* At 192 kHz 9168 is needed so this should be enough.
*/
#define PM_DEPTH 9200
/* maximum phase mod freq */
#define PM_FREQ 30.0f
/* splitting input signals into low and high freq components */
#define SPLIT_FREQ 1000.0f
#define SPLIT_BW 1.0f
/* approx. sound velocity in air [m/s] */
#define C_AIR 340.0f
/* coefficient between rotating frequency and pitch mod depth (aka. Doppler effect) */
#define FREQ_PITCH 1.6f
/* cosine table for fast computations */
LADSPA_Data cos_table[1024];
/* The structure used to hold port connection information and state */
typedef struct {
LADSPA_Data * hornfreq;
LADSPA_Data * bassfreq;
LADSPA_Data * stwidth;
LADSPA_Data * hrbal;
LADSPA_Data * latency;
LADSPA_Data * input_L;
LADSPA_Data * input_R;
LADSPA_Data * output_L;
LADSPA_Data * output_R;
LADSPA_Data * ringbuffer_h_L;
unsigned long buflen_h_L;
unsigned long pos_h_L;
LADSPA_Data * ringbuffer_h_R;
unsigned long buflen_h_R;
unsigned long pos_h_R;
LADSPA_Data * ringbuffer_b_L;
unsigned long buflen_b_L;
unsigned long pos_b_L;
LADSPA_Data * ringbuffer_b_R;
unsigned long buflen_b_R;
unsigned long pos_b_R;
biquad * eq_filter_L;
biquad * lp_filter_L;
biquad * hp_filter_L;
biquad * eq_filter_R;
biquad * lp_filter_R;
biquad * hp_filter_R;
unsigned long sample_rate;
LADSPA_Data phase_h;
LADSPA_Data phase_b;
LADSPA_Data run_adding_gain;
} RotSpkr;
void cleanup_RotSpkr(LADSPA_Handle Instance);
/* Construct a new plugin instance. */
LADSPA_Handle
instantiate_RotSpkr(const LADSPA_Descriptor * Descriptor,
unsigned long sample_rate) {
LADSPA_Handle * ptr;
if ((ptr = calloc(1, sizeof(RotSpkr))) != NULL) {
RotSpkr* rotSpeak = (RotSpkr*)ptr;
rotSpeak->sample_rate = sample_rate;
rotSpeak->run_adding_gain = 1.0;
if ((rotSpeak->ringbuffer_h_L =
calloc(2 * PM_DEPTH, sizeof(LADSPA_Data))) == NULL)
{
cleanup_RotSpkr((LADSPA_Handle)rotSpeak);
return NULL;
}
if ((rotSpeak->ringbuffer_h_R =
calloc(2 * PM_DEPTH, sizeof(LADSPA_Data))) == NULL)
{
cleanup_RotSpkr((LADSPA_Handle)rotSpeak);
return NULL;
}
rotSpeak->buflen_h_L = ceil(0.3f * sample_rate / M_PI);
rotSpeak->buflen_h_R = ceil(0.3f * sample_rate / M_PI);
rotSpeak->pos_h_L = 0;
rotSpeak->pos_h_R = 0;
if ((rotSpeak->ringbuffer_b_L =
calloc(2 * PM_DEPTH, sizeof(LADSPA_Data))) == NULL)
{
cleanup_RotSpkr((LADSPA_Handle)rotSpeak);
return NULL;
}
if ((rotSpeak->ringbuffer_b_R =
calloc(2 * PM_DEPTH, sizeof(LADSPA_Data))) == NULL)
{
cleanup_RotSpkr((LADSPA_Handle)rotSpeak);
return NULL;
}
rotSpeak->buflen_b_L = ceil(0.3f * sample_rate / M_PI);
rotSpeak->buflen_b_R = ceil(0.3f * sample_rate / M_PI);
rotSpeak->pos_b_L = 0;
rotSpeak->pos_b_R = 0;
if ((rotSpeak->eq_filter_L = calloc(1, sizeof(biquad))) == NULL)
{
cleanup_RotSpkr((LADSPA_Handle)rotSpeak);
return NULL;
}
if ((rotSpeak->lp_filter_L = calloc(1, sizeof(biquad))) == NULL)
{
cleanup_RotSpkr((LADSPA_Handle)rotSpeak);
return NULL;
}
if ((rotSpeak->hp_filter_L = calloc(1, sizeof(biquad))) == NULL)
{
cleanup_RotSpkr((LADSPA_Handle)rotSpeak);
return NULL;
}
if ((rotSpeak->eq_filter_R = calloc(1, sizeof(biquad))) == NULL)
{
cleanup_RotSpkr((LADSPA_Handle)rotSpeak);
return NULL;
}
if ((rotSpeak->lp_filter_R = calloc(1, sizeof(biquad))) == NULL)
{
cleanup_RotSpkr((LADSPA_Handle)rotSpeak);
return NULL;
}
if ((rotSpeak->hp_filter_R = calloc(1, sizeof(biquad))) == NULL)
{
cleanup_RotSpkr((LADSPA_Handle)rotSpeak);
return NULL;
}
return ptr;
}
return NULL;
}
void
activate_RotSpkr(LADSPA_Handle Instance) {
int i;
RotSpkr * ptr;
ptr = (RotSpkr *)Instance;
for (i = 0; i < 2 * PM_DEPTH; i++) {
ptr->ringbuffer_h_L[i] = 0.0f;
ptr->ringbuffer_h_R[i] = 0.0f;
ptr->ringbuffer_b_L[i] = 0.0f;
ptr->ringbuffer_b_R[i] = 0.0f;
}
ptr->phase_h = 0.0f;
ptr->phase_b = 0.0f;
biquad_init(ptr->eq_filter_L);
biquad_init(ptr->lp_filter_L);
biquad_init(ptr->hp_filter_L);
biquad_init(ptr->eq_filter_R);
biquad_init(ptr->lp_filter_R);
biquad_init(ptr->hp_filter_R);
eq_set_params(ptr->eq_filter_L, SPLIT_FREQ, +8.0f, SPLIT_BW, ptr->sample_rate);
eq_set_params(ptr->eq_filter_R, SPLIT_FREQ, +8.0f, SPLIT_BW, ptr->sample_rate);
lp_set_params(ptr->lp_filter_L, SPLIT_FREQ, SPLIT_BW, ptr->sample_rate);
lp_set_params(ptr->lp_filter_R, SPLIT_FREQ, SPLIT_BW, ptr->sample_rate);
hp_set_params(ptr->hp_filter_L, SPLIT_FREQ, SPLIT_BW, ptr->sample_rate);
hp_set_params(ptr->hp_filter_R, SPLIT_FREQ, SPLIT_BW, ptr->sample_rate);
}
/* Connect a port to a data location. */
void
connect_port_RotSpkr(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * DataLocation) {
RotSpkr * ptr;
ptr = (RotSpkr *)Instance;
switch (Port) {
case HORNFREQ:
ptr->hornfreq = DataLocation;
break;
case BASSFREQ:
ptr->bassfreq = DataLocation;
break;
case STWIDTH:
ptr->stwidth = DataLocation;
break;
case HRBAL:
ptr->hrbal = DataLocation;
break;
case LATENCY:
ptr->latency = DataLocation;
*(ptr->latency) = ptr->buflen_h_L / 2; /* IS THIS LEGAL? YES, ONLY IF DataLocation points to valid memory location on stack/heap*/
break;
case INPUT_L:
ptr->input_L = DataLocation;
break;
case INPUT_R:
ptr->input_R = DataLocation;
break;
case OUTPUT_L:
ptr->output_L = DataLocation;
break;
case OUTPUT_R:
ptr->output_R = DataLocation;
break;
}
}
void
run_RotSpkr(LADSPA_Handle Instance,
unsigned long SampleCount) {
RotSpkr * ptr = (RotSpkr *)Instance;
LADSPA_Data * input_L = ptr->input_L;
LADSPA_Data * input_R = ptr->input_R;
LADSPA_Data * output_L = ptr->output_L;
LADSPA_Data * output_R = ptr->output_R;
LADSPA_Data freq_h = LIMIT(*(ptr->hornfreq),0.0f,PM_FREQ);
LADSPA_Data freq_b = LIMIT(*(ptr->bassfreq),0.0f,PM_FREQ);
LADSPA_Data stwidth = LIMIT(*(ptr->stwidth),0.0f,100.0f);
LADSPA_Data hrbal = LIMIT(*(ptr->hrbal),0.0f,1.0f);
LADSPA_Data pmdepth_h =
LIMIT(1.0f/(1.0f+FREQ_PITCH*freq_h/C_AIR) * ptr->sample_rate
/ 200.0f / M_PI / freq_h, 0, ptr->buflen_h_L / 2);
LADSPA_Data pmdepth_b =
LIMIT(1.0f/(1.0f+FREQ_PITCH*freq_b/C_AIR) * ptr->sample_rate
/ 200.0f / M_PI / freq_b, 0, ptr->buflen_b_L / 2);
unsigned long sample_index;
LADSPA_Data in_L = 0.0f, in_R = 0.0f;
LADSPA_Data lo_L = 0.0f, lo_R = 0.0f;
LADSPA_Data hi_L = 0.0f, hi_R = 0.0f;
LADSPA_Data phase_h_L = 0.0f, phase_b_L = 0.0f;
LADSPA_Data phase_h_R = 0.0f, phase_b_R = 0.0f;
LADSPA_Data phase_pm_h_L = 0.0f, phase_pm_b_L = 0.0f;
LADSPA_Data phase_pm_h_R = 0.0f, phase_pm_b_R = 0.0f;
LADSPA_Data pm_h_L = 0.0f, pm_b_L = 0.0f;
LADSPA_Data pm_h_R = 0.0f, pm_b_R = 0.0f;
LADSPA_Data fpos_h_L = 0.0f, fpos_b_L = 0.0f, fpos_h_R = 0.0f, fpos_b_R = 0.0f;
LADSPA_Data n_h_L = 0.0f, n_b_L = 0.0f, n_h_R = 0.0f, n_b_R = 0.0f;
LADSPA_Data rem_h_L = 0.0f, rem_b_L = 0.0f, rem_h_R = 0.0f, rem_b_R = 0.0f;
LADSPA_Data sa_h_L = 0.0f, sa_b_L = 0.0f, sb_h_L = 0.0f, sb_b_L = 0.0f;
LADSPA_Data sa_h_R = 0.0f, sa_b_R = 0.0f, sb_h_R = 0.0f, sb_b_R = 0.0f;
for (sample_index = 0; sample_index < SampleCount; sample_index++) {
in_L = *(input_L++);
in_R = *(input_R++);
in_L = biquad_run(ptr->eq_filter_L, in_L);
in_R = biquad_run(ptr->eq_filter_R, in_R);
lo_L = biquad_run(ptr->lp_filter_L, in_L);
lo_R = biquad_run(ptr->lp_filter_R, in_R);
hi_L = biquad_run(ptr->hp_filter_L, in_L);
hi_R = biquad_run(ptr->hp_filter_R, in_R);
phase_h_L = 1024.0f * freq_h * sample_index / ptr->sample_rate + ptr->phase_h;
while (phase_h_L >= 1024.0f)
phase_h_L -= 1024.0f;
phase_pm_h_L = phase_h_L + 256.0f;
while (phase_pm_h_L >= 1024.0f)
phase_pm_h_L -= 1024.0f;
phase_h_R = phase_h_L + 512.0f;
while (phase_h_R >= 1024.0f)
phase_h_R -= 1024.0f;
phase_pm_h_R = phase_h_R + 256.0f;
while (phase_pm_h_R >= 1024.0f)
phase_pm_h_R -= 1024.0f;
phase_b_L = 1024.0f * freq_b * sample_index / ptr->sample_rate + ptr->phase_b;
while (phase_b_L >= 1024.0f)
phase_b_L -= 1024.0f;
phase_pm_b_L = phase_b_L + 256.0f;
while (phase_pm_b_L >= 1024.0f)
phase_pm_b_L -= 1024.0f;
phase_b_R = phase_b_L + 512.0f;
while (phase_b_R >= 1024.0f)
phase_b_R -= 1024.0f;
phase_pm_b_R = phase_b_R + 256.0f;
while (phase_pm_b_R >= 1024.0f)
phase_pm_b_R -= 1024.0f;
push_buffer(hi_L, ptr->ringbuffer_h_L, ptr->buflen_h_L, &(ptr->pos_h_L));
push_buffer(hi_R, ptr->ringbuffer_h_R, ptr->buflen_h_R, &(ptr->pos_h_R));
push_buffer(lo_L, ptr->ringbuffer_b_L, ptr->buflen_b_L, &(ptr->pos_b_L));
push_buffer(lo_R, ptr->ringbuffer_b_R, ptr->buflen_b_R, &(ptr->pos_b_R));
fpos_h_L = pmdepth_h * (1.0f - cos_table[(unsigned long) phase_pm_h_L]);
n_h_L = floorf(fpos_h_L);
rem_h_L = fpos_h_L - n_h_L;
sa_h_L = read_buffer(ptr->ringbuffer_h_L,
ptr->buflen_h_L, ptr->pos_h_L, (unsigned long) n_h_L);
sb_h_L = read_buffer(ptr->ringbuffer_h_L,
ptr->buflen_h_L, ptr->pos_h_L, (unsigned long) n_h_L + 1);
pm_h_L = (1 - rem_h_L) * sa_h_L + rem_h_L * sb_h_L;
fpos_h_R = pmdepth_h * (1.0f - cos_table[(unsigned long) phase_pm_h_R]);
n_h_R = floorf(fpos_h_R);
rem_h_R = fpos_h_R - n_h_R;
sa_h_R = read_buffer(ptr->ringbuffer_h_R,
ptr->buflen_h_R, ptr->pos_h_R, (unsigned long) n_h_R);
sb_h_R = read_buffer(ptr->ringbuffer_h_R,
ptr->buflen_h_R, ptr->pos_h_R, (unsigned long) n_h_R + 1);
pm_h_R = (1 - rem_h_R) * sa_h_R + rem_h_R * sb_h_R;
fpos_b_L = pmdepth_b * (1.0f - cos_table[(unsigned long) phase_pm_b_L]);
n_b_L = floorf(fpos_b_L);
rem_b_L = fpos_b_L - n_b_L;
sa_b_L = read_buffer(ptr->ringbuffer_b_L,
ptr->buflen_b_L, ptr->pos_b_L, (unsigned long) n_b_L);
sb_b_L = read_buffer(ptr->ringbuffer_b_L,
ptr->buflen_b_L, ptr->pos_b_L, (unsigned long) n_b_L + 1);
pm_b_L = (1 - rem_b_L) * sa_b_L + rem_b_L * sb_b_L;
fpos_b_R = pmdepth_b * (1.0f - cos_table[(unsigned long) phase_pm_b_R]);
n_b_R = floorf(fpos_b_R);
rem_b_R = fpos_b_R - n_b_R;
sa_b_R = read_buffer(ptr->ringbuffer_b_R,
ptr->buflen_b_R, ptr->pos_b_R, (unsigned long) n_b_R);
sb_b_R = read_buffer(ptr->ringbuffer_b_R,
ptr->buflen_b_R, ptr->pos_b_R, (unsigned long) n_b_R + 1);
pm_b_R = (1 - rem_b_R) * sa_b_R + rem_b_R * sb_b_R;
*(output_L++) =
hrbal * pm_h_L * (1.0f + 0.5f * stwidth/100.0f *
cos_table[(unsigned long) phase_h_L]) +
(1.0f - hrbal) * pm_b_L * (1.0f + 0.5f * stwidth/100.0f *
cos_table[(unsigned long) phase_b_L]);
*(output_R++) =
hrbal * pm_h_R * (1.0f + 0.5f * stwidth/100.0f *
cos_table[(unsigned long) phase_h_R]) +
(1.0f - hrbal) * pm_b_R * (1.0f + 0.5f * stwidth/100.0f *
cos_table[(unsigned long) phase_b_R]);
}
ptr->phase_h += 1024.0f * freq_h * sample_index / ptr->sample_rate;
while (ptr->phase_h >= 1024.0f)
ptr->phase_h -= 1024.0f;
ptr->phase_b += 1024.0f * freq_b * sample_index / ptr->sample_rate;
while (ptr->phase_b >= 1024.0f)
ptr->phase_b -= 1024.0f;
*(ptr->latency) = ptr->buflen_h_L / 2;
}
void
set_run_adding_gain_RotSpkr(LADSPA_Handle Instance, LADSPA_Data gain) {
RotSpkr * ptr = (RotSpkr *)Instance;
ptr->run_adding_gain = gain;
}
void
run_adding_RotSpkr(LADSPA_Handle Instance,
unsigned long SampleCount) {
RotSpkr * ptr = (RotSpkr *)Instance;
LADSPA_Data * input_L = ptr->input_L;
LADSPA_Data * input_R = ptr->input_R;
LADSPA_Data * output_L = ptr->output_L;
LADSPA_Data * output_R = ptr->output_R;
LADSPA_Data freq_h = LIMIT(*(ptr->hornfreq),0.0f,PM_FREQ);
LADSPA_Data freq_b = LIMIT(*(ptr->bassfreq),0.0f,PM_FREQ);
LADSPA_Data stwidth = LIMIT(*(ptr->stwidth),0.0f,100.0f);
LADSPA_Data hrbal = LIMIT(*(ptr->hrbal),0.0f,1.0f);
LADSPA_Data pmdepth_h =
LIMIT(1.0f/(1.0f+FREQ_PITCH*freq_h/C_AIR) * ptr->sample_rate
/ 200.0f / M_PI / freq_h, 0, ptr->buflen_h_L / 2);
LADSPA_Data pmdepth_b =
LIMIT(1.0f/(1.0f+FREQ_PITCH*freq_b/C_AIR) * ptr->sample_rate
/ 200.0f / M_PI / freq_b, 0, ptr->buflen_b_L / 2);
unsigned long sample_index;
LADSPA_Data in_L = 0.0f, in_R = 0.0f;
LADSPA_Data lo_L = 0.0f, lo_R = 0.0f;
LADSPA_Data hi_L = 0.0f, hi_R = 0.0f;
LADSPA_Data phase_h_L = 0.0f, phase_b_L = 0.0f;
LADSPA_Data phase_h_R = 0.0f, phase_b_R = 0.0f;
LADSPA_Data phase_pm_h_L = 0.0f, phase_pm_b_L = 0.0f;
LADSPA_Data phase_pm_h_R = 0.0f, phase_pm_b_R = 0.0f;
LADSPA_Data pm_h_L = 0.0f, pm_b_L = 0.0f;
LADSPA_Data pm_h_R = 0.0f, pm_b_R = 0.0f;
LADSPA_Data fpos_h_L = 0.0f, fpos_b_L = 0.0f, fpos_h_R = 0.0f, fpos_b_R = 0.0f;
LADSPA_Data n_h_L = 0.0f, n_b_L = 0.0f, n_h_R = 0.0f, n_b_R = 0.0f;
LADSPA_Data rem_h_L = 0.0f, rem_b_L = 0.0f, rem_h_R = 0.0f, rem_b_R = 0.0f;
LADSPA_Data sa_h_L = 0.0f, sa_b_L = 0.0f, sb_h_L = 0.0f, sb_b_L = 0.0f;
LADSPA_Data sa_h_R = 0.0f, sa_b_R = 0.0f, sb_h_R = 0.0f, sb_b_R = 0.0f;
for (sample_index = 0; sample_index < SampleCount; sample_index++) {
in_L = *(input_L++);
in_R = *(input_R++);
in_L = biquad_run(ptr->eq_filter_L, in_L);
in_R = biquad_run(ptr->eq_filter_R, in_R);
lo_L = biquad_run(ptr->lp_filter_L, in_L);
lo_R = biquad_run(ptr->lp_filter_R, in_R);
hi_L = biquad_run(ptr->hp_filter_L, in_L);
hi_R = biquad_run(ptr->hp_filter_R, in_R);
phase_h_L = 1024.0f * freq_h * sample_index / ptr->sample_rate + ptr->phase_h;
while (phase_h_L >= 1024.0f)
phase_h_L -= 1024.0f;
phase_pm_h_L = phase_h_L + 256.0f;
while (phase_pm_h_L >= 1024.0f)
phase_pm_h_L -= 1024.0f;
phase_h_R = phase_h_L + 512.0f;
while (phase_h_R >= 1024.0f)
phase_h_R -= 1024.0f;
phase_pm_h_R = phase_h_R + 256.0f;
while (phase_pm_h_R >= 1024.0f)
phase_pm_h_R -= 1024.0f;
phase_b_L = 1024.0f * freq_b * sample_index / ptr->sample_rate + ptr->phase_b;
while (phase_b_L >= 1024.0f)
phase_b_L -= 1024.0f;
phase_pm_b_L = phase_b_L + 256.0f;
while (phase_pm_b_L >= 1024.0f)
phase_pm_b_L -= 1024.0f;
phase_b_R = phase_b_L + 512.0f;
while (phase_b_R >= 1024.0f)
phase_b_R -= 1024.0f;
phase_pm_b_R = phase_b_R + 256.0f;
while (phase_pm_b_R >= 1024.0f)
phase_pm_b_R -= 1024.0f;
push_buffer(hi_L, ptr->ringbuffer_h_L, ptr->buflen_h_L, &(ptr->pos_h_L));
push_buffer(hi_R, ptr->ringbuffer_h_R, ptr->buflen_h_R, &(ptr->pos_h_R));
push_buffer(lo_L, ptr->ringbuffer_b_L, ptr->buflen_b_L, &(ptr->pos_b_L));
push_buffer(lo_R, ptr->ringbuffer_b_R, ptr->buflen_b_R, &(ptr->pos_b_R));
fpos_h_L = pmdepth_h * (1.0f - cos_table[(unsigned long) phase_pm_h_L]);
n_h_L = floorf(fpos_h_L);
rem_h_L = fpos_h_L - n_h_L;
sa_h_L = read_buffer(ptr->ringbuffer_h_L,
ptr->buflen_h_L, ptr->pos_h_L, (unsigned long) n_h_L);
sb_h_L = read_buffer(ptr->ringbuffer_h_L,
ptr->buflen_h_L, ptr->pos_h_L, (unsigned long) n_h_L + 1);
pm_h_L = (1 - rem_h_L) * sa_h_L + rem_h_L * sb_h_L;
fpos_h_R = pmdepth_h * (1.0f - cos_table[(unsigned long) phase_pm_h_R]);
n_h_R = floorf(fpos_h_R);
rem_h_R = fpos_h_R - n_h_R;
sa_h_R = read_buffer(ptr->ringbuffer_h_R,
ptr->buflen_h_R, ptr->pos_h_R, (unsigned long) n_h_R);
sb_h_R = read_buffer(ptr->ringbuffer_h_R,
ptr->buflen_h_R, ptr->pos_h_R, (unsigned long) n_h_R + 1);
pm_h_R = (1 - rem_h_R) * sa_h_R + rem_h_R * sb_h_R;
fpos_b_L = pmdepth_b * (1.0f - cos_table[(unsigned long) phase_pm_b_L]);
n_b_L = floorf(fpos_b_L);
rem_b_L = fpos_b_L - n_b_L;
sa_b_L = read_buffer(ptr->ringbuffer_b_L,
ptr->buflen_b_L, ptr->pos_b_L, (unsigned long) n_b_L);
sb_b_L = read_buffer(ptr->ringbuffer_b_L,
ptr->buflen_b_L, ptr->pos_b_L, (unsigned long) n_b_L + 1);
pm_b_L = (1 - rem_b_L) * sa_b_L + rem_b_L * sb_b_L;
fpos_b_R = pmdepth_b * (1.0f - cos_table[(unsigned long) phase_pm_b_R]);
n_b_R = floorf(fpos_b_R);
rem_b_R = fpos_b_R - n_b_R;
sa_b_R = read_buffer(ptr->ringbuffer_b_R,
ptr->buflen_b_R, ptr->pos_b_R, (unsigned long) n_b_R);
sb_b_R = read_buffer(ptr->ringbuffer_b_R,
ptr->buflen_b_R, ptr->pos_b_R, (unsigned long) n_b_R + 1);
pm_b_R = (1 - rem_b_R) * sa_b_R + rem_b_R * sb_b_R;
*(output_L++) += ptr->run_adding_gain *
hrbal * pm_h_L * (1.0f + 0.5f * stwidth/100.0f *
cos_table[(unsigned long) phase_h_L]) +
(1.0f - hrbal) * pm_b_L * (1.0f + 0.5f * stwidth/100.0f *
cos_table[(unsigned long) phase_b_L]);
*(output_R++) += ptr->run_adding_gain *
hrbal * pm_h_R * (1.0f + 0.5f * stwidth/100.0f *
cos_table[(unsigned long) phase_h_R]) +
(1.0f - hrbal) * pm_b_R * (1.0f + 0.5f * stwidth/100.0f *
cos_table[(unsigned long) phase_b_R]);
}
ptr->phase_h += 1024.0f * freq_h * sample_index / ptr->sample_rate;
while (ptr->phase_h >= 1024.0f)
ptr->phase_h -= 1024.0f;
ptr->phase_b += 1024.0f * freq_b * sample_index / ptr->sample_rate;
while (ptr->phase_b >= 1024.0f)
ptr->phase_b -= 1024.0f;
*(ptr->latency) = ptr->buflen_h_L / 2;
}
/*
Throw away an RotSpkr effect instance.
This function should be called only when RotSpkr was allocated with calloc.
*/
void
cleanup_RotSpkr(LADSPA_Handle Instance) {
RotSpkr * ptr = (RotSpkr *)Instance;
if (!ptr)
return;
if (ptr->ringbuffer_h_L)
free(ptr->ringbuffer_h_L);
if (ptr->ringbuffer_h_R)
free(ptr->ringbuffer_h_R);
if (ptr->ringbuffer_b_L)
free(ptr->ringbuffer_b_L);
if (ptr->ringbuffer_b_R)
free(ptr->ringbuffer_b_R);
if (ptr->eq_filter_L)
free(ptr->eq_filter_L);
if (ptr->eq_filter_R)
free(ptr->eq_filter_R);
if (ptr->lp_filter_L)
free(ptr->lp_filter_L);
if (ptr->lp_filter_R)
free(ptr->lp_filter_R);
if (ptr->hp_filter_L)
free(ptr->hp_filter_L);
if (ptr->hp_filter_R)
free(ptr->hp_filter_R);
if (Instance)
free(Instance);
}
LADSPA_Descriptor * stereo_descriptor = NULL;
/* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
loaded. */
void
__attribute__((constructor)) tap_init() {
int i;
char ** port_names;
LADSPA_PortDescriptor * port_descriptors;
LADSPA_PortRangeHint * port_range_hints;
if ((stereo_descriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
exit(1);
for (i = 0; i < 1024; i++)
cos_table[i] = cosf(i * M_PI / 512.0f);
stereo_descriptor->UniqueID = ID_STEREO;
stereo_descriptor->Label = strdup("tap_rotspeak");
stereo_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
stereo_descriptor->Name = strdup("TAP Rotary Speaker");
stereo_descriptor->Maker = strdup("Tom Szilagyi");
stereo_descriptor->Copyright = strdup("GPL");
stereo_descriptor->PortCount = PORTCOUNT_STEREO;
if ((port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortDescriptor))) == NULL)
exit(1);
stereo_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
port_descriptors[HORNFREQ] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[BASSFREQ] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[STWIDTH] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[HRBAL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[LATENCY] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
port_descriptors[INPUT_L] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[INPUT_R] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT_L] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT_R] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
if ((port_names =
(char **)calloc(PORTCOUNT_STEREO, sizeof(char *))) == NULL)
exit(1);
stereo_descriptor->PortNames = (const char **)port_names;
port_names[HORNFREQ] = strdup("Horn Frequency [Hz]");
port_names[BASSFREQ] = strdup("Rotor Frequency [Hz]");
port_names[STWIDTH] = strdup("Mic Distance [%]");
port_names[HRBAL] = strdup("Rotor/Horn Mix");
port_names[LATENCY] = strdup("latency");
port_names[INPUT_L] = strdup("Input L");
port_names[INPUT_R] = strdup("Input R");
port_names[OUTPUT_L] = strdup("Output L");
port_names[OUTPUT_R] = strdup("Output R");
if ((port_range_hints =
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortRangeHint)))) == NULL)
exit(1);
stereo_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
port_range_hints[HORNFREQ].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[BASSFREQ].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[STWIDTH].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_LOW);
port_range_hints[HRBAL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MIDDLE);
port_range_hints[LATENCY].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MAXIMUM);
port_range_hints[HORNFREQ].LowerBound = 0;
port_range_hints[HORNFREQ].UpperBound = PM_FREQ;
port_range_hints[BASSFREQ].LowerBound = 0;
port_range_hints[BASSFREQ].UpperBound = PM_FREQ;
port_range_hints[STWIDTH].LowerBound = 0;
port_range_hints[STWIDTH].UpperBound = 100.0f;
port_range_hints[HRBAL].LowerBound = 0;
port_range_hints[HRBAL].UpperBound = 1.0f;
port_range_hints[LATENCY].LowerBound = 0;
port_range_hints[LATENCY].UpperBound = PM_DEPTH;
port_range_hints[INPUT_L].HintDescriptor = 0;
port_range_hints[INPUT_R].HintDescriptor = 0;
port_range_hints[OUTPUT_L].HintDescriptor = 0;
port_range_hints[OUTPUT_R].HintDescriptor = 0;
stereo_descriptor->instantiate = instantiate_RotSpkr;
stereo_descriptor->connect_port = connect_port_RotSpkr;
stereo_descriptor->activate = activate_RotSpkr;
stereo_descriptor->run = run_RotSpkr;
stereo_descriptor->run_adding = run_adding_RotSpkr;
stereo_descriptor->set_run_adding_gain = set_run_adding_gain_RotSpkr;
stereo_descriptor->deactivate = NULL;
stereo_descriptor->cleanup = cleanup_RotSpkr;
}
void
delete_descriptor(LADSPA_Descriptor * descriptor) {
unsigned long index;
if (descriptor) {
free((char *)descriptor->Label);
free((char *)descriptor->Name);
free((char *)descriptor->Maker);
free((char *)descriptor->Copyright);
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
for (index = 0; index < descriptor->PortCount; index++)
free((char *)(descriptor->PortNames[index]));
free((char **)descriptor->PortNames);
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
free(descriptor);
}
}
/* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
void
__attribute__((destructor)) tap_fini() {
delete_descriptor(stereo_descriptor);
}
/* Return a descriptor of the requested plugin type. */
const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index) {
switch (Index) {
case 0:
return stereo_descriptor;
default:
return NULL;
}
}

View File

@@ -1,338 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_sigmoid.c,v 1.3 2005/08/30 11:19:14 tszilagyi Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ladspa.h>
#include "tap_utils.h"
/* The Unique ID of the plugin: */
#define ID_MONO 2157
/* The port numbers for the plugin: */
#define PREGAIN 0
#define POSTGAIN 1
#define INPUT 2
#define OUTPUT 3
/* Total number of ports */
#define PORTCOUNT_MONO 4
/* The closer this is to 1.0, the slower the input parameter
interpolation will be. */
#define INTERP 0.99f
/* The structure used to hold port connection information and state */
typedef struct {
LADSPA_Data * pregain;
LADSPA_Data * postgain;
LADSPA_Data * input;
LADSPA_Data * output;
LADSPA_Data pregain_i;
LADSPA_Data postgain_i;
unsigned long sample_rate;
LADSPA_Data run_adding_gain;
} Sigmoid;
/* Construct a new plugin instance. */
LADSPA_Handle
instantiate_Sigmoid(const LADSPA_Descriptor * Descriptor,
unsigned long sample_rate) {
LADSPA_Handle * ptr;
if ((ptr = malloc(sizeof(Sigmoid))) != NULL) {
((Sigmoid *)ptr)->sample_rate = sample_rate;
((Sigmoid *)ptr)->run_adding_gain = 1.0f;
return ptr;
}
return NULL;
}
/* Connect a port to a data location. */
void
connect_port_Sigmoid(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * DataLocation) {
Sigmoid * ptr = (Sigmoid *)Instance;
switch (Port) {
case PREGAIN:
ptr->pregain = DataLocation;
ptr->pregain_i = db2lin(LIMIT(*DataLocation,-90.0f,20.0f));
break;
case POSTGAIN:
ptr->postgain = DataLocation;
ptr->postgain_i = db2lin(LIMIT(*DataLocation,-90.0f,20.0f));
break;
case INPUT:
ptr->input = DataLocation;
break;
case OUTPUT:
ptr->output = DataLocation;
break;
}
}
void
run_Sigmoid(LADSPA_Handle Instance,
unsigned long SampleCount) {
Sigmoid * ptr = (Sigmoid *)Instance;
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
LADSPA_Data pregain = db2lin(LIMIT(*(ptr->pregain),-90.0f,20.0f));
LADSPA_Data postgain = db2lin(LIMIT(*(ptr->postgain),-90.0f,20.0f));
LADSPA_Data pregain_i = ptr->pregain_i;
LADSPA_Data postgain_i = ptr->postgain_i;
unsigned long sample_index;
unsigned long sample_count = SampleCount;
LADSPA_Data in = 0.0f;
LADSPA_Data out = 0.0f;
if ((pregain_i != pregain) || (postgain_i != postgain)) {
for (sample_index = 0; sample_index < sample_count; sample_index++) {
pregain_i = pregain_i * INTERP + pregain * (1.0f - INTERP);
postgain_i = postgain_i * INTERP + postgain * (1.0f - INTERP);
in = *(input++) * pregain_i;
out = 2.0f / (1.0f + exp(-5.0*in)) - 1.0f;
*(output++) = out * postgain_i;
}
ptr->pregain_i = pregain_i;
ptr->postgain_i = postgain_i;
} else {
for (sample_index = 0; sample_index < sample_count; sample_index++) {
in = *(input++) * pregain_i;
out = 2.0f / (1.0f + exp(-5.0*in)) - 1.0f;
*(output++) = out * postgain_i;
}
ptr->pregain_i = pregain_i;
ptr->postgain_i = postgain_i;
}
}
void
set_run_adding_gain_Sigmoid(LADSPA_Handle Instance, LADSPA_Data gain) {
Sigmoid * ptr = (Sigmoid *)Instance;
ptr->run_adding_gain = gain;
}
void
run_adding_Sigmoid(LADSPA_Handle Instance,
unsigned long SampleCount) {
Sigmoid * ptr = (Sigmoid *)Instance;
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
LADSPA_Data pregain = db2lin(LIMIT(*(ptr->pregain),-90.0f,20.0f));
LADSPA_Data postgain = db2lin(LIMIT(*(ptr->postgain),-90.0f,20.0f));
LADSPA_Data pregain_i = ptr->pregain_i;
LADSPA_Data postgain_i = ptr->postgain_i;
unsigned long sample_index;
unsigned long sample_count = SampleCount;
LADSPA_Data in = 0.0f;
LADSPA_Data out = 0.0f;
if ((pregain_i != pregain) || (postgain_i != postgain)) {
for (sample_index = 0; sample_index < sample_count; sample_index++) {
pregain_i = pregain_i * INTERP + pregain * (1.0f - INTERP);
postgain_i = postgain_i * INTERP + postgain * (1.0f - INTERP);
in = *(input++) * pregain_i;
out = 2.0f / (1.0f + exp(-5.0*in)) - 1.0f;
*(output++) = out * postgain_i * ptr->run_adding_gain;
}
ptr->pregain_i = pregain_i;
ptr->postgain_i = postgain_i;
} else {
for (sample_index = 0; sample_index < sample_count; sample_index++) {
in = *(input++) * pregain_i;
out = 2.0f / (1.0f + exp(-5.0*in)) - 1.0f;
*(output++) = out * postgain_i * ptr->run_adding_gain;
}
}
}
/* Throw away a Sigmoid effect instance. */
void
cleanup_Sigmoid(LADSPA_Handle Instance) {
free(Instance);
}
LADSPA_Descriptor * mono_descriptor = NULL;
/* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
loaded. */
void
__attribute__((constructor)) tap_init() {
char ** port_names;
LADSPA_PortDescriptor * port_descriptors;
LADSPA_PortRangeHint * port_range_hints;
if ((mono_descriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
exit(1);
mono_descriptor->UniqueID = ID_MONO;
mono_descriptor->Label = strdup("tap_sigmoid");
mono_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
mono_descriptor->Name = strdup("TAP Sigmoid Booster");
mono_descriptor->Maker = strdup("Tom Szilagyi");
mono_descriptor->Copyright = strdup("GPL");
mono_descriptor->PortCount = PORTCOUNT_MONO;
if ((port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
exit(1);
mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
port_descriptors[PREGAIN] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[POSTGAIN] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
if ((port_names =
(char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
exit(1);
mono_descriptor->PortNames = (const char **)port_names;
port_names[PREGAIN] = strdup("Pre Gain [dB]");
port_names[POSTGAIN] = strdup("Post Gain [dB]");
port_names[INPUT] = strdup("Input");
port_names[OUTPUT] = strdup("Output");
if ((port_range_hints =
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
exit(1);
mono_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
port_range_hints[PREGAIN].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[POSTGAIN].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[PREGAIN].LowerBound = -90.0f;
port_range_hints[PREGAIN].UpperBound = 20.0f;
port_range_hints[POSTGAIN].LowerBound = -90.0f;
port_range_hints[POSTGAIN].UpperBound = 20.0f;
port_range_hints[INPUT].HintDescriptor = 0;
port_range_hints[OUTPUT].HintDescriptor = 0;
mono_descriptor->instantiate = instantiate_Sigmoid;
mono_descriptor->connect_port = connect_port_Sigmoid;
mono_descriptor->activate = NULL;
mono_descriptor->run = run_Sigmoid;
mono_descriptor->run_adding = run_adding_Sigmoid;
mono_descriptor->set_run_adding_gain = set_run_adding_gain_Sigmoid;
mono_descriptor->deactivate = NULL;
mono_descriptor->cleanup = cleanup_Sigmoid;
}
void
delete_descriptor(LADSPA_Descriptor * descriptor) {
unsigned long index;
if (descriptor) {
free((char *)descriptor->Label);
free((char *)descriptor->Name);
free((char *)descriptor->Maker);
free((char *)descriptor->Copyright);
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
for (index = 0; index < descriptor->PortCount; index++)
free((char *)(descriptor->PortNames[index]));
free((char **)descriptor->PortNames);
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
free(descriptor);
}
}
/* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
void
__attribute__((destructor)) tap_fini() {
delete_descriptor(mono_descriptor);
}
/* Return a descriptor of the requested plugin type. */
const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index) {
switch (Index) {
case 0:
return mono_descriptor;
default:
return NULL;
}
}

View File

@@ -1,343 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_tremolo.c,v 1.6 2004/02/21 17:33:36 tszilagyi Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ladspa.h>
#include "tap_utils.h"
/* The Unique ID of the plugin: */
#define ID_MONO 2144
/* The port numbers for the plugin: */
#define CONTROL_FREQ 0
#define CONTROL_DEPTH 1
#define CONTROL_GAIN 2
#define INPUT_0 3
#define OUTPUT_0 4
/* Total number of ports */
#define PORTCOUNT_MONO 5
/* cosine table for fast computations */
LADSPA_Data cos_table[1024];
/* The structure used to hold port connection information and state */
typedef struct {
LADSPA_Data * Control_Freq;
LADSPA_Data * Control_Depth;
LADSPA_Data * Control_Gain;
LADSPA_Data * InputBuffer_1;
LADSPA_Data * OutputBuffer_1;
unsigned long SampleRate;
LADSPA_Data Phase;
LADSPA_Data run_adding_gain;
} Tremolo;
/* Construct a new plugin instance. */
LADSPA_Handle
instantiate_Tremolo(const LADSPA_Descriptor * Descriptor,
unsigned long SampleRate) {
LADSPA_Handle * ptr;
if ((ptr = malloc(sizeof(Tremolo))) != NULL) {
((Tremolo *)ptr)->SampleRate = SampleRate;
((Tremolo *)ptr)->run_adding_gain = 1.0;
return ptr;
}
return NULL;
}
void
activate_Tremolo(LADSPA_Handle Instance) {
Tremolo * ptr;
ptr = (Tremolo *)Instance;
ptr->Phase = 0.0f;
}
/* Connect a port to a data location. */
void
connect_port_Tremolo(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * DataLocation) {
Tremolo * ptr;
ptr = (Tremolo *)Instance;
switch (Port) {
case CONTROL_FREQ:
ptr->Control_Freq = DataLocation;
break;
case CONTROL_DEPTH:
ptr->Control_Depth = DataLocation;
break;
case CONTROL_GAIN:
ptr->Control_Gain = DataLocation;
break;
case INPUT_0:
ptr->InputBuffer_1 = DataLocation;
break;
case OUTPUT_0:
ptr->OutputBuffer_1 = DataLocation;
break;
}
}
void
run_Tremolo(LADSPA_Handle Instance,
unsigned long SampleCount) {
LADSPA_Data * input;
LADSPA_Data * output;
LADSPA_Data freq;
LADSPA_Data depth;
LADSPA_Data gain;
Tremolo * ptr;
unsigned long sample_index;
LADSPA_Data phase = 0.0f;
ptr = (Tremolo *)Instance;
input = ptr->InputBuffer_1;
output = ptr->OutputBuffer_1;
freq = LIMIT(*(ptr->Control_Freq),0.0f,20.0f);
depth = LIMIT(*(ptr->Control_Depth),0.0f,100.0f);
gain = db2lin(LIMIT(*(ptr->Control_Gain),-70.0f,20.0f));
for (sample_index = 0; sample_index < SampleCount; sample_index++) {
phase = 1024.0f * freq * sample_index / ptr->SampleRate + ptr->Phase;
while (phase >= 1024.0f)
phase -= 1024.0f;
*(output++) = *(input++) * gain *
(1 - 0.5*depth/100 + 0.5 * depth/100 * cos_table[(unsigned long) phase]);
}
ptr->Phase = phase;
while (ptr->Phase >= 1024.0f)
ptr->Phase -= 1024.0f;
}
void
set_run_adding_gain_Tremolo(LADSPA_Handle Instance, LADSPA_Data gain) {
Tremolo * ptr;
ptr = (Tremolo *)Instance;
ptr->run_adding_gain = gain;
}
void
run_adding_Tremolo(LADSPA_Handle Instance,
unsigned long SampleCount) {
LADSPA_Data * input;
LADSPA_Data * output;
LADSPA_Data freq;
LADSPA_Data depth;
LADSPA_Data gain;
Tremolo * ptr;
unsigned long sample_index;
LADSPA_Data phase = 0.0f;
ptr = (Tremolo *)Instance;
input = ptr->InputBuffer_1;
output = ptr->OutputBuffer_1;
freq = LIMIT(*(ptr->Control_Freq),0.0f,20.0f);
depth = LIMIT(*(ptr->Control_Depth),0.0f,100.0f);
gain = db2lin(LIMIT(*(ptr->Control_Gain),-70.0f,20.0f));
for (sample_index = 0; sample_index < SampleCount; sample_index++) {
phase = 1024.0f * freq * sample_index / ptr->SampleRate + ptr->Phase;
while (phase >= 1024.0f)
phase -= 1024.0f;
*(output++) += *(input++) * ptr->run_adding_gain * gain *
(1 - 0.5*depth/100 + 0.5 * depth/100 * cos_table[(unsigned long) phase]);
}
ptr->Phase = phase;
while (ptr->Phase >= 1024.0f)
ptr->Phase -= 1024.0f;
}
/* Throw away a Tremolo effect instance. */
void
cleanup_Tremolo(LADSPA_Handle Instance) {
free(Instance);
}
LADSPA_Descriptor * mono_descriptor = NULL;
/* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
loaded. */
void
__attribute__((constructor)) tap_init() {
char ** port_names;
LADSPA_PortDescriptor * port_descriptors;
LADSPA_PortRangeHint * port_range_hints;
int i;
if ((mono_descriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
exit(1);
for (i = 0; i < 1024; i++)
cos_table[i] = cosf(i * M_PI / 512.0f);
mono_descriptor->UniqueID = ID_MONO;
mono_descriptor->Label = strdup("tap_tremolo");
mono_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
mono_descriptor->Name = strdup("TAP Tremolo");
mono_descriptor->Maker = strdup("Tom Szilagyi");
mono_descriptor->Copyright = strdup("GPL");
mono_descriptor->PortCount = PORTCOUNT_MONO;
if ((port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
exit(1);
mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
port_descriptors[CONTROL_FREQ] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[CONTROL_DEPTH] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[CONTROL_GAIN] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[INPUT_0] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT_0] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
if ((port_names =
(char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
exit(1);
mono_descriptor->PortNames = (const char **)port_names;
port_names[CONTROL_FREQ] = strdup("Frequency [Hz]");
port_names[CONTROL_DEPTH] = strdup("Depth [%]");
port_names[CONTROL_GAIN] = strdup("Gain [dB]");
port_names[INPUT_0] = strdup("Input_0");
port_names[OUTPUT_0] = strdup("Output_0");
if ((port_range_hints =
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
exit(1);
mono_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
port_range_hints[CONTROL_FREQ].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[CONTROL_DEPTH].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[CONTROL_GAIN].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[CONTROL_FREQ].LowerBound = 0;
port_range_hints[CONTROL_FREQ].UpperBound = 20;
port_range_hints[CONTROL_DEPTH].LowerBound = 0;
port_range_hints[CONTROL_DEPTH].UpperBound = 100;
port_range_hints[CONTROL_GAIN].LowerBound = -70;
port_range_hints[CONTROL_GAIN].UpperBound = 20;
port_range_hints[INPUT_0].HintDescriptor = 0;
port_range_hints[OUTPUT_0].HintDescriptor = 0;
mono_descriptor->instantiate = instantiate_Tremolo;
mono_descriptor->connect_port = connect_port_Tremolo;
mono_descriptor->activate = activate_Tremolo;
mono_descriptor->run = run_Tremolo;
mono_descriptor->run_adding = run_adding_Tremolo;
mono_descriptor->set_run_adding_gain = set_run_adding_gain_Tremolo;
mono_descriptor->deactivate = NULL;
mono_descriptor->cleanup = cleanup_Tremolo;
}
void
delete_descriptor(LADSPA_Descriptor * descriptor) {
unsigned long index;
if (descriptor) {
free((char *)descriptor->Label);
free((char *)descriptor->Name);
free((char *)descriptor->Maker);
free((char *)descriptor->Copyright);
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
for (index = 0; index < descriptor->PortCount; index++)
free((char *)(descriptor->PortNames[index]));
free((char **)descriptor->PortNames);
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
free(descriptor);
}
}
/* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
void
__attribute__((destructor)) tap_fini() {
delete_descriptor(mono_descriptor);
}
/* Return a descriptor of the requested plugin type. */
const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index) {
switch (Index) {
case 0:
return mono_descriptor;
default:
return NULL;
}
}

View File

@@ -1,491 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_tubewarmth.c,v 1.1 2004/08/02 18:14:50 tszilagyi Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ladspa.h>
#include "tap_utils.h"
/* The Unique ID of the plugin: */
#define ID_MONO 2158
/* The port numbers for the plugin: */
#define DRIVE 0
#define BLEND 1
#define INPUT 2
#define OUTPUT 3
/* Total number of ports */
#define PORTCOUNT_MONO 4
/* The structure used to hold port connection information and state */
typedef struct {
LADSPA_Data * drive;
LADSPA_Data * blend;
LADSPA_Data * input;
LADSPA_Data * output;
LADSPA_Data prev_med;
LADSPA_Data prev_out;
LADSPA_Data rdrive;
LADSPA_Data rbdr;
LADSPA_Data kpa;
LADSPA_Data kpb;
LADSPA_Data kna;
LADSPA_Data knb;
LADSPA_Data ap;
LADSPA_Data an;
LADSPA_Data imr;
LADSPA_Data kc;
LADSPA_Data srct;
LADSPA_Data sq;
LADSPA_Data pwrq;
LADSPA_Data prev_drive;
LADSPA_Data prev_blend;
unsigned long sample_rate;
LADSPA_Data run_adding_gain;
} TubeWarmth;
/* Construct a new plugin instance. */
LADSPA_Handle
instantiate_TubeWarmth(const LADSPA_Descriptor * Descriptor,
unsigned long sample_rate) {
LADSPA_Handle * ptr;
if ((ptr = malloc(sizeof(TubeWarmth))) != NULL) {
((TubeWarmth *)ptr)->sample_rate = sample_rate;
((TubeWarmth *)ptr)->run_adding_gain = 1.0f;
((TubeWarmth *)ptr)->prev_med = 0.0f;
((TubeWarmth *)ptr)->prev_out = 0.0f;
((TubeWarmth *)ptr)->rdrive = 0.0f;
((TubeWarmth *)ptr)->rbdr = 0.0f;
((TubeWarmth *)ptr)->kpa = 0.0f;
((TubeWarmth *)ptr)->kpb = 0.0f;
((TubeWarmth *)ptr)->kna = 0.0f;
((TubeWarmth *)ptr)->knb = 0.0f;
((TubeWarmth *)ptr)->ap = 0.0f;
((TubeWarmth *)ptr)->an = 0.0f;
((TubeWarmth *)ptr)->imr = 0.0f;
((TubeWarmth *)ptr)->kc = 0.0f;
((TubeWarmth *)ptr)->srct = 0.0f;
((TubeWarmth *)ptr)->sq = 0.0f;
((TubeWarmth *)ptr)->pwrq = 0.0f;
/* These are out of band to force param recalc upon first run() */
((TubeWarmth *)ptr)->prev_drive = -1.0f;
((TubeWarmth *)ptr)->prev_blend = -11.0f;
return ptr;
}
return NULL;
}
/* Connect a port to a data location. */
void
connect_port_TubeWarmth(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * DataLocation) {
TubeWarmth * ptr = (TubeWarmth *)Instance;
switch (Port) {
case DRIVE:
ptr->drive = DataLocation;
break;
case BLEND:
ptr->blend = DataLocation;
break;
case INPUT:
ptr->input = DataLocation;
break;
case OUTPUT:
ptr->output = DataLocation;
break;
}
}
#define EPS 0.000000001f
static inline float
M(float x) {
if ((x > EPS) || (x < -EPS))
return x;
else
return 0.0f;
}
static inline float
D(float x) {
if (x > EPS)
return sqrt(x);
else if (x < -EPS)
return sqrt(-x);
else
return 0.0f;
}
void
run_TubeWarmth(LADSPA_Handle Instance,
unsigned long SampleCount) {
TubeWarmth * ptr = (TubeWarmth *)Instance;
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
LADSPA_Data drive = LIMIT(*(ptr->drive),0.1f,10.0f);
LADSPA_Data blend = LIMIT(*(ptr->blend),-10.0f,10.0f);
unsigned long sample_index;
unsigned long sample_count = SampleCount;
unsigned long sample_rate = ptr->sample_rate;
LADSPA_Data rdrive = ptr->rdrive;
LADSPA_Data rbdr = ptr->rbdr;
LADSPA_Data kpa = ptr->kpa;
LADSPA_Data kpb = ptr->kpb;
LADSPA_Data kna = ptr->kna;
LADSPA_Data knb = ptr->knb;
LADSPA_Data ap = ptr->ap;
LADSPA_Data an = ptr->an;
LADSPA_Data imr = ptr->imr;
LADSPA_Data kc = ptr->kc;
LADSPA_Data srct = ptr->srct;
LADSPA_Data sq = ptr->sq;
LADSPA_Data pwrq = ptr->pwrq;
LADSPA_Data prev_med;
LADSPA_Data prev_out;
LADSPA_Data in;
LADSPA_Data med;
LADSPA_Data out;
if ((ptr->prev_drive != drive) || (ptr->prev_blend != blend)) {
rdrive = 12.0f / drive;
rbdr = rdrive / (10.5f - blend) * 780.0f / 33.0f;
kpa = D(2.0f * (rdrive*rdrive) - 1.0f) + 1.0f;
kpb = (2.0f - kpa) / 2.0f;
ap = ((rdrive*rdrive) - kpa + 1.0f) / 2.0f;
kc = kpa / D(2.0f * D(2.0f * (rdrive*rdrive) - 1.0f) - 2.0f * rdrive*rdrive);
srct = (0.1f * sample_rate) / (0.1f * sample_rate + 1.0f);
sq = kc*kc + 1.0f;
knb = -1.0f * rbdr / D(sq);
kna = 2.0f * kc * rbdr / D(sq);
an = rbdr*rbdr / sq;
imr = 2.0f * knb + D(2.0f * kna + 4.0f * an - 1.0f);
pwrq = 2.0f / (imr + 1.0f);
ptr->prev_drive = drive;
ptr->prev_blend = blend;
}
for (sample_index = 0; sample_index < sample_count; sample_index++) {
in = *(input++);
prev_med = ptr->prev_med;
prev_out = ptr->prev_out;
if (in >= 0.0f) {
med = (D(ap + in * (kpa - in)) + kpb) * pwrq;
} else {
med = (D(an - in * (kna + in)) + knb) * pwrq * -1.0f;
}
out = srct * (med - prev_med + prev_out);
if (out < -1.0f)
out = -1.0f;
*(output++) = out;
ptr->prev_med = M(med);
ptr->prev_out = M(out);
}
ptr->rdrive = rdrive;
ptr->rbdr = rbdr;
ptr->kpa = kpa;
ptr->kpb = kpb;
ptr->kna = kna;
ptr->knb = knb;
ptr->ap = ap;
ptr->an = an;
ptr->imr = imr;
ptr->kc = kc;
ptr->srct = srct;
ptr->sq = sq;
ptr->pwrq = pwrq;
}
void
set_run_adding_gain_TubeWarmth(LADSPA_Handle Instance, LADSPA_Data gain) {
TubeWarmth * ptr = (TubeWarmth *)Instance;
ptr->run_adding_gain = gain;
}
void
run_adding_TubeWarmth(LADSPA_Handle Instance,
unsigned long SampleCount) {
TubeWarmth * ptr = (TubeWarmth *)Instance;
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
LADSPA_Data drive = LIMIT(*(ptr->drive),0.1f,10.0f);
LADSPA_Data blend = LIMIT(*(ptr->blend),-10.0f,10.0f);
unsigned long sample_index;
unsigned long sample_count = SampleCount;
unsigned long sample_rate = ptr->sample_rate;
LADSPA_Data rdrive = ptr->rdrive;
LADSPA_Data rbdr = ptr->rbdr;
LADSPA_Data kpa = ptr->kpa;
LADSPA_Data kpb = ptr->kpb;
LADSPA_Data kna = ptr->kna;
LADSPA_Data knb = ptr->knb;
LADSPA_Data ap = ptr->ap;
LADSPA_Data an = ptr->an;
LADSPA_Data imr = ptr->imr;
LADSPA_Data kc = ptr->kc;
LADSPA_Data srct = ptr->srct;
LADSPA_Data sq = ptr->sq;
LADSPA_Data pwrq = ptr->pwrq;
LADSPA_Data prev_med;
LADSPA_Data prev_out;
LADSPA_Data in;
LADSPA_Data med;
LADSPA_Data out;
if ((ptr->prev_drive != drive) || (ptr->prev_blend != blend)) {
rdrive = 12.0f / drive;
rbdr = rdrive / (10.5f - blend) * 780.0f / 33.0f;
kpa = D(2.0f * (rdrive*rdrive) - 1.0f) + 1.0f;
kpb = (2.0f - kpa) / 2.0f;
ap = ((rdrive*rdrive) - kpa + 1.0f) / 2.0f;
kc = kpa / D(2.0f * D(2.0f * (rdrive*rdrive) - 1.0f) - 2.0f * rdrive*rdrive);
srct = (0.1f * sample_rate) / (0.1f * sample_rate + 1.0f);
sq = kc*kc + 1.0f;
knb = -1.0f * rbdr / D(sq);
kna = 2.0f * kc * rbdr / D(sq);
an = rbdr*rbdr / sq;
imr = 2.0f * knb + D(2.0f * kna + 4.0f * an - 1.0f);
pwrq = 2.0f / (imr + 1.0f);
ptr->prev_drive = drive;
ptr->prev_blend = blend;
}
for (sample_index = 0; sample_index < sample_count; sample_index++) {
in = *(input++);
prev_med = ptr->prev_med;
prev_out = ptr->prev_out;
if (in >= 0.0f) {
med = (D(ap + in * (kpa - in)) + kpb) * pwrq;
} else {
med = (D(an - in * (kna + in)) + knb) * pwrq * -1.0f;
}
out = srct * (med - prev_med + prev_out);
if (out < -1.0f)
out = -1.0f;
*(output++) += out * ptr->run_adding_gain;
ptr->prev_med = M(med);
ptr->prev_out = M(out);
}
ptr->rdrive = rdrive;
ptr->rbdr = rbdr;
ptr->kpa = kpa;
ptr->kpb = kpb;
ptr->kna = kna;
ptr->knb = knb;
ptr->ap = ap;
ptr->an = an;
ptr->imr = imr;
ptr->kc = kc;
ptr->srct = srct;
ptr->sq = sq;
ptr->pwrq = pwrq;
}
/* Throw away a TubeWarmth effect instance. */
void
cleanup_TubeWarmth(LADSPA_Handle Instance) {
free(Instance);
}
LADSPA_Descriptor * mono_descriptor = NULL;
/* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
loaded. */
void
__attribute__((constructor)) tap_init() {
char ** port_names;
LADSPA_PortDescriptor * port_descriptors;
LADSPA_PortRangeHint * port_range_hints;
if ((mono_descriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
exit(1);
mono_descriptor->UniqueID = ID_MONO;
mono_descriptor->Label = strdup("tap_tubewarmth");
mono_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
mono_descriptor->Name = strdup("TAP TubeWarmth");
mono_descriptor->Maker = strdup("Tom Szilagyi");
mono_descriptor->Copyright = strdup("GPL");
mono_descriptor->PortCount = PORTCOUNT_MONO;
if ((port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
exit(1);
mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
port_descriptors[DRIVE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[BLEND] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
if ((port_names =
(char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
exit(1);
mono_descriptor->PortNames = (const char **)port_names;
port_names[DRIVE] = strdup("Drive");
port_names[BLEND] = strdup("Tape--Tube Blend");
port_names[INPUT] = strdup("Input");
port_names[OUTPUT] = strdup("Output");
if ((port_range_hints =
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
exit(1);
mono_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
port_range_hints[DRIVE].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_LOW);
port_range_hints[BLEND].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MAXIMUM);
port_range_hints[DRIVE].LowerBound = 0.1f;
port_range_hints[DRIVE].UpperBound = 10.0f;
port_range_hints[BLEND].LowerBound = -10.0f;
port_range_hints[BLEND].UpperBound = 10.0f;
port_range_hints[INPUT].HintDescriptor = 0;
port_range_hints[OUTPUT].HintDescriptor = 0;
mono_descriptor->instantiate = instantiate_TubeWarmth;
mono_descriptor->connect_port = connect_port_TubeWarmth;
mono_descriptor->activate = NULL;
mono_descriptor->run = run_TubeWarmth;
mono_descriptor->run_adding = run_adding_TubeWarmth;
mono_descriptor->set_run_adding_gain = set_run_adding_gain_TubeWarmth;
mono_descriptor->deactivate = NULL;
mono_descriptor->cleanup = cleanup_TubeWarmth;
}
void
delete_descriptor(LADSPA_Descriptor * descriptor) {
unsigned long index;
if (descriptor) {
free((char *)descriptor->Label);
free((char *)descriptor->Name);
free((char *)descriptor->Maker);
free((char *)descriptor->Copyright);
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
for (index = 0; index < descriptor->PortCount; index++)
free((char *)(descriptor->PortNames[index]));
free((char **)descriptor->PortNames);
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
free(descriptor);
}
}
/* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
void
__attribute__((destructor)) tap_fini() {
delete_descriptor(mono_descriptor);
}
/* Return a descriptor of the requested plugin type. */
const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index) {
switch (Index) {
case 0:
return mono_descriptor;
default:
return NULL;
}
}

View File

@@ -1,267 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_utils.h,v 1.5 2004/02/21 17:33:36 tszilagyi Exp $
*/
#ifndef _ISOC99_SOURCE
#define _ISOC99_SOURCE
#endif
#include <stdint.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846264338327
#endif
/* push a sample into a ringbuffer and return the sample falling out */
static inline
LADSPA_Data
push_buffer(LADSPA_Data insample, LADSPA_Data * buffer,
unsigned long buflen, unsigned long * pos) {
LADSPA_Data outsample;
outsample = buffer[*pos];
buffer[(*pos)++] = insample;
if (*pos >= buflen)
*pos = 0;
return outsample;
}
/* read a value from a ringbuffer.
* n == 0 returns the oldest sample from the buffer.
* n == buflen-1 returns the sample written to the buffer
* at the last push_buffer call.
* n must not exceed buflen-1, or your computer will explode.
*/
static inline
LADSPA_Data
read_buffer(LADSPA_Data * buffer, unsigned long buflen,
unsigned long pos, unsigned long n) {
while (n + pos >= buflen)
n -= buflen;
return buffer[n + pos];
}
/* overwrites a value in a ringbuffer, but pos stays the same.
* n == 0 overwrites the oldest sample pushed in the buffer.
* n == buflen-1 overwrites the sample written to the buffer
* at the last push_buffer call.
* n must not exceed buflen-1, or your computer... you know.
*/
static inline
void
write_buffer(LADSPA_Data insample, LADSPA_Data * buffer, unsigned long buflen,
unsigned long pos, unsigned long n) {
while (n + pos >= buflen)
n -= buflen;
buffer[n + pos] = insample;
}
/* Please note that the majority of the definitions and helper
functions below have been derived from the source code of Steve
Harris's SWH plugins (particularly from the "biquad.h" file). While I
give him credit for his excellent work, I reserve myself to be blamed
for any bugs or malfunction. */
#define db2lin(x) ((x) > -90.0f ? powf(10.0f, (x) * 0.05f) : 0.0f)
#define ABS(x) (x)>0.0f?(x):-1.0f*(x)
#define LN_2_2 0.34657359f
#define LIMIT(v,l,u) ((v)<(l)?(l):((v)>(u)?(u):(v)))
#define BIQUAD_TYPE float
typedef BIQUAD_TYPE bq_t;
/* Biquad filter (adapted from lisp code by Eli Brandt,
http://www.cs.cmu.edu/~eli/) */
/* The prev. comment has been preserved from Steve Harris's biquad.h */
typedef struct {
bq_t a1;
bq_t a2;
bq_t b0;
bq_t b1;
bq_t b2;
bq_t x1;
bq_t x2;
bq_t y1;
bq_t y2;
} biquad;
static inline void biquad_init(biquad *f) {
f->x1 = 0.0f;
f->x2 = 0.0f;
f->y1 = 0.0f;
f->y2 = 0.0f;
}
static inline
void
eq_set_params(biquad *f, bq_t fc, bq_t gain, bq_t bw, bq_t fs) {
bq_t w = 2.0f * M_PI * LIMIT(fc, 1.0f, fs/2.0f) / fs;
bq_t cw = cosf(w);
bq_t sw = sinf(w);
bq_t J = pow(10.0f, gain * 0.025f);
bq_t g = sw * sinhf(LN_2_2 * LIMIT(bw, 0.0001f, 4.0f) * w / sw);
bq_t a0r = 1.0f / (1.0f + (g / J));
f->b0 = (1.0f + (g * J)) * a0r;
f->b1 = (-2.0f * cw) * a0r;
f->b2 = (1.0f - (g * J)) * a0r;
f->a1 = -(f->b1);
f->a2 = ((g / J) - 1.0f) * a0r;
}
static inline void lp_set_params(biquad *f, bq_t fc, bq_t bw, bq_t fs) {
bq_t omega = 2.0 * M_PI * fc/fs;
bq_t sn = sin(omega);
bq_t cs = cos(omega);
bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
const float a0r = 1.0 / (1.0 + alpha);
#if 0
b0 = (1 - cs) /2;
b1 = 1 - cs;
b2 = (1 - cs) /2;
a0 = 1 + alpha;
a1 = -2 * cs;
a2 = 1 - alpha;
#endif
f->b0 = a0r * (1.0 - cs) * 0.5;
f->b1 = a0r * (1.0 - cs);
f->b2 = a0r * (1.0 - cs) * 0.5;
f->a1 = a0r * (2.0 * cs);
f->a2 = a0r * (alpha - 1.0);
}
static inline
void
hp_set_params(biquad *f, bq_t fc, bq_t bw, bq_t fs)
{
bq_t omega = 2.0 * M_PI * fc/fs;
bq_t sn = sin(omega);
bq_t cs = cos(omega);
bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
const float a0r = 1.0 / (1.0 + alpha);
#if 0
b0 = (1 + cs) /2;
b1 = -(1 + cs);
b2 = (1 + cs) /2;
a0 = 1 + alpha;
a1 = -2 * cs;
a2 = 1 - alpha;
#endif
f->b0 = a0r * (1.0 + cs) * 0.5;
f->b1 = a0r * -(1.0 + cs);
f->b2 = a0r * (1.0 + cs) * 0.5;
f->a1 = a0r * (2.0 * cs);
f->a2 = a0r * (alpha - 1.0);
}
static inline
void
ls_set_params(biquad *f, bq_t fc, bq_t gain, bq_t slope, bq_t fs)
{
bq_t w = 2.0f * M_PI * LIMIT(fc, 1.0, fs/2.0) / fs;
bq_t cw = cosf(w);
bq_t sw = sinf(w);
bq_t A = powf(10.0f, gain * 0.025f);
bq_t b = sqrt(((1.0f + A * A) / LIMIT(slope, 0.0001f, 1.0f)) - ((A -
1.0f) * (A - 1.0)));
bq_t apc = cw * (A + 1.0f);
bq_t amc = cw * (A - 1.0f);
bq_t bs = b * sw;
bq_t a0r = 1.0f / (A + 1.0f + amc + bs);
f->b0 = a0r * A * (A + 1.0f - amc + bs);
f->b1 = a0r * 2.0f * A * (A - 1.0f - apc);
f->b2 = a0r * A * (A + 1.0f - amc - bs);
f->a1 = a0r * 2.0f * (A - 1.0f + apc);
f->a2 = a0r * (-A - 1.0f - amc + bs);
}
static inline
void
hs_set_params(biquad *f, bq_t fc, bq_t gain, bq_t slope, bq_t fs) {
bq_t w = 2.0f * M_PI * LIMIT(fc, 1.0, fs/2.0) / fs;
bq_t cw = cosf(w);
bq_t sw = sinf(w);
bq_t A = powf(10.0f, gain * 0.025f);
bq_t b = sqrt(((1.0f + A * A) / LIMIT(slope, 0.0001f, 1.0f)) - ((A -
1.0f) * (A - 1.0f)));
bq_t apc = cw * (A + 1.0f);
bq_t amc = cw * (A - 1.0f);
bq_t bs = b * sw;
bq_t a0r = 1.0f / (A + 1.0f - amc + bs);
f->b0 = a0r * A * (A + 1.0f + amc + bs);
f->b1 = a0r * -2.0f * A * (A - 1.0f + apc);
f->b2 = a0r * A * (A + 1.0f + amc - bs);
f->a1 = a0r * -2.0f * (A - 1.0f - apc);
f->a2 = a0r * (-A - 1.0f + amc + bs);
}
static inline
bq_t
biquad_run(biquad *f, bq_t x) {
union {
bq_t y;
uint32_t y_int;
} u;
u.y = f->b0 * x + f->b1 * f->x1 + f->b2 * f->x2
+ f->a1 * f->y1 + f->a2 * f->y2;
if ((u.y_int & 0x7f800000) == 0)
u.y = 0.0f;
f->x2 = f->x1;
f->x1 = x;
f->y2 = f->y1;
f->y1 = u.y;
return u.y;
}

View File

@@ -1,445 +0,0 @@
/* -*- linux-c -*-
Copyright (C) 2004 Tom Szilagyi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tap_vibrato.c,v 1.3 2004/02/21 17:33:36 tszilagyi Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ladspa.h>
#include "tap_utils.h"
/* The Unique ID of the plugin: */
#define ID_MONO 2148
/* The port numbers for the plugin: */
#define FREQ 0
#define DEPTH 1
#define DRYLEVEL 2
#define WETLEVEL 3
#define LATENCY 4
#define INPUT 5
#define OUTPUT 6
/* Total number of ports */
#define PORTCOUNT_MONO 7
/*
* This has to be bigger than 0.2f * sample_rate / (2*PI) for any sample rate.
* At 192 kHz 6238 is needed so this should be enough.
*/
#define PM_DEPTH 6300
#define PM_FREQ 30.0f
#define COS_TABLE_SIZE 1024
LADSPA_Data cos_table[COS_TABLE_SIZE];
/* The structure used to hold port connection information and state */
typedef struct {
LADSPA_Data * depth;
LADSPA_Data * freq;
LADSPA_Data * drylevel;
LADSPA_Data * wetlevel;
LADSPA_Data * latency;
LADSPA_Data * input;
LADSPA_Data * output;
LADSPA_Data * ringbuffer;
unsigned long buflen;
unsigned long pos;
LADSPA_Data phase;
unsigned long sample_rate;
LADSPA_Data run_adding_gain;
} Vibrato;
/* Construct a new plugin instance. */
LADSPA_Handle
instantiate_Vibrato(const LADSPA_Descriptor * Descriptor,
unsigned long sample_rate) {
LADSPA_Handle * ptr;
if ((ptr = malloc(sizeof(Vibrato))) != NULL) {
((Vibrato *)ptr)->sample_rate = sample_rate;
((Vibrato *)ptr)->run_adding_gain = 1.0f;
if ((((Vibrato *)ptr)->ringbuffer =
calloc(2 * PM_DEPTH, sizeof(LADSPA_Data))) == NULL)
{
free(ptr);
return NULL;
}
((Vibrato *)ptr)->buflen = ceil(0.2f * sample_rate / M_PI);
((Vibrato *)ptr)->pos = 0;
return ptr;
}
return NULL;
}
void
activate_Vibrato(LADSPA_Handle Instance) {
Vibrato * ptr = (Vibrato *)Instance;
unsigned long i;
for (i = 0; i < 2 * PM_DEPTH; i++)
ptr->ringbuffer[i] = 0.0f;
ptr->phase = 0.0f;
}
/* Connect a port to a data location. */
void
connect_port_Vibrato(LADSPA_Handle Instance,
unsigned long Port,
LADSPA_Data * DataLocation) {
Vibrato * ptr = (Vibrato *)Instance;
switch (Port) {
case DEPTH:
ptr->depth = DataLocation;
break;
case FREQ:
ptr->freq = DataLocation;
break;
case DRYLEVEL:
ptr->drylevel = DataLocation;
break;
case WETLEVEL:
ptr->wetlevel = DataLocation;
break;
case LATENCY:
ptr->latency = DataLocation;
*(ptr->latency) = ptr->buflen / 2; /* IS THIS LEGAL? */
break;
case INPUT:
ptr->input = DataLocation;
break;
case OUTPUT:
ptr->output = DataLocation;
break;
}
}
void
run_Vibrato(LADSPA_Handle Instance,
unsigned long SampleCount) {
Vibrato * ptr = (Vibrato *)Instance;
LADSPA_Data freq = LIMIT(*(ptr->freq),0.0f,PM_FREQ);
LADSPA_Data depth =
LIMIT(LIMIT(*(ptr->depth),0.0f,20.0f) * ptr->sample_rate / 200.0f / M_PI / freq,
0, ptr->buflen / 2);
LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
LADSPA_Data wetlevel = db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
unsigned long sample_index;
unsigned long sample_count = SampleCount;
LADSPA_Data in = 0.0f;
LADSPA_Data phase = 0.0f;
LADSPA_Data fpos = 0.0f;
LADSPA_Data n = 0.0f;
LADSPA_Data rem = 0.0f;
LADSPA_Data s_a, s_b;
if (freq == 0.0f)
depth = 0.0f;
for (sample_index = 0; sample_index < sample_count; sample_index++) {
in = *(input++);
phase = COS_TABLE_SIZE * freq * sample_index / ptr->sample_rate + ptr->phase;
while (phase >= COS_TABLE_SIZE)
phase -= COS_TABLE_SIZE;
push_buffer(in, ptr->ringbuffer, ptr->buflen, &(ptr->pos));
fpos = depth * (1.0f - cos_table[(unsigned long) phase]);
n = floorf(fpos);
rem = fpos - n;
s_a = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n);
s_b = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n + 1);
*(output++) = wetlevel * ((1 - rem) * s_a + rem * s_b) +
drylevel * read_buffer(ptr->ringbuffer, ptr->buflen,
ptr->pos, ptr->buflen / 2);
}
ptr->phase += COS_TABLE_SIZE * freq * sample_index / ptr->sample_rate;
while (ptr->phase >= COS_TABLE_SIZE)
ptr->phase -= COS_TABLE_SIZE;
*(ptr->latency) = ptr->buflen / 2;
}
void
set_run_adding_gain_Vibrato(LADSPA_Handle Instance, LADSPA_Data gain) {
Vibrato * ptr = (Vibrato *)Instance;
ptr->run_adding_gain = gain;
}
void
run_adding_Vibrato(LADSPA_Handle Instance,
unsigned long SampleCount) {
Vibrato * ptr = (Vibrato *)Instance;
LADSPA_Data freq = LIMIT(*(ptr->freq),0.0f,PM_FREQ);
LADSPA_Data depth =
LIMIT(LIMIT(*(ptr->depth),0.0f,20.0f) * ptr->sample_rate / 200.0f / M_PI / freq,
0, ptr->buflen / 2);
LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
LADSPA_Data wetlevel = db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
LADSPA_Data * input = ptr->input;
LADSPA_Data * output = ptr->output;
unsigned long sample_index;
unsigned long sample_count = SampleCount;
LADSPA_Data in = 0.0f;
LADSPA_Data phase = 0.0f;
LADSPA_Data fpos = 0.0f;
LADSPA_Data n = 0.0f;
LADSPA_Data rem = 0.0f;
LADSPA_Data s_a, s_b;
if (freq == 0.0f)
depth = 0.0f;
for (sample_index = 0; sample_index < sample_count; sample_index++) {
in = *(input++);
phase = COS_TABLE_SIZE * freq * sample_index / ptr->sample_rate + ptr->phase;
while (phase >= COS_TABLE_SIZE)
phase -= COS_TABLE_SIZE;
push_buffer(in, ptr->ringbuffer, ptr->buflen, &(ptr->pos));
fpos = depth * (1.0f - cos_table[(unsigned long) phase]);
n = floorf(fpos);
rem = fpos - n;
s_a = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n);
s_b = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n + 1);
*(output++) += ptr->run_adding_gain * wetlevel * ((1 - rem) * s_a + rem * s_b) +
drylevel * read_buffer(ptr->ringbuffer, ptr->buflen,
ptr->pos, ptr->buflen / 2);
}
ptr->phase += COS_TABLE_SIZE * freq * sample_index / ptr->sample_rate;
while (ptr->phase >= COS_TABLE_SIZE)
ptr->phase -= COS_TABLE_SIZE;
*(ptr->latency) = ptr->buflen / 2;
}
/* Throw away a Vibrato effect instance. */
void
cleanup_Vibrato(LADSPA_Handle Instance) {
Vibrato * ptr = (Vibrato *)Instance;
free(ptr->ringbuffer);
free(Instance);
}
LADSPA_Descriptor * mono_descriptor = NULL;
/* __attribute__((constructor)) tap_init() is called automatically when the plugin library is first
loaded. */
void
__attribute__((constructor)) tap_init() {
int i;
char ** port_names;
LADSPA_PortDescriptor * port_descriptors;
LADSPA_PortRangeHint * port_range_hints;
if ((mono_descriptor =
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
exit(1);
for (i = 0; i < COS_TABLE_SIZE; i++)
cos_table[i] = cosf(i * 2.0f * M_PI / COS_TABLE_SIZE);
mono_descriptor->UniqueID = ID_MONO;
mono_descriptor->Label = strdup("tap_vibrato");
mono_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
mono_descriptor->Name = strdup("TAP Vibrato");
mono_descriptor->Maker = strdup("Tom Szilagyi");
mono_descriptor->Copyright = strdup("GPL");
mono_descriptor->PortCount = PORTCOUNT_MONO;
if ((port_descriptors =
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
exit(1);
mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
port_descriptors[DEPTH] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[FREQ] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[DRYLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[WETLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
port_descriptors[LATENCY] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
port_descriptors[INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
port_descriptors[OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
if ((port_names =
(char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
exit(1);
mono_descriptor->PortNames = (const char **)port_names;
port_names[FREQ] = strdup("Frequency [Hz]");
port_names[DEPTH] = strdup("Depth [%]");
port_names[DRYLEVEL] = strdup("Dry Level [dB]");
port_names[WETLEVEL] = strdup("Wet Level [dB]");
port_names[LATENCY] = strdup("latency");
port_names[INPUT] = strdup("Input");
port_names[OUTPUT] = strdup("Output");
if ((port_range_hints =
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
exit(1);
mono_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
port_range_hints[DEPTH].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[FREQ].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[DRYLEVEL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MINIMUM);
port_range_hints[WETLEVEL].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_0);
port_range_hints[LATENCY].HintDescriptor =
(LADSPA_HINT_BOUNDED_BELOW |
LADSPA_HINT_BOUNDED_ABOVE |
LADSPA_HINT_DEFAULT_MAXIMUM);
port_range_hints[DEPTH].LowerBound = 0;
port_range_hints[DEPTH].UpperBound = 20.0f;
port_range_hints[FREQ].LowerBound = 0;
port_range_hints[FREQ].UpperBound = PM_FREQ;
port_range_hints[DRYLEVEL].LowerBound = -90.0f;
port_range_hints[DRYLEVEL].UpperBound = +20.0f;
port_range_hints[WETLEVEL].LowerBound = -90.0f;
port_range_hints[WETLEVEL].UpperBound = +20.0f;
port_range_hints[LATENCY].LowerBound = 0;
port_range_hints[LATENCY].UpperBound = PM_DEPTH;
port_range_hints[INPUT].HintDescriptor = 0;
port_range_hints[OUTPUT].HintDescriptor = 0;
mono_descriptor->instantiate = instantiate_Vibrato;
mono_descriptor->connect_port = connect_port_Vibrato;
mono_descriptor->activate = activate_Vibrato;
mono_descriptor->run = run_Vibrato;
mono_descriptor->run_adding = run_adding_Vibrato;
mono_descriptor->set_run_adding_gain = set_run_adding_gain_Vibrato;
mono_descriptor->deactivate = NULL;
mono_descriptor->cleanup = cleanup_Vibrato;
}
void
delete_descriptor(LADSPA_Descriptor * descriptor) {
unsigned long index;
if (descriptor) {
free((char *)descriptor->Label);
free((char *)descriptor->Name);
free((char *)descriptor->Maker);
free((char *)descriptor->Copyright);
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
for (index = 0; index < descriptor->PortCount; index++)
free((char *)(descriptor->PortNames[index]));
free((char **)descriptor->PortNames);
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
free(descriptor);
}
}
/* __attribute__((destructor)) tap_fini() is called automatically when the library is unloaded. */
void
__attribute__((destructor)) tap_fini() {
delete_descriptor(mono_descriptor);
}
/* Return a descriptor of the requested plugin type. */
const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index) {
switch (Index) {
case 0:
return mono_descriptor;
default:
return NULL;
}
}