From 5d62cdbd1e5dd92450d360a41e118fbe9fdf1048 Mon Sep 17 00:00:00 2001 From: Leland Lucius Date: Thu, 27 Feb 2020 00:52:34 -0600 Subject: [PATCH] Add sc4 plug-in to CMake build for Windows and Mac --- CMakeLists.txt | 5 + cmake-proxies/ladspa-plugins/CMakeLists.txt | 43 ++ cmake-proxies/ladspa-plugins/COPYING | 340 +++++++++++ cmake-proxies/ladspa-plugins/README | 6 + cmake-proxies/ladspa-plugins/config.h | 1 + cmake-proxies/ladspa-plugins/ladspa-util.h | 233 ++++++++ cmake-proxies/ladspa-plugins/sc4_1882.c | 629 ++++++++++++++++++++ cmake-proxies/ladspa-plugins/util/db.c | 22 + cmake-proxies/ladspa-plugins/util/db.h | 86 +++ cmake-proxies/ladspa-plugins/util/rms.c | 25 + cmake-proxies/ladspa-plugins/util/rms.h | 35 ++ 11 files changed, 1425 insertions(+) create mode 100644 cmake-proxies/ladspa-plugins/CMakeLists.txt create mode 100644 cmake-proxies/ladspa-plugins/COPYING create mode 100644 cmake-proxies/ladspa-plugins/README create mode 100644 cmake-proxies/ladspa-plugins/config.h create mode 100644 cmake-proxies/ladspa-plugins/ladspa-util.h create mode 100644 cmake-proxies/ladspa-plugins/sc4_1882.c create mode 100644 cmake-proxies/ladspa-plugins/util/db.c create mode 100644 cmake-proxies/ladspa-plugins/util/db.h create mode 100644 cmake-proxies/ladspa-plugins/util/rms.c create mode 100644 cmake-proxies/ladspa-plugins/util/rms.h diff --git a/CMakeLists.txt b/CMakeLists.txt index bc956fd9a..e3470627b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -547,6 +547,11 @@ add_subdirectory( "cmake-proxies/mod-null" ) add_subdirectory( "cmake-proxies/mod-nyq-bench" ) add_subdirectory( "cmake-proxies/mod-script-pipe" ) +# Only need the sc4_1882 Ladspa plug-in on Windows and Mac +if( CMAKE_SYSTEM_NAME MATCHES "Windows|Darwin" ) + add_subdirectory( "cmake-proxies/ladspa-plugins" ) +endif() + # Uncomment what follows for symbol values. #[[ get_cmake_property(_variableNames VARIABLES) diff --git a/cmake-proxies/ladspa-plugins/CMakeLists.txt b/cmake-proxies/ladspa-plugins/CMakeLists.txt new file mode 100644 index 000000000..9958900d9 --- /dev/null +++ b/cmake-proxies/ladspa-plugins/CMakeLists.txt @@ -0,0 +1,43 @@ + +set( TARGET sc4_1882 ) +set( TARGET_ROOT "${_SRCDIR}" ) + +message( STATUS "========== Configuring ${TARGET} ==========" ) + +add_library( ${TARGET} MODULE EXCLUDE_FROM_ALL ) + +def_vars() + +list( APPEND SOURCES + PRIVATE + ${_SRCDIR}/sc4_1882.c + ${_SRCDIR}/util/db.c + ${_SRCDIR}/util/rms.c +) + +list( APPEND INCLUDES + PRIVATE + ${_SRCDIR} + ${topdir}/src/effects/ladspa +) + +list( APPEND OPTIONS + PRIVATE + $<$:-D_init=__attribute__\(\(constructor\)\)_${TARGET}_init> +) + +set_target_property_all( ${TARGET} + LIBRARY_OUTPUT_DIRECTORY + "${_DEST}/plug-ins" +) + +set_target_properties( ${TARGET} + PROPERTIES + PREFIX "" + FOLDER "lib-src" +) + +target_sources( ${TARGET} PRIVATE ${SOURCES} ) +target_compile_options( ${TARGET} PRIVATE ${OPTIONS} ) +target_include_directories( ${TARGET} PRIVATE ${INCLUDES} ) + diff --git a/cmake-proxies/ladspa-plugins/COPYING b/cmake-proxies/ladspa-plugins/COPYING new file mode 100644 index 000000000..d60c31a97 --- /dev/null +++ b/cmake-proxies/ladspa-plugins/COPYING @@ -0,0 +1,340 @@ + 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. + + + Copyright (C) + + 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. + + , 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. diff --git a/cmake-proxies/ladspa-plugins/README b/cmake-proxies/ladspa-plugins/README new file mode 100644 index 000000000..49b4dbe30 --- /dev/null +++ b/cmake-proxies/ladspa-plugins/README @@ -0,0 +1,6 @@ +This plug-in was extracted from the swh-plugins found here: + + http://plugin.org.uk/ + +See COPYING for license information. + diff --git a/cmake-proxies/ladspa-plugins/config.h b/cmake-proxies/ladspa-plugins/config.h new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/cmake-proxies/ladspa-plugins/config.h @@ -0,0 +1 @@ + diff --git a/cmake-proxies/ladspa-plugins/ladspa-util.h b/cmake-proxies/ladspa-plugins/ladspa-util.h new file mode 100644 index 000000000..ef6e31bed --- /dev/null +++ b/cmake-proxies/ladspa-plugins/ladspa-util.h @@ -0,0 +1,233 @@ +/* Some misc util functions for audio DSP work, written by Steve Harris, + * December 2000 + * + * steve@plugin.org.uk + */ + +#ifndef LADSPA_UTIL_H +#define LADSPA_UTIL_H + +#include +#include + +#include "config.h" + +// 16.16 fixpoint +typedef union { + int32_t all; + struct { +#ifdef WORDS_BIGENDIAN + int16_t in; + uint16_t fr; +#else + uint16_t fr; + int16_t in; +#endif + } part; +} fixp16; + +// 32.32 fixpoint +typedef union { + int64_t all; + struct { +#ifdef WORDS_BIGENDIAN + int32_t in; + uint32_t fr; +#else + uint32_t fr; + int32_t in; +#endif + } part; +} fixp32; + +/* 32 bit "pointer cast" union */ +typedef union { + float f; + int32_t i; +} ls_pcast32; + +// Sometimes it doesn't get defined, even though it eists and C99 is declared +long int lrintf (float x); + +// 1.0 / ln(2) +#define LN2R 1.442695041f + +/* detet floating point denormal numbers by comparing them to the smallest + * normal, crap, but reliable */ +#define DN_CHECK(x, l) if (fabs(x) < 1e-38) printf("DN: "l"\n") + +// Denormalise floats, only actually needed for PIII and recent PowerPC +//#define FLUSH_TO_ZERO(fv) (((*(unsigned int*)&(fv))&0x7f800000)==0)?0.0f:(fv) + +static inline float flush_to_zero(float f) +{ + ls_pcast32 v; + + v.f = f; + + // original: return (v.i & 0x7f800000) == 0 ? 0.0f : f; + // version from Tim Blechmann + return (v.i & 0x7f800000) < 0x08000000 ? 0.0f : f; +} + +static inline void round_to_zero(volatile float *f) +{ + *f += 1e-18; + *f -= 1e-18; +} + +/* A set of branchless clipping operations from Laurent de Soras */ + +static inline float f_max(float x, float a) +{ + x -= a; + x += fabs(x); + x *= 0.5; + x += a; + + return x; +} + +static inline float f_min(float x, float b) +{ + x = b - x; + x += fabs(x); + x *= 0.5; + x = b - x; + + return x; +} + +static inline float f_clamp(float x, float a, float b) +{ + const float x1 = fabs(x - a); + const float x2 = fabs(x - b); + + x = x1 + a + b; + x -= x2; + x *= 0.5; + + return x; +} + +// Limit a value to be l<=v<=u +#define LIMIT(v,l,u) ((v)<(l)?(l):((v)>(u)?(u):(v))) + +// Truncate-to-zero modulo (ANSI C doesn't specify) will only work +// if -m < v < 2m +#define MOD(v,m) (v<0?v+m:(v>=m?v-m:v)) + +// Truncate-to-zero modulo (ANSI C doesn't specify) will only work +// if v > -m and v < m +#define NEG_MOD(v,m) ((v)<0?((v)+(m)):(v)) + +// Convert a value in dB's to a coefficent +#define DB_CO(g) ((g) > -90.0f ? powf(10.0f, (g) * 0.05f) : 0.0f) +#define CO_DB(v) (20.0f * log10f(v)) + +// Linearly interpolate [ = a * (1 - f) + b * f] +#define LIN_INTERP(f,a,b) ((a) + (f) * ((b) - (a))) + +// Cubic interpolation function +static inline float cube_interp(const float fr, const float inm1, const float + in, const float inp1, const float inp2) +{ + return in + 0.5f * fr * (inp1 - inm1 + + fr * (4.0f * inp1 + 2.0f * inm1 - 5.0f * in - inp2 + + fr * (3.0f * (in - inp1) - inm1 + inp2))); +} + +/* fast sin^2 aproxiamtion, adapted from jan AT rpgfan's posting to the + * music-dsp list */ +static inline float f_sin_sq(float angle) +{ + const float asqr = angle * angle; + float result = -2.39e-08f; + + result *= asqr; + result += 2.7526e-06f; + result *= asqr; + result -= 1.98409e-04f; + result *= asqr; + result += 8.3333315e-03f; + result *= asqr; + result -= 1.666666664e-01f; + result *= asqr; + result += 1.0f; + result *= angle; + + return result * result; +} + +#ifdef HAVE_LRINTF + +#define f_round(f) lrintf(f) + +#else + +// Round float to int using IEEE int* hack +static inline int f_round(float f) +{ + ls_pcast32 p; + + p.f = f; + p.f += (3<<22); + + return p.i - 0x4b400000; +} + +#endif + +// Truncate float to int +static inline int f_trunc(float f) +{ + return f_round(floorf(f)); +} + +/* Andrew Simper's pow(2, x) aproximation from the music-dsp list */ + +#if 0 + +/* original */ +static inline float f_pow2(float x) +{ + long *px = (long*)(&x); // store address of float as long pointer + const float tx = (x-0.5f) + (3<<22); // temporary value for truncation + const long lx = *((long*)&tx) - 0x4b400000; // integer power of 2 + const float dx = x-(float)(lx); // float remainder of power of 2 + + x = 1.0f + dx*(0.6960656421638072f + // cubic apporoximation of 2^x + dx*(0.224494337302845f + // for x in the range [0, 1] + dx*(0.07944023841053369f))); + *px += (lx<<23); // add integer power of 2 to exponent + + return x; +} + +#else + +/* union version */ +static inline float f_pow2(float x) +{ + ls_pcast32 *px, tx, lx; + float dx; + + px = (ls_pcast32 *)&x; // store address of float as long pointer + tx.f = (x-0.5f) + (3<<22); // temporary value for truncation + lx.i = tx.i - 0x4b400000; // integer power of 2 + dx = x - (float)lx.i; // float remainder of power of 2 + + x = 1.0f + dx * (0.6960656421638072f + // cubic apporoximation of 2^x + dx * (0.224494337302845f + // for x in the range [0, 1] + dx * (0.07944023841053369f))); + (*px).i += (lx.i << 23); // add integer power of 2 to exponent + + return (*px).f; +} + +#endif + +/* Fast exponentiation function, y = e^x */ +#define f_exp(x) f_pow2(x * LN2R) + +#endif diff --git a/cmake-proxies/ladspa-plugins/sc4_1882.c b/cmake-proxies/ladspa-plugins/sc4_1882.c new file mode 100644 index 000000000..63493383b --- /dev/null +++ b/cmake-proxies/ladspa-plugins/sc4_1882.c @@ -0,0 +1,629 @@ +#include +#include +#ifndef WIN32 +#include "config.h" +#endif + +#ifdef ENABLE_NLS +#include +#endif + +#define _ISOC9X_SOURCE 1 +#define _ISOC99_SOURCE 1 +#define __USE_ISOC99 1 +#define __USE_ISOC9X 1 + +#include + +#include "ladspa.h" + +#ifdef WIN32 +#define _WINDOWS_DLL_EXPORT_ __declspec(dllexport) +int bIsFirstTime = 1; +void _init(); // forward declaration +#else +#define _WINDOWS_DLL_EXPORT_ +#endif + +#line 10 "sc4_1882.xml" + +#include "util/db.h" +#include "util/rms.h" + +#define A_TBL 256 + +#define SC4_RMS_PEAK 0 +#define SC4_ATTACK 1 +#define SC4_RELEASE 2 +#define SC4_THRESHOLD 3 +#define SC4_RATIO 4 +#define SC4_KNEE 5 +#define SC4_MAKEUP_GAIN 6 +#define SC4_AMPLITUDE 7 +#define SC4_GAIN_RED 8 +#define SC4_LEFT_IN 9 +#define SC4_RIGHT_IN 10 +#define SC4_LEFT_OUT 11 +#define SC4_RIGHT_OUT 12 + +static LADSPA_Descriptor *sc4Descriptor = NULL; + +typedef struct { + LADSPA_Data *rms_peak; + LADSPA_Data *attack; + LADSPA_Data *release; + LADSPA_Data *threshold; + LADSPA_Data *ratio; + LADSPA_Data *knee; + LADSPA_Data *makeup_gain; + LADSPA_Data *amplitude; + LADSPA_Data *gain_red; + LADSPA_Data *left_in; + LADSPA_Data *right_in; + LADSPA_Data *left_out; + LADSPA_Data *right_out; + float amp; + float * as; + unsigned int count; + float env; + float env_peak; + float env_rms; + float gain; + float gain_t; + rms_env * rms; + float sum; + LADSPA_Data run_adding_gain; +} Sc4; + +_WINDOWS_DLL_EXPORT_ +const LADSPA_Descriptor *ladspa_descriptor(unsigned long index) { + +#ifdef WIN32 + if (bIsFirstTime) { + _init(); + bIsFirstTime = 0; + } +#endif + switch (index) { + case 0: + return sc4Descriptor; + default: + return NULL; + } +} + +static void cleanupSc4(LADSPA_Handle instance) { +#line 46 "sc4_1882.xml" + Sc4 *plugin_data = (Sc4 *)instance; + rms_env_free(plugin_data->rms); + free(plugin_data->as); + free(instance); +} + +static void connectPortSc4( + LADSPA_Handle instance, + unsigned long port, + LADSPA_Data *data) { + Sc4 *plugin; + + plugin = (Sc4 *)instance; + switch (port) { + case SC4_RMS_PEAK: + plugin->rms_peak = data; + break; + case SC4_ATTACK: + plugin->attack = data; + break; + case SC4_RELEASE: + plugin->release = data; + break; + case SC4_THRESHOLD: + plugin->threshold = data; + break; + case SC4_RATIO: + plugin->ratio = data; + break; + case SC4_KNEE: + plugin->knee = data; + break; + case SC4_MAKEUP_GAIN: + plugin->makeup_gain = data; + break; + case SC4_AMPLITUDE: + plugin->amplitude = data; + break; + case SC4_GAIN_RED: + plugin->gain_red = data; + break; + case SC4_LEFT_IN: + plugin->left_in = data; + break; + case SC4_RIGHT_IN: + plugin->right_in = data; + break; + case SC4_LEFT_OUT: + plugin->left_out = data; + break; + case SC4_RIGHT_OUT: + plugin->right_out = data; + break; + } +} + +static LADSPA_Handle instantiateSc4( + const LADSPA_Descriptor *descriptor, + unsigned long s_rate) { + Sc4 *plugin_data = (Sc4 *)malloc(sizeof(Sc4)); + float amp; + float *as = NULL; + unsigned int count; + float env; + float env_peak; + float env_rms; + float gain; + float gain_t; + rms_env *rms = NULL; + float sum; + +#line 23 "sc4_1882.xml" + unsigned int i; + float sample_rate = (float)s_rate; + + rms = rms_env_new(); + sum = 0.0f; + amp = 0.0f; + gain = 0.0f; + gain_t = 0.0f; + env = 0.0f; + env_rms = 0.0f; + env_peak = 0.0f; + count = 0; + + as = malloc(A_TBL * sizeof(float)); + as[0] = 1.0f; + for (i=1; iamp = amp; + plugin_data->as = as; + plugin_data->count = count; + plugin_data->env = env; + plugin_data->env_peak = env_peak; + plugin_data->env_rms = env_rms; + plugin_data->gain = gain; + plugin_data->gain_t = gain_t; + plugin_data->rms = rms; + plugin_data->sum = sum; + + return (LADSPA_Handle)plugin_data; +} + +#undef buffer_write +#undef RUN_ADDING +#undef RUN_REPLACING + +#define buffer_write(b, v) (b = v) +#define RUN_ADDING 0 +#define RUN_REPLACING 1 + +static void runSc4(LADSPA_Handle instance, unsigned long sample_count) { + Sc4 *plugin_data = (Sc4 *)instance; + + /* RMS/peak (float value) */ + const LADSPA_Data rms_peak = *(plugin_data->rms_peak); + + /* Attack time (ms) (float value) */ + const LADSPA_Data attack = *(plugin_data->attack); + + /* Release time (ms) (float value) */ + const LADSPA_Data release = *(plugin_data->release); + + /* Threshold level (dB) (float value) */ + const LADSPA_Data threshold = *(plugin_data->threshold); + + /* Ratio (1:n) (float value) */ + const LADSPA_Data ratio = *(plugin_data->ratio); + + /* Knee radius (dB) (float value) */ + const LADSPA_Data knee = *(plugin_data->knee); + + /* Makeup gain (dB) (float value) */ + const LADSPA_Data makeup_gain = *(plugin_data->makeup_gain); + + /* Left input (array of floats of length sample_count) */ + const LADSPA_Data * const left_in = plugin_data->left_in; + + /* Right input (array of floats of length sample_count) */ + const LADSPA_Data * const right_in = plugin_data->right_in; + + /* Left output (array of floats of length sample_count) */ + LADSPA_Data * const left_out = plugin_data->left_out; + + /* Right output (array of floats of length sample_count) */ + LADSPA_Data * const right_out = plugin_data->right_out; + float amp = plugin_data->amp; + float * as = plugin_data->as; + unsigned int count = plugin_data->count; + float env = plugin_data->env; + float env_peak = plugin_data->env_peak; + float env_rms = plugin_data->env_rms; + float gain = plugin_data->gain; + float gain_t = plugin_data->gain_t; + rms_env * rms = plugin_data->rms; + float sum = plugin_data->sum; + +#line 51 "sc4_1882.xml" + unsigned long pos; + + const float ga = attack < 2.0f ? 0.0f : as[f_round(attack * 0.001f * (float)(A_TBL-1))]; + const float gr = as[f_round(release * 0.001f * (float)(A_TBL-1))]; + const float rs = (ratio - 1.0f) / ratio; + const float mug = db2lin(makeup_gain); + const float knee_min = db2lin(threshold - knee); + const float knee_max = db2lin(threshold + knee); + const float ef_a = ga * 0.25f; + const float ef_ai = 1.0f - ef_a; + + for (pos = 0; pos < sample_count; pos++) { + const float la = fabs(left_in[pos]); + const float ra = fabs(right_in[pos]); + const float lev_in = f_max(la, ra); + sum += lev_in * lev_in; + + if (amp > env_rms) { + env_rms = env_rms * ga + amp * (1.0f - ga); + } else { + env_rms = env_rms * gr + amp * (1.0f - gr); + } + round_to_zero(&env_rms); + if (lev_in > env_peak) { + env_peak = env_peak * ga + lev_in * (1.0f - ga); + } else { + env_peak = env_peak * gr + lev_in * (1.0f - gr); + } + round_to_zero(&env_peak); + if ((count++ & 3) == 3) { + amp = rms_env_process(rms, sum * 0.25f); + sum = 0.0f; + if (isnan(env_rms)) { + // This can happen sometimes, but I don't know why + env_rms = 0.0f; + } + + env = LIN_INTERP(rms_peak, env_rms, env_peak); + + if (env <= knee_min) { + gain_t = 1.0f; + } else if (env < knee_max) { + const float x = -(threshold - knee - lin2db(env)) / knee; + gain_t = db2lin(-knee * rs * x * x * 0.25f); + } else { + gain_t = db2lin((threshold - lin2db(env)) * rs); + } + } + gain = gain * ef_a + gain_t * ef_ai; + buffer_write(left_out[pos], left_in[pos] * gain * mug); + buffer_write(right_out[pos], right_in[pos] * gain * mug); + } + plugin_data->sum = sum; + plugin_data->amp = amp; + plugin_data->gain = gain; + plugin_data->gain_t = gain_t; + plugin_data->env = env; + plugin_data->env_rms = env_rms; + plugin_data->env_peak = env_peak; + plugin_data->count = count; + + *(plugin_data->amplitude) = lin2db(env); + *(plugin_data->gain_red) = lin2db(gain); +} +#undef buffer_write +#undef RUN_ADDING +#undef RUN_REPLACING + +#define buffer_write(b, v) (b += (v) * run_adding_gain) +#define RUN_ADDING 1 +#define RUN_REPLACING 0 + +static void setRunAddingGainSc4(LADSPA_Handle instance, LADSPA_Data gain) { + ((Sc4 *)instance)->run_adding_gain = gain; +} + +static void runAddingSc4(LADSPA_Handle instance, unsigned long sample_count) { + Sc4 *plugin_data = (Sc4 *)instance; + LADSPA_Data run_adding_gain = plugin_data->run_adding_gain; + + /* RMS/peak (float value) */ + const LADSPA_Data rms_peak = *(plugin_data->rms_peak); + + /* Attack time (ms) (float value) */ + const LADSPA_Data attack = *(plugin_data->attack); + + /* Release time (ms) (float value) */ + const LADSPA_Data release = *(plugin_data->release); + + /* Threshold level (dB) (float value) */ + const LADSPA_Data threshold = *(plugin_data->threshold); + + /* Ratio (1:n) (float value) */ + const LADSPA_Data ratio = *(plugin_data->ratio); + + /* Knee radius (dB) (float value) */ + const LADSPA_Data knee = *(plugin_data->knee); + + /* Makeup gain (dB) (float value) */ + const LADSPA_Data makeup_gain = *(plugin_data->makeup_gain); + + /* Left input (array of floats of length sample_count) */ + const LADSPA_Data * const left_in = plugin_data->left_in; + + /* Right input (array of floats of length sample_count) */ + const LADSPA_Data * const right_in = plugin_data->right_in; + + /* Left output (array of floats of length sample_count) */ + LADSPA_Data * const left_out = plugin_data->left_out; + + /* Right output (array of floats of length sample_count) */ + LADSPA_Data * const right_out = plugin_data->right_out; + float amp = plugin_data->amp; + float * as = plugin_data->as; + unsigned int count = plugin_data->count; + float env = plugin_data->env; + float env_peak = plugin_data->env_peak; + float env_rms = plugin_data->env_rms; + float gain = plugin_data->gain; + float gain_t = plugin_data->gain_t; + rms_env * rms = plugin_data->rms; + float sum = plugin_data->sum; + +#line 51 "sc4_1882.xml" + unsigned long pos; + + const float ga = attack < 2.0f ? 0.0f : as[f_round(attack * 0.001f * (float)(A_TBL-1))]; + const float gr = as[f_round(release * 0.001f * (float)(A_TBL-1))]; + const float rs = (ratio - 1.0f) / ratio; + const float mug = db2lin(makeup_gain); + const float knee_min = db2lin(threshold - knee); + const float knee_max = db2lin(threshold + knee); + const float ef_a = ga * 0.25f; + const float ef_ai = 1.0f - ef_a; + + for (pos = 0; pos < sample_count; pos++) { + const float la = fabs(left_in[pos]); + const float ra = fabs(right_in[pos]); + const float lev_in = f_max(la, ra); + sum += lev_in * lev_in; + + if (amp > env_rms) { + env_rms = env_rms * ga + amp * (1.0f - ga); + } else { + env_rms = env_rms * gr + amp * (1.0f - gr); + } + round_to_zero(&env_rms); + if (lev_in > env_peak) { + env_peak = env_peak * ga + lev_in * (1.0f - ga); + } else { + env_peak = env_peak * gr + lev_in * (1.0f - gr); + } + round_to_zero(&env_peak); + if ((count++ & 3) == 3) { + amp = rms_env_process(rms, sum * 0.25f); + sum = 0.0f; + if (isnan(env_rms)) { + // This can happen sometimes, but I don't know why + env_rms = 0.0f; + } + + env = LIN_INTERP(rms_peak, env_rms, env_peak); + + if (env <= knee_min) { + gain_t = 1.0f; + } else if (env < knee_max) { + const float x = -(threshold - knee - lin2db(env)) / knee; + gain_t = db2lin(-knee * rs * x * x * 0.25f); + } else { + gain_t = db2lin((threshold - lin2db(env)) * rs); + } + } + gain = gain * ef_a + gain_t * ef_ai; + buffer_write(left_out[pos], left_in[pos] * gain * mug); + buffer_write(right_out[pos], right_in[pos] * gain * mug); + } + plugin_data->sum = sum; + plugin_data->amp = amp; + plugin_data->gain = gain; + plugin_data->gain_t = gain_t; + plugin_data->env = env; + plugin_data->env_rms = env_rms; + plugin_data->env_peak = env_peak; + plugin_data->count = count; + + *(plugin_data->amplitude) = lin2db(env); + *(plugin_data->gain_red) = lin2db(gain); +} + +void _init() { + char **port_names; + LADSPA_PortDescriptor *port_descriptors; + LADSPA_PortRangeHint *port_range_hints; + +#ifdef ENABLE_NLS +#define D_(s) dgettext(PACKAGE, s) + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, PACKAGE_LOCALE_DIR); +#else +#define D_(s) (s) +#endif + + + sc4Descriptor = + (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor)); + + if (sc4Descriptor) { + sc4Descriptor->UniqueID = 1882; + sc4Descriptor->Label = "sc4"; + sc4Descriptor->Properties = + LADSPA_PROPERTY_HARD_RT_CAPABLE; + sc4Descriptor->Name = + D_("SC4"); + sc4Descriptor->Maker = + "Steve Harris "; + sc4Descriptor->Copyright = + "GPL"; + sc4Descriptor->PortCount = 13; + + port_descriptors = (LADSPA_PortDescriptor *)calloc(13, + sizeof(LADSPA_PortDescriptor)); + sc4Descriptor->PortDescriptors = + (const LADSPA_PortDescriptor *)port_descriptors; + + port_range_hints = (LADSPA_PortRangeHint *)calloc(13, + sizeof(LADSPA_PortRangeHint)); + sc4Descriptor->PortRangeHints = + (const LADSPA_PortRangeHint *)port_range_hints; + + port_names = (char **)calloc(13, sizeof(char*)); + sc4Descriptor->PortNames = + (const char **)port_names; + + /* Parameters for RMS/peak */ + port_descriptors[SC4_RMS_PEAK] = + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL; + port_names[SC4_RMS_PEAK] = + D_("RMS/peak"); + port_range_hints[SC4_RMS_PEAK].HintDescriptor = + LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MINIMUM; + port_range_hints[SC4_RMS_PEAK].LowerBound = 0; + port_range_hints[SC4_RMS_PEAK].UpperBound = 1; + + /* Parameters for Attack time (ms) */ + port_descriptors[SC4_ATTACK] = + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL; + port_names[SC4_ATTACK] = + D_("Attack time (ms)"); + port_range_hints[SC4_ATTACK].HintDescriptor = + LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW; + port_range_hints[SC4_ATTACK].LowerBound = 1.5; + port_range_hints[SC4_ATTACK].UpperBound = 400; + + /* Parameters for Release time (ms) */ + port_descriptors[SC4_RELEASE] = + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL; + port_names[SC4_RELEASE] = + D_("Release time (ms)"); + port_range_hints[SC4_RELEASE].HintDescriptor = + LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MIDDLE; + port_range_hints[SC4_RELEASE].LowerBound = 2; + port_range_hints[SC4_RELEASE].UpperBound = 800; + + /* Parameters for Threshold level (dB) */ + port_descriptors[SC4_THRESHOLD] = + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL; + port_names[SC4_THRESHOLD] = + D_("Threshold level (dB)"); + port_range_hints[SC4_THRESHOLD].HintDescriptor = + LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MAXIMUM; + port_range_hints[SC4_THRESHOLD].LowerBound = -30; + port_range_hints[SC4_THRESHOLD].UpperBound = 0; + + /* Parameters for Ratio (1:n) */ + port_descriptors[SC4_RATIO] = + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL; + port_names[SC4_RATIO] = + D_("Ratio (1:n)"); + port_range_hints[SC4_RATIO].HintDescriptor = + LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_1; + port_range_hints[SC4_RATIO].LowerBound = 1; + port_range_hints[SC4_RATIO].UpperBound = 20; + + /* Parameters for Knee radius (dB) */ + port_descriptors[SC4_KNEE] = + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL; + port_names[SC4_KNEE] = + D_("Knee radius (dB)"); + port_range_hints[SC4_KNEE].HintDescriptor = + LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW; + port_range_hints[SC4_KNEE].LowerBound = 1; + port_range_hints[SC4_KNEE].UpperBound = 10; + + /* Parameters for Makeup gain (dB) */ + port_descriptors[SC4_MAKEUP_GAIN] = + LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL; + port_names[SC4_MAKEUP_GAIN] = + D_("Makeup gain (dB)"); + port_range_hints[SC4_MAKEUP_GAIN].HintDescriptor = + LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0; + port_range_hints[SC4_MAKEUP_GAIN].LowerBound = 0; + port_range_hints[SC4_MAKEUP_GAIN].UpperBound = +24; + + /* Parameters for Amplitude (dB) */ + port_descriptors[SC4_AMPLITUDE] = + LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL; + port_names[SC4_AMPLITUDE] = + D_("Amplitude (dB)"); + port_range_hints[SC4_AMPLITUDE].HintDescriptor = + LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE; + port_range_hints[SC4_AMPLITUDE].LowerBound = -40; + port_range_hints[SC4_AMPLITUDE].UpperBound = +12; + + /* Parameters for Gain reduction (dB) */ + port_descriptors[SC4_GAIN_RED] = + LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL; + port_names[SC4_GAIN_RED] = + D_("Gain reduction (dB)"); + port_range_hints[SC4_GAIN_RED].HintDescriptor = + LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE; + port_range_hints[SC4_GAIN_RED].LowerBound = -24; + port_range_hints[SC4_GAIN_RED].UpperBound = 0; + + /* Parameters for Left input */ + port_descriptors[SC4_LEFT_IN] = + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO; + port_names[SC4_LEFT_IN] = + D_("Left input"); + port_range_hints[SC4_LEFT_IN].HintDescriptor = 0; + + /* Parameters for Right input */ + port_descriptors[SC4_RIGHT_IN] = + LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO; + port_names[SC4_RIGHT_IN] = + D_("Right input"); + port_range_hints[SC4_RIGHT_IN].HintDescriptor = 0; + + /* Parameters for Left output */ + port_descriptors[SC4_LEFT_OUT] = + LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; + port_names[SC4_LEFT_OUT] = + D_("Left output"); + port_range_hints[SC4_LEFT_OUT].HintDescriptor = 0; + + /* Parameters for Right output */ + port_descriptors[SC4_RIGHT_OUT] = + LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; + port_names[SC4_RIGHT_OUT] = + D_("Right output"); + port_range_hints[SC4_RIGHT_OUT].HintDescriptor = 0; + + sc4Descriptor->activate = NULL; + sc4Descriptor->cleanup = cleanupSc4; + sc4Descriptor->connect_port = connectPortSc4; + sc4Descriptor->deactivate = NULL; + sc4Descriptor->instantiate = instantiateSc4; + sc4Descriptor->run = runSc4; + sc4Descriptor->run_adding = runAddingSc4; + sc4Descriptor->set_run_adding_gain = setRunAddingGainSc4; + } +} + +void _fini() { + if (sc4Descriptor) { + free((LADSPA_PortDescriptor *)sc4Descriptor->PortDescriptors); + free((char **)sc4Descriptor->PortNames); + free((LADSPA_PortRangeHint *)sc4Descriptor->PortRangeHints); + free(sc4Descriptor); + } + +} diff --git a/cmake-proxies/ladspa-plugins/util/db.c b/cmake-proxies/ladspa-plugins/util/db.c new file mode 100644 index 000000000..94e443086 --- /dev/null +++ b/cmake-proxies/ladspa-plugins/util/db.c @@ -0,0 +1,22 @@ +#include +#include + +#include "db.h" + +float db_data[DB_TABLE_SIZE]; +float lin_data[LIN_TABLE_SIZE]; + +void db_init() +{ + unsigned int i; + + for (i=0; i LIN_TABLE_SIZE - 3) { + return lin_data[LIN_TABLE_SIZE - 2]; + } + return cube_interp(ofs, lin_data[base-1], lin_data[base], lin_data[base+1], lin_data[base+2]); +} + +static inline float f_db2lin_lerp(float db) +{ + float scale = (db - DB_MIN) * (float)LIN_TABLE_SIZE / (DB_MAX - DB_MIN); + int base = f_round(scale - 0.5f); + float ofs = scale - base; + + if (base < 1) { + return 0.0f; + } else if (base > LIN_TABLE_SIZE - 3) { + return lin_data[LIN_TABLE_SIZE - 2]; + } + return (1.0f - ofs) * lin_data[base] + ofs * lin_data[base+1]; +} + +static inline float f_lin2db_cube(float lin) +{ + float scale = (lin - LIN_MIN) * (float)DB_TABLE_SIZE / (LIN_MAX - LIN_MIN); + int base = f_round(scale - 0.5f); + float ofs = scale - base; + + if (base < 2) { + return db_data[2] * scale * 0.5f - 23 * (2.0f - scale); + } else if (base > DB_TABLE_SIZE - 3) { + return db_data[DB_TABLE_SIZE - 2]; + } + return cube_interp(ofs, db_data[base-1], db_data[base], db_data[base+1], db_data[base+2]); +} + +static inline float f_lin2db_lerp(float lin) +{ + float scale = (lin - LIN_MIN) * (float)DB_TABLE_SIZE / (LIN_MAX - LIN_MIN); + int base = f_round(scale - 0.5f); + float ofs = scale - base; + + if (base < 2) { + return db_data[2] * scale * 0.5f - 23.0f * (2.0f - scale); + } else if (base > DB_TABLE_SIZE - 2) { + return db_data[DB_TABLE_SIZE - 1]; + } + return (1.0f - ofs) * db_data[base] + ofs * db_data[base+1]; +} + +#endif diff --git a/cmake-proxies/ladspa-plugins/util/rms.c b/cmake-proxies/ladspa-plugins/util/rms.c new file mode 100644 index 000000000..cca1ce665 --- /dev/null +++ b/cmake-proxies/ladspa-plugins/util/rms.c @@ -0,0 +1,25 @@ +#include +#include "rms.h" + +rms_env *rms_env_new() +{ + 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; ibuffer[i] = 0.0f; + } + r->pos = 0; + r->sum = 0.0f; +} + +void rms_env_free(rms_env *r) +{ + free(r); +} diff --git a/cmake-proxies/ladspa-plugins/util/rms.h b/cmake-proxies/ladspa-plugins/util/rms.h new file mode 100644 index 000000000..efaee6745 --- /dev/null +++ b/cmake-proxies/ladspa-plugins/util/rms.h @@ -0,0 +1,35 @@ +#ifndef _RMS_H +#define _RMS_H + +#include + +#define RMS_BUF_SIZE 64 + +typedef struct { + float buffer[RMS_BUF_SIZE]; + unsigned int pos; + float sum; +} rms_env; + +rms_env *rms_env_new(); + +static inline float rms_env_process(rms_env *r, float x); + +void rms_env_reset(rms_env *r); + +void rms_env_free(rms_env *r); + +inline static float rms_env_process(rms_env *r, const float x) +{ + r->sum -= r->buffer[r->pos]; + r->sum += x; + if (r->sum < 1.0e-6) { + r->sum = 0.0f; + } + r->buffer[r->pos] = x; + r->pos = (r->pos + 1) & (RMS_BUF_SIZE - 1); + + return sqrt(r->sum / (float)RMS_BUF_SIZE); +} + +#endif