From 46f93660d0acf0d34ad9157c7d1da6e3dc34be7a Mon Sep 17 00:00:00 2001 From: minjaesong Date: Sat, 25 Nov 2023 21:46:49 +0900 Subject: [PATCH] all-float FFT and convolution --- COPYING.md | 597 ------------------ src/net/torvald/terrarum/CreditSingleton.kt | 61 ++ src/net/torvald/terrarum/audio/FFT.kt | 304 +++++++++ src/net/torvald/terrarum/audio/FFTConsts.java | 55 ++ .../terrarum/audio/TerrarumAudioFilter.kt | 77 +-- .../terrarum/audio/TerrarumAudioMixerTrack.kt | 3 - 6 files changed, 437 insertions(+), 660 deletions(-) create mode 100644 src/net/torvald/terrarum/audio/FFT.kt create mode 100644 src/net/torvald/terrarum/audio/FFTConsts.java diff --git a/COPYING.md b/COPYING.md index d9adde496..c190b5bbd 100644 --- a/COPYING.md +++ b/COPYING.md @@ -1,5 +1,3 @@ -*Terrarum* - Copyright (C) 2013-2023 Minjae Song ("CuriousTorvald") This program is free software: you can redistribute it and/or modify @@ -14,598 +12,3 @@ 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, see . - ----- - -*Terrarum Sans Bitmap* - -Copyright (c) 2017-2022 Minjae Song ("CuriousTorvald") and the contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ----- - -*Joise* - -Copyright (C) 2013 Jason Taylor - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -*Accidental Noise Library* - -Joise is a derivative work based on Josua Tippetts' C++ library: - - -Copyright (C) 2011 Joshua Tippetts - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - ----- - -*Vector2.java*, *Epsilon.java* - -Copyright (c) 2010-2015 William Bittle -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted -provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this list of conditions - and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright notice, this list of conditions - and the following disclaimer in the documentation and/or other materials provided with the - distribution. -* Neither the name of dyn4j nor the names of its contributors may be used to endorse or - promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Kotlin translated and modified code Copyright (C) 2016 Minjae Song ("CuriousTorvald") - ----- - -*PRTree*, a Priority R-Tree, a spatial index for java code - -Copyright (c) 2008-2012 Robert Olofsson. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -3. Neither the name of the authors nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - ----- - -*HUSLColorConverter.java* - -Copyright (c) 2016 Alexei Boronine - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ----- - -Ambient sound recordings: - - ambient_forest_01.ogg - ambient_meadow_01.ogg - ambient_windy_01.ogg - ambient_woods_01.ogg - crickets_01.ogg - crickets_02.ogg - -Copyright (C) 2012, 2013, 2015, 2016, 2017 Klankbeeld -Sound from - ----- - - Product License - GraalVM Community Edition - -This is a release of GraalVM Community Edition. GraalVM Community Edition -consists of multiple modules. The software as a whole, as well as the JVMCI -and VisualVM modules, are released under version 2 of the GNU General Public -License with the “Classpath” Exception. -The text of the foregoing licenses is reproduced below. - -Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. - -=========================================================================== - -The GNU General Public License (GPL) - -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. - -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) - - 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. - - -"CLASSPATH" EXCEPTION TO THE GPL - -Certain source files distributed by Oracle America and/or its affiliates -are subject to the following clarification and special exception to the GPLv2, -based on the GNU Project exception for its Classpath libraries, known as the -GNU Classpath Exception, but only where Oracle has expressly included in the -particular source file's header the words "Oracle designates this particular -file as subject to the "Classpath" exception as provided by Oracle in the -LICENSE file that accompanied this code." - -You should also note that Oracle includes multiple, independent programs in -this software package. Some of those programs are provided under licenses -deemed incompatible with the GPLv2 by the Free Software Foundation and others. -For example, the package includes programs licensed under the Apache License, -Version 2.0. Such programs are licensed to you under their original licenses. - -Oracle facilitates your further distribution of this package by adding the -Classpath Exception to the necessary parts of its GPLv2 code, which permits you -to use that code in combination with other independent modules not licensed -under the GPLv2. However, note that this would not permit you to commingle code -under an incompatible license with Oracle's GPLv2 licensed code by, for -example, cutting and pasting such code into a file also containing Oracle's -GPLv2 licensed code and then distributing the result. - -Additionally, if you were to remove the Classpath Exception from any of the -files to which it applies and distribute the result, you would likely be -required to license some or all of the other code in that distribution under -the GPLv2 as well, and since the GPLv2 is incompatible with the license terms -of some items included in the distribution by Oracle, removing the Classpath -Exception could therefore effectively compromise your ability to further -distribute the package. - -Proceed with caution and we recommend that you obtain the advice of a lawyer -skilled in open source matters before removing the Classpath Exception or -making modifications to this package which may subsequently be redistributed -and/or involve the use of third party software. - -CLASSPATH EXCEPTION - -Linking this library statically or dynamically with other modules is making a -combined work based on this library. Thus, the terms and conditions of the GNU -General Public License version 2 cover the whole combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent modules, and -to copy and distribute the resulting executable under terms of your choice, -provided that you also meet, for each linked independent module, the terms and -conditions of the license of that module. An independent module is a module -which is not derived from or based on this library. If you modify this library, -you may extend this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this exception -statement from your version. - -=========================================================================== - - WRITTEN OFFER FOR SOURCE CODE -For any software that you receive from Oracle in binary form which is licensed -under an open source license that gives you the right to receive the source -code for that binary, you can obtain a copy of the applicable source code by -visiting http://www.oracle.com/goto/opensourcecode. If the source code for the -binary was not provided to you with the binary, you can also receive a copy of -the source code on physical media by submitting a written request to the -address listed below or by sending an email to Oracle using the following link: -http://www.oracle.com/goto/opensourcecode/request. - -Oracle America, Inc. -Attn: Senior Vice President -Development and Engineering Legal -500 Oracle Parkway, 10th Floor -Redwood Shores, CA 94065 - -Your request should include: -• The name of the binary for which you are requesting the source code -• The name and version number of the Oracle product containing the binary -• The date you received the Oracle product -• Your name -• Your company name (if applicable) -• Your return mailing address and email, and -• A telephone number in the event we need to reach you. - -We may charge you a fee to cover the cost of physical media and processing. -Your request must be sent -a. within three (3) years of the date you received the Oracle product that -included the binary that is the subject of your request, or -b. in the case of code licensed under the GPL v3 for as long as Oracle -offers spare parts or customer support for that product model. - -=========================================================================== diff --git a/src/net/torvald/terrarum/CreditSingleton.kt b/src/net/torvald/terrarum/CreditSingleton.kt index 8e2af4c02..25c9bfe6e 100644 --- a/src/net/torvald/terrarum/CreditSingleton.kt +++ b/src/net/torvald/terrarum/CreditSingleton.kt @@ -221,6 +221,67 @@ as well as the JVMCI and VisualVM modules, are released under version 2 of the GNU General Public License with the “Classpath” Exception. Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + + + + + +$BULLET Jdsp + +Copyright (c) 2019 Sambit Paul + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + + + + +$BULLET Apache Commons Codec +Copyright 2002-2023 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (https://www.apache.org/). + + + + + +$BULLET Apache Commons CSV +Copyright 2005-2023 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (https://www.apache.org/). + + + + + +$BULLET Apache Commons Math + +Copyright 2001-2022 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + +This product includes software developed for Orekit by +CS Systèmes d'Information (http://www.c-s.fr/) +Copyright 2010-2012 CS Systèmes d'Information """).split('\n') diff --git a/src/net/torvald/terrarum/audio/FFT.kt b/src/net/torvald/terrarum/audio/FFT.kt new file mode 100644 index 000000000..b62ee26af --- /dev/null +++ b/src/net/torvald/terrarum/audio/FFT.kt @@ -0,0 +1,304 @@ +package net.torvald.terrarum.audio + +import org.apache.commons.math3.exception.MathIllegalStateException +import org.apache.commons.math3.transform.DftNormalization +import org.apache.commons.math3.transform.TransformType +import org.apache.commons.math3.util.FastMath + +data class FComplex(var real: Float = 0f, var imaginary: Float = 0f) { + operator fun times(other: FComplex) = FComplex( + this.real * other.real - this.imaginary * other.imaginary, + this.real * other.imaginary + this.imaginary * other.real + ) +} + +/** + * Modification of the code form JDSP and Apache Commons Math + * + * Created by minjaesong on 2023-11-25. + */ +object FFT { + + // org.apache.commons.math3.transform.FastFouriesTransformer.java:370 + fun fft(signal: FloatArray): Array { + val dataRI = arrayOf(signal.copyOf(), FloatArray(signal.size)) + + transformInPlace(dataRI, DftNormalization.STANDARD, TransformType.FORWARD) + + val output = dataRI.toComplexArray() + + return getComplex(output, false) + } + + // org.apache.commons.math3.transform.FastFouriesTransformer.java:404 + fun ifftAndGetReal(y: Array): FloatArray { + val dataRI = Array(2) { FloatArray(y.size) } + for (i in y.indices) { + dataRI[0][i] = y[i].real + dataRI[1][i] = y[i].imaginary + } + + transformInPlace(dataRI, DftNormalization.STANDARD, TransformType.INVERSE) + + return dataRI[0] + } + + private fun Array.toComplexArray(): Array { + return Array(this[0].size) { + FComplex(this[0][it], this[1][it]) + } + } + + // com.github.psambit9791.jdsp.transform.FastFourier.java:190 + /** + * Returns the complex value of the fast fourier transformed sequence + * @param onlyPositive Set to True if non-mirrored output is required + * @throws java.lang.ExceptionInInitializerError if called before executing transform() method + * @return Complex[] The complex FFT output + */ + @Throws(ExceptionInInitializerError::class) + fun getComplex(output: Array, onlyPositive: Boolean): Array { + val dftout: Array = if (onlyPositive) { + val numBins: Int = output.size / 2 + 1 + Array(numBins) { FComplex() } + } + else { + Array(output.size) { FComplex() } + } + System.arraycopy(output, 0, dftout, 0, dftout.size) + return dftout + } + + // org.apache.commons.math3.transform.FastFouriesTransformer.java:214 + /** + * Computes the standard transform of the specified complex data. The + * computation is done in place. The input data is laid out as follows + *
    + *
  • {@code dataRI[0][i]} is the real part of the {@code i}-th data point,
  • + *
  • {@code dataRI[1][i]} is the imaginary part of the {@code i}-th data point.
  • + *
+ * + * @param dataRI the two dimensional array of real and imaginary parts of the data + * @param normalization the normalization to be applied to the transformed data + * @param type the type of transform (forward, inverse) to be performed + * @throws DimensionMismatchException if the number of rows of the specified + * array is not two, or the array is not rectangular + * @throws MathIllegalArgumentException if the number of data points is not + * a power of two + */ + private fun transformInPlace(dataRI: Array, normalization: DftNormalization, type: TransformType) { + val dataR = dataRI[0] + val dataI = dataRI[1] + val n = dataR.size + + if (n == 1) { + return + } + else if (n == 2) { + val srcR0 = dataR[0] + val srcI0 = dataI[0] + val srcR1 = dataR[1] + val srcI1 = dataI[1] + + // X_0 = x_0 + x_1 + dataR[0] = srcR0 + srcR1 + dataI[0] = srcI0 + srcI1 + // X_1 = x_0 - x_1 + dataR[1] = srcR0 - srcR1 + dataI[1] = srcI0 - srcI1 + normalizeTransformedData(dataRI, normalization, type) + return + } + + bitReversalShuffle2(dataR, dataI) + + // Do 4-term DFT. + + // Do 4-term DFT. + if (type == TransformType.INVERSE) { + var i0 = 0 + while (i0 < n) { + val i1 = i0 + 1 + val i2 = i0 + 2 + val i3 = i0 + 3 + val srcR0 = dataR[i0] + val srcI0 = dataI[i0] + val srcR1 = dataR[i2] + val srcI1 = dataI[i2] + val srcR2 = dataR[i1] + val srcI2 = dataI[i1] + val srcR3 = dataR[i3] + val srcI3 = dataI[i3] + + // 4-term DFT + // X_0 = x_0 + x_1 + x_2 + x_3 + dataR[i0] = srcR0 + srcR1 + srcR2 + srcR3 + dataI[i0] = srcI0 + srcI1 + srcI2 + srcI3 + // X_1 = x_0 - x_2 + j * (x_3 - x_1) + dataR[i1] = srcR0 - srcR2 + (srcI3 - srcI1) + dataI[i1] = srcI0 - srcI2 + (srcR1 - srcR3) + // X_2 = x_0 - x_1 + x_2 - x_3 + dataR[i2] = srcR0 - srcR1 + srcR2 - srcR3 + dataI[i2] = srcI0 - srcI1 + srcI2 - srcI3 + // X_3 = x_0 - x_2 + j * (x_1 - x_3) + dataR[i3] = srcR0 - srcR2 + (srcI1 - srcI3) + dataI[i3] = srcI0 - srcI2 + (srcR3 - srcR1) + i0 += 4 + } + } + else { + var i0 = 0 + while (i0 < n) { + val i1 = i0 + 1 + val i2 = i0 + 2 + val i3 = i0 + 3 + val srcR0 = dataR[i0] + val srcI0 = dataI[i0] + val srcR1 = dataR[i2] + val srcI1 = dataI[i2] + val srcR2 = dataR[i1] + val srcI2 = dataI[i1] + val srcR3 = dataR[i3] + val srcI3 = dataI[i3] + + // 4-term DFT + // X_0 = x_0 + x_1 + x_2 + x_3 + dataR[i0] = srcR0 + srcR1 + srcR2 + srcR3 + dataI[i0] = srcI0 + srcI1 + srcI2 + srcI3 + // X_1 = x_0 - x_2 + j * (x_3 - x_1) + dataR[i1] = srcR0 - srcR2 + (srcI1 - srcI3) + dataI[i1] = srcI0 - srcI2 + (srcR3 - srcR1) + // X_2 = x_0 - x_1 + x_2 - x_3 + dataR[i2] = srcR0 - srcR1 + srcR2 - srcR3 + dataI[i2] = srcI0 - srcI1 + srcI2 - srcI3 + // X_3 = x_0 - x_2 + j * (x_1 - x_3) + dataR[i3] = srcR0 - srcR2 + (srcI3 - srcI1) + dataI[i3] = srcI0 - srcI2 + (srcR1 - srcR3) + i0 += 4 + } + } + + var lastN0 = 4 + var lastLogN0 = 2 + while (lastN0 < n) { + val n0 = lastN0 shl 1 + val logN0 = lastLogN0 + 1 + val wSubN0R = W_SUB_N_R[logN0] + var wSubN0I = W_SUB_N_I[logN0] + if (type == TransformType.INVERSE) { + wSubN0I = -wSubN0I + } + + // Combine even/odd transforms of size lastN0 into a transform of size N0 (lastN0 * 2). + var destEvenStartIndex = 0 + while (destEvenStartIndex < n) { + val destOddStartIndex = destEvenStartIndex + lastN0 + var wSubN0ToRR = 1f + var wSubN0ToRI = 0f + for (r in 0 until lastN0) { + val grR = dataR[destEvenStartIndex + r] + val grI = dataI[destEvenStartIndex + r] + val hrR = dataR[destOddStartIndex + r] + val hrI = dataI[destOddStartIndex + r] + + // dest[destEvenStartIndex + r] = Gr + WsubN0ToR * Hr + dataR[destEvenStartIndex + r] = grR + wSubN0ToRR * hrR - wSubN0ToRI * hrI + dataI[destEvenStartIndex + r] = grI + wSubN0ToRR * hrI + wSubN0ToRI * hrR + // dest[destOddStartIndex + r] = Gr - WsubN0ToR * Hr + dataR[destOddStartIndex + r] = grR - (wSubN0ToRR * hrR - wSubN0ToRI * hrI) + dataI[destOddStartIndex + r] = grI - (wSubN0ToRR * hrI + wSubN0ToRI * hrR) + + // WsubN0ToR *= WsubN0R + val nextWsubN0ToRR = wSubN0ToRR * wSubN0R - wSubN0ToRI * wSubN0I + val nextWsubN0ToRI = wSubN0ToRR * wSubN0I + wSubN0ToRI * wSubN0R + wSubN0ToRR = nextWsubN0ToRR + wSubN0ToRI = nextWsubN0ToRI + } + destEvenStartIndex += n0 + } + lastN0 = n0 + lastLogN0 = logN0 + } + + normalizeTransformedData(dataRI, normalization, type) + } + + + /** + * Applies the proper normalization to the specified transformed data. + * + * @param dataRI the unscaled transformed data + * @param normalization the normalization to be applied + * @param type the type of transform (forward, inverse) which resulted in the specified data + */ + private fun normalizeTransformedData( + dataRI: Array, + normalization: DftNormalization, type: TransformType + ) { + val dataR = dataRI[0] + val dataI = dataRI[1] + val n = dataR.size + assert(dataI.size == n) + when (normalization) { + DftNormalization.STANDARD -> if (type == TransformType.INVERSE) { + val scaleFactor = 1f / n.toFloat() + var i = 0 + while (i < n) { + dataR[i] *= scaleFactor + dataI[i] *= scaleFactor + i++ + } + } + + DftNormalization.UNITARY -> { + val scaleFactor = (1.0 / FastMath.sqrt(n.toDouble())).toFloat() + var i = 0 + while (i < n) { + dataR[i] *= scaleFactor + dataI[i] *= scaleFactor + i++ + } + } + + else -> throw MathIllegalStateException() + } + } + + /** + * Performs identical index bit reversal shuffles on two arrays of identical + * size. Each element in the array is swapped with another element based on + * the bit-reversal of the index. For example, in an array with length 16, + * item at binary index 0011 (decimal 3) would be swapped with the item at + * binary index 1100 (decimal 12). + * + * @param a the first array to be shuffled + * @param b the second array to be shuffled + */ + private fun bitReversalShuffle2(a: FloatArray, b: FloatArray) { + val n = a.size + assert(b.size == n) + val halfOfN = n shr 1 + var j = 0 + for (i in 0 until n) { + if (i < j) { + // swap indices i & j + var temp = a[i] + a[i] = a[j] + a[j] = temp + temp = b[i] + b[i] = b[j] + b[j] = temp + } + var k = halfOfN + while (k in 1..j) { + j -= k + k = k shr 1 + } + j += k + } + } + + private val W_SUB_N_R = FFTConsts.W_SUB_N_R.map { it.toFloat() }.toFloatArray() + private val W_SUB_N_I = FFTConsts.W_SUB_N_I.map { it.toFloat() }.toFloatArray() + +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/audio/FFTConsts.java b/src/net/torvald/terrarum/audio/FFTConsts.java new file mode 100644 index 000000000..cf2768bd6 --- /dev/null +++ b/src/net/torvald/terrarum/audio/FFTConsts.java @@ -0,0 +1,55 @@ +package net.torvald.terrarum.audio; + +/** + * Created by minjaesong on 2023-11-25. + */ +public class FFTConsts { + + // org.apache.commons.math3.transform.FastFouriesTransformer.java:58 + /** + * {@code W_SUB_N_R[i]} is the real part of + * {@code exp(- 2 * i * pi / n)}: + * {@code W_SUB_N_R[i] = cos(2 * pi/ n)}, where {@code n = 2^i}. + */ + public static final double[] W_SUB_N_R = + { 0x1.0p0, -0x1.0p0, 0x1.1a62633145c07p-54, 0x1.6a09e667f3bcdp-1 + , 0x1.d906bcf328d46p-1, 0x1.f6297cff75cbp-1, 0x1.fd88da3d12526p-1, 0x1.ff621e3796d7ep-1 + , 0x1.ffd886084cd0dp-1, 0x1.fff62169b92dbp-1, 0x1.fffd8858e8a92p-1, 0x1.ffff621621d02p-1 + , 0x1.ffffd88586ee6p-1, 0x1.fffff62161a34p-1, 0x1.fffffd8858675p-1, 0x1.ffffff621619cp-1 + , 0x1.ffffffd885867p-1, 0x1.fffffff62161ap-1, 0x1.fffffffd88586p-1, 0x1.ffffffff62162p-1 + , 0x1.ffffffffd8858p-1, 0x1.fffffffff6216p-1, 0x1.fffffffffd886p-1, 0x1.ffffffffff621p-1 + , 0x1.ffffffffffd88p-1, 0x1.fffffffffff62p-1, 0x1.fffffffffffd9p-1, 0x1.ffffffffffff6p-1 + , 0x1.ffffffffffffep-1, 0x1.fffffffffffffp-1, 0x1.0p0, 0x1.0p0 + , 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0 + , 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0 + , 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0 + , 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0 + , 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0 + , 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0 + , 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0 + , 0x1.0p0, 0x1.0p0, 0x1.0p0 }; + + /** + * {@code W_SUB_N_I[i]} is the imaginary part of + * {@code exp(- 2 * i * pi / n)}: + * {@code W_SUB_N_I[i] = -sin(2 * pi/ n)}, where {@code n = 2^i}. + */ + public static final double[] W_SUB_N_I = + { 0x1.1a62633145c07p-52, -0x1.1a62633145c07p-53, -0x1.0p0, -0x1.6a09e667f3bccp-1 + , -0x1.87de2a6aea963p-2, -0x1.8f8b83c69a60ap-3, -0x1.917a6bc29b42cp-4, -0x1.91f65f10dd814p-5 + , -0x1.92155f7a3667ep-6, -0x1.921d1fcdec784p-7, -0x1.921f0fe670071p-8, -0x1.921f8becca4bap-9 + , -0x1.921faaee6472dp-10, -0x1.921fb2aecb36p-11, -0x1.921fb49ee4ea6p-12, -0x1.921fb51aeb57bp-13 + , -0x1.921fb539ecf31p-14, -0x1.921fb541ad59ep-15, -0x1.921fb5439d73ap-16, -0x1.921fb544197ap-17 + , -0x1.921fb544387bap-18, -0x1.921fb544403c1p-19, -0x1.921fb544422c2p-20, -0x1.921fb54442a83p-21 + , -0x1.921fb54442c73p-22, -0x1.921fb54442cefp-23, -0x1.921fb54442d0ep-24, -0x1.921fb54442d15p-25 + , -0x1.921fb54442d17p-26, -0x1.921fb54442d18p-27, -0x1.921fb54442d18p-28, -0x1.921fb54442d18p-29 + , -0x1.921fb54442d18p-30, -0x1.921fb54442d18p-31, -0x1.921fb54442d18p-32, -0x1.921fb54442d18p-33 + , -0x1.921fb54442d18p-34, -0x1.921fb54442d18p-35, -0x1.921fb54442d18p-36, -0x1.921fb54442d18p-37 + , -0x1.921fb54442d18p-38, -0x1.921fb54442d18p-39, -0x1.921fb54442d18p-40, -0x1.921fb54442d18p-41 + , -0x1.921fb54442d18p-42, -0x1.921fb54442d18p-43, -0x1.921fb54442d18p-44, -0x1.921fb54442d18p-45 + , -0x1.921fb54442d18p-46, -0x1.921fb54442d18p-47, -0x1.921fb54442d18p-48, -0x1.921fb54442d18p-49 + , -0x1.921fb54442d18p-50, -0x1.921fb54442d18p-51, -0x1.921fb54442d18p-52, -0x1.921fb54442d18p-53 + , -0x1.921fb54442d18p-54, -0x1.921fb54442d18p-55, -0x1.921fb54442d18p-56, -0x1.921fb54442d18p-57 + , -0x1.921fb54442d18p-58, -0x1.921fb54442d18p-59, -0x1.921fb54442d18p-60 }; + +} diff --git a/src/net/torvald/terrarum/audio/TerrarumAudioFilter.kt b/src/net/torvald/terrarum/audio/TerrarumAudioFilter.kt index a247a2f20..fc10151a5 100644 --- a/src/net/torvald/terrarum/audio/TerrarumAudioFilter.kt +++ b/src/net/torvald/terrarum/audio/TerrarumAudioFilter.kt @@ -1,7 +1,5 @@ package net.torvald.terrarum.audio -import com.github.psambit9791.jdsp.transform.FastFourier -import com.github.psambit9791.jdsp.transform.InverseFastFourier import com.jme3.math.FastMath import com.jme3.math.FastMath.sin import net.torvald.terrarum.audio.AudioMixer.SPEED_OF_SOUND @@ -9,7 +7,6 @@ import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.BUFFER_SIZE import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATED import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.SAMPLING_RATEF import net.torvald.terrarum.roundToFloat -import org.apache.commons.math3.complex.Complex import java.io.File import kotlin.math.absoluteValue import kotlin.math.roundToInt @@ -298,12 +295,11 @@ class Reverb(val delayMS: Float = 36f, var feedback: Float = 0.92f, var lowpass: } } -class Convolv(ir: File, val gain: Float = decibelsToFullscale(-12.0).toFloat()): TerrarumAudioFilter() { +class Convolv(ir: File, val gain: Float = decibelsToFullscale(-24.0).toFloat()): TerrarumAudioFilter() { private val fftLen: Int - private val convFFT: Array> - private val inbuf: Array -// private val outbuf: Array + private val convFFT: Array> + private val inbuf: Array private val BLOCKSIZE = BUFFER_SIZE / 4 @@ -317,8 +313,8 @@ class Convolv(ir: File, val gain: Float = decibelsToFullscale(-12.0).toFloat()): println("IR Sample Count = $sampleCount; FFT Length = $fftLen") - val conv = Array(2) { DoubleArray(fftLen) } - inbuf = Array(2) { DoubleArray(fftLen) } + val conv = Array(2) { FloatArray(fftLen) } + inbuf = Array(2) { FloatArray(fftLen) } // outbuf = Array(2) { DoubleArray(fftLen) } ir.inputStream().let { @@ -331,8 +327,8 @@ class Convolv(ir: File, val gain: Float = decibelsToFullscale(-12.0).toFloat()): it.read().and(255).shl(8) or it.read().and(255).shl(16) or it.read().and(255).shl(24)) - conv[0][i] = f1.toDouble() - conv[1][i] = f2.toDouble() + conv[0][i] = f1 + conv[1][i] = f2 } it.close() @@ -340,7 +336,7 @@ class Convolv(ir: File, val gain: Float = decibelsToFullscale(-12.0).toFloat()): // fourier-transform the 'conv' convFFT = Array(2) { - FastFourier(conv[it]).let { it.transform(); it.getComplex(false) } + FFT.fft(conv[it]) } println("convFFT Length = ${convFFT[0].size}") @@ -354,72 +350,33 @@ class Convolv(ir: File, val gain: Float = decibelsToFullscale(-12.0).toFloat()): val t1 = System.nanoTime() for (ch in outbuf1.indices) { + push(inbuf1[ch].applyGain(gain), inbuf[ch]) - push(inbuf1[ch].toDoubleArray(gain), inbuf[ch]) - - val inputFFT = FastFourier(inbuf[ch]).let { it.transform(); it.getComplex(false) } - - val Ny = inputFFT.size// + convFFT[ch].size - 1 - -// println("inputFFT.size=${inputFFT.size} convFFT[ch].size=${convFFT[ch].size} Ny=$Ny") + val inputFFT = FFT.fft(inbuf[ch]) val Y = multiply(inputFFT, convFFT[ch]) - val y = real(ifft(Y)) + val y = FFT.ifftAndGetReal(Y) -// val u = y.sliceArray(Ny - BLOCKSIZE until Ny).toFloatArray(gain) // y size == Ny - val u = y.takeLast(BLOCKSIZE).map { it.toFloat() }.toFloatArray() - -// println("y size: ${y.size}; Ny=$Ny") + val u = y.takeLast(BLOCKSIZE).toFloatArray() System.arraycopy(u, 0, outbuf1[ch], 0, BLOCKSIZE) } val t2 = System.nanoTime() val ptime = (t2 - t1).toDouble() val realtime = BLOCKSIZE / SAMPLING_RATED * 1000000000L - if (realtime >= ptime) { -// println("Processing speed: ${realtime / ptime}x FASTER than realtime") - } - else { -// println("Processing speed: ${ptime / realtime}x SLOWER than realtime") - } + println("Processing speed: ${realtime / ptime}x") } - private fun real(cs: Array): DoubleArray { - return cs.map { it.real }.toDoubleArray() + private fun multiply(X: Array, H: Array): Array { + return Array(X.size) { X[it] * H[it] } } - private fun ifft(y: Array): Array { - return InverseFastFourier(y, false).let { it.transform(); it.complex } - } - - private fun multiply(X: Array, H: Array): Array { - if (X.size != H.size) throw IllegalArgumentException() - return Array(X.size) { - //X[it].multiply(H[it]) - - // following is a snippet of the code from org.apache.commons.math3.complex.multiply, - // to remove the non-necessary sanity checks - val a = X[it] - val b = H[it] - val re = a.real * b.real - a.imaginary * b.imaginary - val im = a.real * b.imaginary + a.imaginary * b.real - Complex(re, im) - } - } - - - private fun push(sample: Double, buf: DoubleArray) { - System.arraycopy(buf, 1, buf, 0, buf.size - 1) - buf[buf.lastIndex] = sample - } - - private fun push(samples: DoubleArray, buf: DoubleArray) { + private fun push(samples: FloatArray, buf: FloatArray) { System.arraycopy(buf, samples.size, buf, 0, buf.size - samples.size) System.arraycopy(samples, 0, buf, buf.size - samples.size, samples.size) } - private fun FloatArray.toDoubleArray(gain: Float = 1f) = this.map { it.toDouble() * gain }.toDoubleArray() - private fun DoubleArray.toFloatArray(gain: Float = 1f) = this.map { it.toFloat() * gain }.toFloatArray() + private fun FloatArray.applyGain(gain: Float = 1f) = this.map { it * gain }.toFloatArray() } object XYtoMS: TerrarumAudioFilter() { diff --git a/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt b/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt index b410423b2..4dfe89b99 100644 --- a/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt +++ b/src/net/torvald/terrarum/audio/TerrarumAudioMixerTrack.kt @@ -21,9 +21,6 @@ class TerrarumAudioMixerTrack(val name: String, val isMaster: Boolean = false, v const val SAMPLING_RATEF = 48000f const val SAMPLING_RATED = 48000.0 const val BUFFER_SIZE = 512 // n ms -> 384 * n - - const val INDEX_BGM = 0 - const val INDEX_AMB = 1 } val hash = getHashStr()