From e5a3c99d0f46d825a5550e88a0906f900e31be52 Mon Sep 17 00:00:00 2001 From: musil Date: Thu, 9 Mar 2006 17:05:43 +0000 Subject: initial version JAN_06 with all sources svn path=/trunk/externals/iem/iem_ambi/; revision=4668 --- GnuGPL.txt | 340 ++++++++++ LICENSE.txt | 27 + READ_ME.txt | 6 + help/help-ambi_decode.pd | 247 +++++++ help/help-ambi_decode2.pd | 97 +++ help/help-ambi_decode3.pd | 150 +++++ help/help-ambi_encode.pd | 283 ++++++++ help/help-ambi_rot.pd | 80 +++ help/test-ambi_rot.pd | 80 +++ src/Make.config.in | 28 + src/Makefile | 88 +++ src/ambi_decode.c | 724 +++++++++++++++++++++ src/ambi_decode2.c | 824 ++++++++++++++++++++++++ src/ambi_decode3.c | 772 ++++++++++++++++++++++ src/ambi_decode_cube.c | 799 +++++++++++++++++++++++ src/ambi_encode.c | 433 +++++++++++++ src/ambi_rot.c | 1534 ++++++++++++++++++++++++++++++++++++++++++++ src/configure.ac | 292 +++++++++ src/iem_ambi.c | 44 ++ src/iem_ambi.dsp | 85 +++ src/iem_ambi.dsw | 29 + src/iem_ambi.h | 15 + src/iem_ambi_sources.h | 11 + src/iem_bin_ambi_sources.c | 13 + src/iemlib.h | 102 +++ src/makefile_win | 42 ++ src/makesource.sh | 65 ++ 27 files changed, 7210 insertions(+) create mode 100644 GnuGPL.txt create mode 100644 LICENSE.txt create mode 100644 READ_ME.txt create mode 100644 help/help-ambi_decode.pd create mode 100644 help/help-ambi_decode2.pd create mode 100644 help/help-ambi_decode3.pd create mode 100644 help/help-ambi_encode.pd create mode 100644 help/help-ambi_rot.pd create mode 100644 help/test-ambi_rot.pd create mode 100644 src/Make.config.in create mode 100644 src/Makefile create mode 100644 src/ambi_decode.c create mode 100644 src/ambi_decode2.c create mode 100644 src/ambi_decode3.c create mode 100644 src/ambi_decode_cube.c create mode 100644 src/ambi_encode.c create mode 100644 src/ambi_rot.c create mode 100644 src/configure.ac create mode 100644 src/iem_ambi.c create mode 100644 src/iem_ambi.dsp create mode 100644 src/iem_ambi.dsw create mode 100644 src/iem_ambi.h create mode 100644 src/iem_ambi_sources.h create mode 100644 src/iem_bin_ambi_sources.c create mode 100644 src/iemlib.h create mode 100644 src/makefile_win create mode 100644 src/makesource.sh diff --git a/GnuGPL.txt b/GnuGPL.txt new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/GnuGPL.txt @@ -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/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..cdd6236 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,27 @@ +iem_ambi - ambisonic encoder, rotation and decoder rendering + +Copyright (C) 2000-2006 Thomas MUSIL [musil_at_iem.at] + +IEM - Institute of Electronic Music and Acoustics, Graz +Inffeldgasse 10/3, 8010 Graz, Austria +http://iem.at + + + + 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 ( GnuGPL.txt ). + (e.g. http://www.gnu.org/copyleft/gpl.html) + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Graz, 15 June 2005 + Thomas Musil \ No newline at end of file diff --git a/READ_ME.txt b/READ_ME.txt new file mode 100644 index 0000000..d37dd65 --- /dev/null +++ b/READ_ME.txt @@ -0,0 +1,6 @@ +This library extends the performance of miller puckette's pure data (pd). + +iem_ambi contains 3 objects: +"ambi_encode", "ambi_rot" and "ambi_decode3" +they calculate ambisonic encoder matrices, rotation matrices and +decoder matrices from 1st to 4th order in 2D or 3D. diff --git a/help/help-ambi_decode.pd b/help/help-ambi_decode.pd new file mode 100644 index 0000000..93ce8e3 --- /dev/null +++ b/help/help-ambi_decode.pd @@ -0,0 +1,247 @@ +#N canvas 117 18 719 674 10; +#X obj 47 249 print; +#X text 291 171 1.arg: ambisonic order; +#X text 306 180 (1 .. 12 for 2 dimensional use); +#X obj 47 226 round_zero 1e-006; +#X text 117 310 ambisonic-order = n_ao; +#X msg 150 170 ambi_weight 1 1 1; +#X msg 133 149 ambi_weight 1 1 0.3904; +#X text 305 385 ambisonic-order-group; +#X text 98 416 -90 <= delta <= +90; +#X text 98 428 -180 <= phi <= +180; +#X text 34 385 input: one mul-factor for each; +#X text 21 12 ambi_decode; +#X text 105 12 calculates a decoder-matrix; +#X obj 47 204 ambi_decode 2 2 5 0; +#X text 291 199 2.arg: dimension; +#X text 440 199 (2 or 3); +#X text 291 211 3.arg: number of real loudspeakers; +#X text 305 222 (best results \, if n_ls = n_ambi_channels); +#X text 316 232 (could be more or less); +#X text 292 243 4.arg: number of phantom_loudspeakers; +#X text 334 254 (optional \, default 0); +#X msg 46 116 pinv; +#X obj 59 90 t b b; +#X obj 59 46 bng 35 250 50 0 empty empty empty 0 -6 0 8 -24198 -42246 +-1; +#X text 34 334 input: index + phi [degree] .. 2-dimensional; +#X text 34 344 input: index + delta + phi [degree] .. 3-dimensional +; +#X text 34 358 input: index + phi [degree .. 2-dimensional; +#X text 34 369 input: index + delta + phi [degree] .. 3-dimensional +; +#X text 63 525 n_col = (2*n_ao+1) = number of ambisonic-channels +; +#X text 51 534 + n_row = (n_ls) = number of loudspeakers; +#X text 286 311 number of loudspeakers = n_ls; +#X text 51 594 + n_row = (n_ls) = number of loudspeakers; +#X text 36 575 output in case of 3d: ((n_ao+1)*(n_ao+1)*n_ls+2) +; +#X text 37 514 output in case of 2d: ((2*n_ao+1)*n_ls+2); +#X text 384 575 :; +#X text 341 513 :; +#X text 281 585 number of ambisonic-channels; +#X text 63 585 n_col = (n_ao+1)*(n_ao+1) =; +#X text 252 604 elements of a matrix; +#X text 51 604 + (n_ao + 1) * (n_ao + 1) * n_ls; +#X text 51 544 + (2*n_ao + 1) * n_ls elements of a matrix; +#X text 34 458 input: calculates the pseudo-inverse of the encoded +; +#X text 90 469 loudspeaker-positions (+ the phantom-speakers); +#X text 104 480 and output a matrix-message; +#X text 306 189 (1 .. 5 for 3 dimensional use); +#X msg 95 116 ls 1 0 \, ls 2 72 \, ls 3 144 \, ls 4 216 \, ls 5 288 +; +#X text 113 405 1 <= index <= n_ao; +#X text 340 275 a regular matrix to inverse it); +#X text 437 384 to suppress the side-lobe-phenomena; +#X text 308 265 (it is sometimes necessary to add phantom-ls. for achieving +; +#N canvas 0 0 812 677 phantom_example 0; +#X obj 57 631 print; +#X obj 57 608 round_zero 1e-006; +#X msg 57 94 pinv; +#X obj 70 24 bng 35 250 50 0 empty empty empty 0 -6 0 8 -24198 -42246 +-1; +#X msg 198 72 ls 1 5 \, ls 2 2.5 \, ls 3 0 \, ls 4 -2.5 \, ls 5 -5 +; +#X msg 92 176 phls 5 -17.5 \, phls 6 -20 \, phls 7 -22.5 \, phls 8 +-25; +#X msg 92 200 phls 9 -27.5 \, phls 10 -30 \, phls 11 -32.5 \, phls +12 -35; +#X msg 92 223 phls 13 -37.5 \, phls 14 -40 \, phls 15 -42.5 \, phls +16 -45; +#X msg 92 247 phls 17 -47.5 \, phls 18 -50 \, phls 19 -52.5 \, phls +20 -55; +#X msg 92 270 phls 21 -57.5 \, phls 22 -60 \, phls 23 -62.5 \, phls +24 -65; +#X msg 92 294 phls 25 -67.5 \, phls 26 -70 \, phls 27 -72.5 \, phls +28 -75; +#X msg 92 317 phls 29 -77.5 \, phls 30 -80 \, phls 31 -82.5 \, phls +32 -85; +#X msg 92 340 phls 33 -87.5 \, phls 34 -90 \, phls 35 -92.5 \, phls +36 -95; +#X msg 92 364 phls 37 -97.5 \, phls 38 -100 \, phls 39 -102.5 \, phls +40 -105; +#X msg 92 387 phls 41 -107.5 \, phls 42 -110 \, phls 43 -112.5 \, phls +44 -115; +#X msg 92 411 phls 45 -117.5 \, phls 46 -120 \, phls 47 -122.5 \, phls +48 -125; +#X msg 92 434 phls 49 -127.5 \, phls 50 -130 \, phls 51 -132.5 \, phls +52 -135; +#X msg 92 456 phls 53 -137.5 \, phls 54 -140 \, phls 55 -142.5 \, phls +56 -145; +#X msg 92 480 phls 57 -147.5 \, phls 58 -150 \, phls 59 -152.5 \, phls +60 -155; +#X msg 92 503 phls 61 -157.5 \, phls 62 -160 \, phls 63 -162.5 \, phls +64 -165; +#X msg 92 527 phls 65 -167.5 \, phls 66 -170 \, phls 67 -172.5 \, phls +68 -175; +#X msg 92 550 phls 69 -177.5 \, phls 70 -180 \, phls 71 177.5 \, phls +72 175; +#X msg 497 228 phls 73 172.5 \, phls 74 170 \, phls 75 167.5 \, phls +76 165; +#X msg 497 249 phls 77 162.5 \, phls 78 160 \, phls 79 157.5 \, phls +80 155; +#X msg 497 270 phls 81 152.5 \, phls 82 150 \, phls 83 147.5 \, phls +84 145; +#X msg 497 290 phls 85 142.5 \, phls 86 140 \, phls 87 137.5 \, phls +88 135; +#X msg 497 312 phls 89 132.5 \, phls 90 130 \, phls 91 127.5 \, phls +92 125; +#X msg 497 333 phls 93 122.5 \, phls 94 120 \, phls 95 117.5 \, phls +96 115; +#X msg 497 354 phls 97 112.5 \, phls 98 110 \, phls 99 107.5 \, phls +100 105; +#X msg 497 375 phls 101 102.5 \, phls 102 100 \, phls 103 97.5 \, phls +104 95; +#X msg 497 396 phls 105 92.5 \, phls 106 90 \, phls 107 87.5 \, phls +108 85; +#X msg 497 418 phls 109 82.5 \, phls 110 80 \, phls 111 77.5 \, phls +112 75; +#X msg 497 439 phls 113 72.5 \, phls 114 70 \, phls 115 67.5 \, phls +116 65; +#X msg 497 460 phls 117 62.5 \, phls 118 60 \, phls 119 57.5 \, phls +120 55; +#X msg 497 481 phls 121 52.5 \, phls 122 50 \, phls 123 47.5 \, phls +124 45; +#X msg 497 502 phls 125 42.5 \, phls 126 40 \, phls 127 37.5 \, phls +128 35; +#X msg 497 524 phls 129 32.5 \, phls 130 30 \, phls 131 27.5 \, phls +132 25; +#X msg 497 545 phls 133 22.5 \, phls 134 20 \, phls 135 17.5 \, phls +136 15; +#X msg 497 566 phls 137 12.5 \, phls 138 10 \, phls 139 7.5; +#X obj 70 68 t b b b b; +#X obj 92 127 t b; +#X obj 497 206 t b; +#X obj 57 586 ambi_decode 2 2 5 139; +#X msg 92 152 phls 1 -7.5 \, phls 2 -10 \, phls 3 -12.5 \, phls 4 -15 +; +#X connect 1 0 0 0; +#X connect 2 0 42 0; +#X connect 3 0 39 0; +#X connect 4 0 42 0; +#X connect 5 0 42 0; +#X connect 6 0 42 0; +#X connect 7 0 42 0; +#X connect 8 0 42 0; +#X connect 9 0 42 0; +#X connect 10 0 42 0; +#X connect 11 0 42 0; +#X connect 12 0 42 0; +#X connect 13 0 42 0; +#X connect 14 0 42 0; +#X connect 15 0 42 0; +#X connect 16 0 42 0; +#X connect 17 0 42 0; +#X connect 18 0 42 0; +#X connect 19 0 42 0; +#X connect 20 0 42 0; +#X connect 21 0 42 0; +#X connect 22 0 42 0; +#X connect 23 0 42 0; +#X connect 24 0 42 0; +#X connect 25 0 42 0; +#X connect 26 0 42 0; +#X connect 27 0 42 0; +#X connect 28 0 42 0; +#X connect 29 0 42 0; +#X connect 30 0 42 0; +#X connect 31 0 42 0; +#X connect 32 0 42 0; +#X connect 33 0 42 0; +#X connect 34 0 42 0; +#X connect 35 0 42 0; +#X connect 36 0 42 0; +#X connect 37 0 42 0; +#X connect 38 0 42 0; +#X connect 39 0 2 0; +#X connect 39 1 41 0; +#X connect 39 2 40 0; +#X connect 39 3 4 0; +#X connect 40 0 43 0; +#X connect 40 0 5 0; +#X connect 40 0 6 0; +#X connect 40 0 7 0; +#X connect 40 0 8 0; +#X connect 40 0 9 0; +#X connect 40 0 10 0; +#X connect 40 0 11 0; +#X connect 40 0 12 0; +#X connect 40 0 13 0; +#X connect 40 0 14 0; +#X connect 40 0 15 0; +#X connect 40 0 16 0; +#X connect 40 0 17 0; +#X connect 40 0 18 0; +#X connect 40 0 19 0; +#X connect 40 0 20 0; +#X connect 40 0 21 0; +#X connect 41 0 22 0; +#X connect 41 0 23 0; +#X connect 41 0 24 0; +#X connect 41 0 25 0; +#X connect 41 0 26 0; +#X connect 41 0 27 0; +#X connect 41 0 28 0; +#X connect 41 0 29 0; +#X connect 41 0 30 0; +#X connect 41 0 31 0; +#X connect 41 0 32 0; +#X connect 41 0 33 0; +#X connect 41 0 34 0; +#X connect 41 0 35 0; +#X connect 41 0 36 0; +#X connect 41 0 37 0; +#X connect 41 0 38 0; +#X connect 42 0 1 0; +#X connect 43 0 42 0; +#X restore 421 117 pd phantom_example regular; +#N canvas 0 0 814 679 real_example 0; +#X obj 58 293 print; +#X obj 58 270 round_zero 1e-006; +#X msg 57 94 pinv; +#X obj 70 24 bng 35 250 50 0 empty empty empty 0 -6 0 8 -24198 -42246 +-1; +#X msg 103 115 ls 1 5 \, ls 2 2.5 \, ls 3 0 \, ls 4 -2.5 \, ls 5 -5 +; +#X obj 70 68 t b b; +#X obj 58 248 ambi_decode 2 2 5 0; +#X connect 1 0 0 0; +#X connect 2 0 6 0; +#X connect 3 0 5 0; +#X connect 4 0 6 0; +#X connect 5 0 2 0; +#X connect 5 1 4 0; +#X connect 6 0 1 0; +#X restore 421 90 pd real_example singular; +#X connect 3 0 0 0; +#X connect 5 0 13 0; +#X connect 6 0 13 0; +#X connect 13 0 3 0; +#X connect 21 0 13 0; +#X connect 22 0 21 0; +#X connect 22 1 45 0; +#X connect 23 0 22 0; +#X connect 45 0 13 0; diff --git a/help/help-ambi_decode2.pd b/help/help-ambi_decode2.pd new file mode 100644 index 0000000..c1c998b --- /dev/null +++ b/help/help-ambi_decode2.pd @@ -0,0 +1,97 @@ +#N canvas 82 3 844 643 10; +#X obj 38 441 print; +#X text 454 156 1.arg: ambisonic order; +#X obj 38 418 round_zero 1e-006; +#X text 297 312 ambisonic-order = n_ao; +#X text 485 387 ambisonic-order-group; +#X text 273 428 -90 <= delta <= +90; +#X text 273 440 -180 <= phi <= +180; +#X text 214 387 input: one mul-factor for each; +#X text 21 12 ambi_decode; +#X text 105 12 calculates a decoder-matrix; +#X obj 38 33 bng 35 250 50 0 empty empty empty 0 -6 0 8 -24198 -42246 +-1; +#X text 214 336 input: index + phi [degree] .. 2-dimensional; +#X text 214 346 input: index + delta + phi [degree] .. 3-dimensional +; +#X text 214 360 input: index + phi [degree .. 2-dimensional +; +#X text 214 371 input: index + delta + phi [degree] .. 3-dimensional +; +#X text 238 518 n_col = (2*n_ao+1) = number of ambisonic-channels +; +#X text 226 527 + n_row = (n_ls) = number of loudspeakers; +#X text 466 313 number of loudspeakers = n_ls; +#X text 229 587 + n_row = (n_ls) = number of loudspeakers; +#X text 214 568 output in case of 3d: ((n_ao+1)*(n_ao+1)*n_ls+2) +; +#X text 212 507 output in case of 2d: ((2*n_ao+1)*n_ls+2) +; +#X text 559 568 :; +#X text 516 506 :; +#X text 456 578 number of ambisonic-channels; +#X text 241 578 n_col = (n_ao+1)*(n_ao+1) =; +#X text 427 597 elements of a matrix; +#X text 229 597 + (n_ao + 1) * (n_ao + 1) * n_ls; +#X text 226 537 + (2*n_ao + 1) * n_ls elements of a matrix +; +#X text 207 460 input: calculates the pseudo-inverse of the +encoded; +#X text 263 471 loudspeaker-positions (+ the phantom-speakers); +#X text 277 482 and output a matrix-message; +#X text 288 417 1 <= index <= n_ao; +#X text 544 268 a regular matrix to inverse it); +#X text 375 399 to suppress the side-lobe-phenomena; +#X text 467 258 (it is sometimes necessary to add phantom-ls. for achieving +; +#X msg 38 372 pseudo_inverse; +#X msg 234 128 ambi_weight 1 1 1 0.3904; +#X msg 108 129 ambi_weight 1 1 1 1; +#X msg 123 104 mirror_weight 0.7; +#X obj 94 178 pp ind_ls; +#X msg 94 155 1 90 0 \, 2 45 45 \, 3 45 135 \, 4 45 225 \, 5 45 315 +; +#X obj 38 396 ambi_decode2 3 3 5 8 1; +#X obj 80 243 pp mrg_ls; +#X msg 80 208 1 0 0 \, 2 0 45 \, 3 0 90 \, 4 0 135 \, 5 0 180 \, 6 +0 225 \, 7 0 270 \, 8 0 315; +#X obj 66 300 pp mir_ls; +#X msg 66 265 1 -45 0 \, 2 -45 45 \, 3 -45 90 \, 4 -45 135 \, 5 -45 +180 \, 6 -45 225 \, 7 -45 270 \, 8 -45 315; +#X obj 52 346 pp pht_ls; +#X msg 52 323 1 -90 0; +#X obj 38 77 t b b b b b b b; +#X text 469 174 (1 .. 5 in case of 3 dimensional); +#X text 469 165 (1 .. 12 in case of 2 dimensional); +#X text 455 196 3.arg: number of independent loudspeakers; +#X text 454 184 2.arg: dimension (2 or 3); +#X text 454 247 5.arg: number of canceled phantom_loudspeakers +; +#X text 455 208 4.arg: number of merged and mirrored loudspeakers +; +#X text 501 221 (the merged loudspeakers are at the border of the arc +; +#X text 514 233 or the hemisphere \, the mirrored loudspeakers are +; +#X connect 2 0 0 0; +#X connect 10 0 48 0; +#X connect 35 0 41 0; +#X connect 36 0 41 0; +#X connect 37 0 41 0; +#X connect 38 0 41 0; +#X connect 39 0 41 0; +#X connect 40 0 39 0; +#X connect 41 0 2 0; +#X connect 42 0 41 0; +#X connect 43 0 42 0; +#X connect 44 0 41 0; +#X connect 45 0 44 0; +#X connect 46 0 41 0; +#X connect 47 0 46 0; +#X connect 48 0 35 0; +#X connect 48 1 47 0; +#X connect 48 2 45 0; +#X connect 48 3 43 0; +#X connect 48 4 40 0; +#X connect 48 5 37 0; +#X connect 48 6 38 0; diff --git a/help/help-ambi_decode3.pd b/help/help-ambi_decode3.pd new file mode 100644 index 0000000..acc1c6d --- /dev/null +++ b/help/help-ambi_decode3.pd @@ -0,0 +1,150 @@ +#N canvas 4 4 856 655 10; +#X obj 60 572 print; +#X text 513 156 1.arg: ambisonic order; +#X obj 60 549 round_zero 1e-006; +#X text 348 312 ambisonic-order = n_ao; +#X text 536 387 ambisonic-order-group; +#X text 324 428 -90 <= delta <= +90; +#X text 324 440 -180 <= phi <= +180; +#X text 265 387 input: one mul-factor for each; +#X text 21 12 ambi_decode; +#X text 105 12 calculates a decoder-matrix; +#X obj 38 33 bng 35 250 50 0 empty empty empty 0 -6 0 8 -24198 -42246 +-1; +#X text 265 336 input: index + phi [degree] .. 2-dimensional; +#X text 265 346 input: index + delta + phi [degree] .. 3-dimensional +; +#X text 265 360 input: index + phi [degree .. 2-dimensional +; +#X text 265 371 input: index + delta + phi [degree] .. 3-dimensional +; +#X text 289 518 n_col = (2*n_ao+1) = number of ambisonic-channels +; +#X text 277 527 + n_row = (n_ls) = number of loudspeakers; +#X text 517 313 number of loudspeakers = n_ls; +#X text 280 587 + n_row = (n_ls) = number of loudspeakers; +#X text 265 568 output in case of 3d: ((n_ao+1)*(n_ao+1)*n_ls+2) +; +#X text 263 507 output in case of 2d: ((2*n_ao+1)*n_ls+2) +; +#X text 610 568 :; +#X text 567 506 :; +#X text 507 578 number of ambisonic-channels; +#X text 292 578 n_col = (n_ao+1)*(n_ao+1) =; +#X text 478 597 elements of a matrix; +#X text 280 597 + (n_ao + 1) * (n_ao + 1) * n_ls; +#X text 277 537 + (2*n_ao + 1) * n_ls elements of a matrix +; +#X text 258 460 input: calculates the pseudo-inverse of the +encoded; +#X text 314 471 loudspeaker-positions (+ the phantom-speakers); +#X text 328 482 and output a matrix-message; +#X text 339 417 1 <= index <= n_ao; +#X text 603 268 a regular matrix to inverse it); +#X text 426 399 to suppress the side-lobe-phenomena; +#X text 526 258 (it is sometimes necessary to add phantom-ls. for achieving +; +#X msg 272 130 ambi_weight 1 1 1 0.3904; +#X msg 123 129 ambi_weight 1 1 1 1; +#X msg 138 106 mirror_weight 0.7; +#X obj 94 237 pp pht_ls; +#X obj 38 77 t b b b b b b b; +#X text 528 174 (1 .. 5 in case of 3 dimensional); +#X text 528 165 (1 .. 12 in case of 2 dimensional); +#X text 514 196 3.arg: number of independent loudspeakers; +#X text 513 184 2.arg: dimension (2 or 3); +#X text 513 247 5.arg: number of canceled phantom_loudspeakers +; +#X text 514 208 4.arg: number of merged and mirrored loudspeakers +; +#X text 560 221 (the merged loudspeakers are at the border of the arc +; +#X text 573 233 or the hemisphere \, the mirrored loudspeakers are +; +#X obj 742 385 pp ind_ls; +#X msg 742 362 1 90 0 \, 2 45 45 \, 3 45 135 \, 4 45 225 \, 5 45 315 +; +#X obj 728 450 pp mrg_ls; +#X msg 728 415 1 0 0 \, 2 0 45 \, 3 0 90 \, 4 0 135 \, 5 0 180 \, 6 +0 225 \, 7 0 270 \, 8 0 315; +#X obj 714 507 pp mir_ls; +#X msg 714 472 1 -45 0 \, 2 -45 45 \, 3 -45 90 \, 4 -45 135 \, 5 -45 +180 \, 6 -45 225 \, 7 -45 270 \, 8 -45 315; +#X obj 700 553 pp pht_ls; +#X msg 700 530 1 -90 0; +#X msg 108 155 1 90 0 \, 2 45 45 \, 3 45 135 \, 4 45 225 \, 5 45 315 +\, 6 0 0 \, 7 0 45 \, 8 0 90 \, 9 0 135 \, 10 0 180 \, 11 0 225 \, +12 0 270 \, 13 0 315; +#X obj 108 190 pp real_ls; +#X msg 80 263 begin_pseudo_inverse; +#X obj 60 527 ambi_decode3 3 3 13 6; +#X msg 30 501 end_pseudo_inverse; +#X msg 94 215 1 -45 0 \, 2 -45 90 \, 3 -45 180 \, 4 -45 270 \, 6 -90 +0; +#X msg 47 476 ipht_ireal_muladd \$1 \$2 \$3; +#N canvas 337 146 559 509 /SUBPATCH/ 0; +#X msg 142 186 1 6 \$1; +#X obj 102 58 inlet; +#X obj 101 441 outlet; +#X obj 162 59 inlet; +#X obj 71 135 f; +#X obj 103 135 f; +#X obj 157 106 * 0.25; +#X obj 214 106 * 0.5; +#X msg 163 211 2 8 \$1; +#X msg 40 187 1 13 \$1 \, 1 7 \$1; +#X msg 61 212 2 7 \$1 \, 2 9 \$1; +#X msg 179 241 3 10 \$1; +#X msg 77 242 3 9 \$1 \, 3 11 \$1; +#X msg 199 271 4 12 \$1; +#X msg 87 271 4 11 \$1 \, 4 13 \$1; +#X obj 162 81 route mirror_weight; +#X connect 0 0 2 0; +#X connect 1 0 4 0; +#X connect 1 0 5 0; +#X connect 3 0 15 0; +#X connect 4 0 9 0; +#X connect 4 0 10 0; +#X connect 4 0 12 0; +#X connect 4 0 14 0; +#X connect 5 0 0 0; +#X connect 5 0 8 0; +#X connect 5 0 11 0; +#X connect 5 0 13 0; +#X connect 6 0 4 1; +#X connect 7 0 5 1; +#X connect 8 0 2 0; +#X connect 9 0 2 0; +#X connect 10 0 2 0; +#X connect 11 0 2 0; +#X connect 12 0 2 0; +#X connect 13 0 2 0; +#X connect 14 0 2 0; +#X connect 15 0 7 0; +#X connect 15 0 6 0; +#X restore 47 436 pd; +#X connect 2 0 0 0; +#X connect 10 0 39 0; +#X connect 35 0 59 0; +#X connect 36 0 59 0; +#X connect 37 0 63 1; +#X connect 38 0 59 0; +#X connect 39 0 60 0; +#X connect 39 1 63 0; +#X connect 39 2 58 0; +#X connect 39 3 61 0; +#X connect 39 4 56 0; +#X connect 39 5 36 0; +#X connect 39 6 37 0; +#X connect 49 0 48 0; +#X connect 51 0 50 0; +#X connect 53 0 52 0; +#X connect 55 0 54 0; +#X connect 56 0 57 0; +#X connect 57 0 59 0; +#X connect 58 0 59 0; +#X connect 59 0 2 0; +#X connect 60 0 59 0; +#X connect 61 0 38 0; +#X connect 62 0 59 0; +#X connect 63 0 62 0; diff --git a/help/help-ambi_encode.pd b/help/help-ambi_encode.pd new file mode 100644 index 0000000..b5e1632 --- /dev/null +++ b/help/help-ambi_encode.pd @@ -0,0 +1,283 @@ +#N canvas 61 48 860 672 10; +#X obj 374 243 ambi_encode 2; +#X obj 374 288 print; +#X text 478 247 1.arg: ambisonic order; +#X text 489 259 (1 .. 12 for 2 dimensional use); +#X msg 461 178 col 2 \$1; +#X msg 425 97 row 1 \$1; +#X msg 288 211 col 3 \$1 \$2; +#X obj 288 188 pack 0 0; +#X obj 306 166 t b f; +#X obj 374 265 round_zero 1e-006; +#X obj 184 193 pack 0 0; +#X obj 202 171 t b f; +#X floatatom 100 161 5 -180 180 0 - - -; +#X floatatom 51 162 5 -90 90 0 - - -; +#X obj 82 222 pack 0 0; +#X obj 100 200 t b f; +#X text 48 143 delta; +#X text 102 142 phi; +#X text 21 12 ambi_encode; +#X text 34 291 ambisonic-order = n_ao; +#X text 346 320 -> output: of (2*n_ao+1) ; +#X text 346 331 -> output: of (n_ao+1)*(n_ao+1) ; +#X text 387 356 -> output: + index + (2*n_ao+1) ; +#X text 387 368 -> output: + index + (n_ao+1)*(n_ao+1) +; +#X text 383 394 -> output: + index + (2*n_ao+1) ; +#X text 383 406 -> output: + index + (n_ao+1)*(n_ao+1) +; +#X text 432 424 for crossfading of 2 ambisonic-systems; +#X msg 605 183 ambi_weight 1 1 1; +#X msg 588 162 ambi_weight 1 1 0.3904; +#X text 299 424 ambisonic-order-group; +#X text 89 452 -90 <= delta <= +90; +#X text 89 464 -180 <= phi <= +180; +#X text 415 439 or for bluring a signal-source-direction; +#X text 31 506 order of ambisonic-channels in 2d-case: W X1 Y1 X2 Y2 +X3 Y3; +#X text 391 506 X4 Y4 X5 Y5 ....; +#X text 167 520 W := 1 \, X-term ... cos(i*phi) \, Y-term ... sin(i*phi) +; +#X text 30 560 order of ambisonic-channels in 3d-case: W Z1X1 Z1Y1 +Z1; +#X text 358 560 Z2X2 Z2Y2 Z2X1 Z2Y1 Z2 Z3X3 Z3Y3 Z3X2 Z3Y2 Z3X1 Z3Y1 +Z3 ...; +#X text 166 574 W := 1 \, X-term ... cos(i*phi) \, Y-term ... sin(i*phi) +\,; +#X text 489 574 Z-term ... cos(j*delta)*sin(k*delta); +#X text 33 318 input: phi [degree] .. 2-dimensional; +#X text 33 331 input: delta + phi [degree] .. 3-dimensional +; +#X text 33 356 input: index + phi [degree] .. 2-dimensional; +#X text 34 368 input: index + delta + phi [degree] .. 3-dimensional +; +#X text 31 395 input: index + phi [degree .. 2-dimensional; +#X text 31 407 input: index + delta + phi [degree] .. 3-dimensional +; +#X text 31 424 input: one mul-factor for each; +#X text 267 492 |0| 1 | 2 | 3 | 4 | 5 |; +#X text 687 549 |; +#X text 263 547 |0| 1 | 2 | 3; +#X floatatom 226 142 5 -180 180 0 - - -; +#X floatatom 177 143 5 -90 90 0 - - -; +#X text 174 124 delta; +#X text 228 123 phi; +#X floatatom 327 139 5 -180 180 0 - - -; +#X floatatom 278 140 5 -90 90 0 - - -; +#X text 275 121 delta; +#X text 329 120 phi; +#X floatatom 370 65 5 -180 180 0 - - -; +#X text 372 46 phi; +#X floatatom 425 79 5 -180 180 0 - - -; +#X text 427 60 phi; +#X floatatom 461 160 5 -180 180 0 - - -; +#X text 463 141 phi; +#X text 491 272 (1 .. 5 for 3 dimensional use); +#X msg 184 218 row 4 \$1 \$2; +#X text 112 12 calculates a row or column of a ambisonic-encoder-matrix +; +#X text 82 849 "float"-message: azimuth-angle phi [degree] +-> two-dimensional ambisonic-system -> output a of (2*n_ao + +1) elements; +#X text 478 850 "list"-message: 1.item elevation-angle delta +[degree] \, 2.item azimuth-angle phi [degree] -> three-dimensional +ambisonic-system -> output a of (n_ao + 1)^2 elements +; +#X text 87 914 "row"-message: row-index of ambisonic-encoder-matrix +\, azimuth-angle phi [degree] -> two-dimensional ambisonic-system +-> output a "row"-message + row-index + (2*n_ao + 1) +elements; +#X text 480 919 "row"-message: 1.item elevation-angle delta +[degree] \, 2.item azimuth-angle phi [degree] -> three-dimensional +ambisonic-system -> output a of (n_ao + 1)^2 elements +; +#X text 105 441 1 <= index <= nr_sources; +#N canvas 0 0 860 478 3D-5.Order-example 0; +#X obj 78 97 pack 0 0; +#X floatatom 78 55 5 -90 90 0 - - -; +#X floatatom 121 56 5 -180 180 0 - - -; +#X text 63 24 delta; +#X text 44 38 -90 .. +90; +#X text 147 26 phi; +#X text 120 40 -180 .. +180; +#X obj 96 76 t b f; +#X obj 97 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 9439 1; +#X obj 107 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 6442 1; +#X obj 117 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 3208 1; +#X obj 127 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 137 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 147 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 157 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 167 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 177 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 187 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 197 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 207 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 217 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 227 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 237 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 247 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 257 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 267 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 277 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 287 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 297 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 307 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 317 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 327 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 87 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 10000 1; +#X obj 422 89 ambi_encode 4; +#X floatatom 422 68 5 -180 180 0 - - -; +#X text 434 31 phi; +#X text 407 45 -180 .. +180; +#X obj 142 202 print 3d; +#X obj 422 132 print 2d; +#X obj 78 201 route row; +#X obj 142 180 round_zero 1e-006; +#X floatatom 42 244 5 0 0 0 - - -; +#X obj 78 124 pp row 7; +#X text 13 254 row-index; +#X obj 422 111 round_zero 1e-006; +#X text 448 260 +1; +#X text 448 360 -1; +#X text 451 311 0; +#X obj 78 151 ambi_encode 5; +#X obj 78 222 unpack 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0; +#X obj 337 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 347 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 357 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 367 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 377 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 387 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 397 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 407 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 417 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 427 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X obj 437 268 vsl 8 101 -1 1 0 0 empty empty empty 0 -8 0 8 -225280 +-1109 -1 5000 1; +#X msg 260 57 ambi_weight 1 1 1 1 1 1; +#X msg 260 95 ambi_weight 1 1 1 1 0 0; +#X msg 260 114 ambi_weight 1 1 1 0 0 0; +#X msg 260 134 ambi_weight 1 1 0 0 0 0; +#X msg 260 154 ambi_weight 1 0 0 0 0 0; +#X msg 260 76 ambi_weight 1 1 1 1 1 0; +#X connect 0 0 42 0; +#X connect 1 0 0 0; +#X connect 2 0 7 0; +#X connect 7 0 0 0; +#X connect 7 1 0 1; +#X connect 33 0 44 0; +#X connect 34 0 33 0; +#X connect 39 0 49 0; +#X connect 40 0 37 0; +#X connect 42 0 48 0; +#X connect 44 0 38 0; +#X connect 48 0 39 0; +#X connect 48 0 40 0; +#X connect 49 0 41 0; +#X connect 49 1 32 0; +#X connect 49 2 8 0; +#X connect 49 3 9 0; +#X connect 49 4 10 0; +#X connect 49 5 11 0; +#X connect 49 6 12 0; +#X connect 49 7 13 0; +#X connect 49 8 14 0; +#X connect 49 9 15 0; +#X connect 49 10 16 0; +#X connect 49 11 17 0; +#X connect 49 12 18 0; +#X connect 49 13 19 0; +#X connect 49 14 20 0; +#X connect 49 15 21 0; +#X connect 49 16 22 0; +#X connect 49 17 23 0; +#X connect 49 18 24 0; +#X connect 49 19 25 0; +#X connect 49 20 26 0; +#X connect 49 21 27 0; +#X connect 49 22 28 0; +#X connect 49 23 29 0; +#X connect 49 24 30 0; +#X connect 49 25 31 0; +#X connect 49 26 50 0; +#X connect 49 27 51 0; +#X connect 49 28 52 0; +#X connect 49 29 53 0; +#X connect 49 30 54 0; +#X connect 49 31 55 0; +#X connect 49 32 56 0; +#X connect 49 33 57 0; +#X connect 49 34 58 0; +#X connect 49 35 59 0; +#X connect 49 36 60 0; +#X connect 61 0 48 0; +#X connect 62 0 48 0; +#X connect 63 0 48 0; +#X connect 64 0 48 0; +#X connect 65 0 48 0; +#X connect 66 0 48 0; +#X restore 538 61 pd 3D-5.Order-example; +#X connect 0 0 9 0; +#X connect 4 0 0 0; +#X connect 5 0 0 0; +#X connect 6 0 0 0; +#X connect 7 0 6 0; +#X connect 8 0 7 0; +#X connect 8 1 7 1; +#X connect 9 0 1 0; +#X connect 10 0 65 0; +#X connect 11 0 10 0; +#X connect 11 1 10 1; +#X connect 12 0 15 0; +#X connect 13 0 14 0; +#X connect 14 0 0 0; +#X connect 15 0 14 0; +#X connect 15 1 14 1; +#X connect 27 0 0 0; +#X connect 28 0 0 0; +#X connect 50 0 11 0; +#X connect 51 0 10 0; +#X connect 54 0 8 0; +#X connect 55 0 7 0; +#X connect 58 0 0 0; +#X connect 60 0 5 0; +#X connect 62 0 4 0; +#X connect 65 0 0 0; diff --git a/help/help-ambi_rot.pd b/help/help-ambi_rot.pd new file mode 100644 index 0000000..1d3baae --- /dev/null +++ b/help/help-ambi_rot.pd @@ -0,0 +1,80 @@ +#N canvas 44 25 730 500 10; +#X text 230 40 phi ... azimut \, positiv direction from nose to left +ear; +#X text 228 18 delta ... elevation \, positiv direction from nose to +top of the head; +#X floatatom 52 76 6 -180 180 0 - - -; +#X obj 29 76 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X floatatom 128 76 6 -180 180 0 - - -; +#X text 129 59 rho_y; +#X text 54 59 rho_z; +#X floatatom 195 76 6 -180 180 0 - - -; +#X text 197 59 rho_x; +#X obj 127 149 pack 0 0 0; +#X obj 195 120 t b f; +#X obj 128 120 t b f; +#X obj 52 93 deg2rad; +#X obj 128 94 deg2rad; +#X obj 195 95 deg2rad; +#X text 241 6 AMBISONIC Encoder 4.Order 3-Dimensional; +#X text 254 73 umkehrung der matrizen multiplikation: funktioniert +nicht; +#X obj 63 393 print r1; +#X obj 174 390 print r2; +#X obj 292 389 print r3; +#X obj 407 387 print r4; +#X obj 63 342 mtx_mul; +#X obj 389 275 pack 0 0 0; +#X obj 389 214 unpack 0 0 0; +#X obj 389 237 * -1; +#X obj 126 172 t l l; +#X obj 174 341 mtx_mul; +#X obj 292 339 mtx_mul; +#X obj 407 338 mtx_mul; +#X obj 422 238 * -1; +#X obj 455 237 * -1; +#X obj 389 300 ambi_rot 4; +#X obj 63 244 ambi_rot 4; +#X text 10 8 ambi_rot; +#X obj 407 362 round_zero 0.0001; +#X obj 292 365 round_zero 0.0001; +#X obj 174 364 round_zero 0.0001; +#X obj 63 365 round_zero 0.0001; +#X connect 2 0 12 0; +#X connect 3 0 2 0; +#X connect 4 0 13 0; +#X connect 7 0 14 0; +#X connect 9 0 25 0; +#X connect 10 0 9 0; +#X connect 10 1 9 2; +#X connect 11 0 9 0; +#X connect 11 1 9 1; +#X connect 12 0 9 0; +#X connect 13 0 11 0; +#X connect 14 0 10 0; +#X connect 21 0 37 0; +#X connect 22 0 31 0; +#X connect 23 0 24 0; +#X connect 23 1 29 0; +#X connect 23 2 30 0; +#X connect 24 0 22 0; +#X connect 25 0 32 0; +#X connect 25 1 23 0; +#X connect 26 0 36 0; +#X connect 27 0 35 0; +#X connect 28 0 34 0; +#X connect 29 0 22 1; +#X connect 30 0 22 2; +#X connect 31 0 21 1; +#X connect 31 1 26 1; +#X connect 31 2 27 1; +#X connect 31 3 28 1; +#X connect 32 0 21 0; +#X connect 32 1 26 0; +#X connect 32 2 27 0; +#X connect 32 3 28 0; +#X connect 34 0 20 0; +#X connect 35 0 19 0; +#X connect 36 0 18 0; +#X connect 37 0 17 0; diff --git a/help/test-ambi_rot.pd b/help/test-ambi_rot.pd new file mode 100644 index 0000000..e859374 --- /dev/null +++ b/help/test-ambi_rot.pd @@ -0,0 +1,80 @@ +#N canvas 44 25 726 496 10; +#X text 230 40 phi ... azimut \, positiv direction from nose to left +ear; +#X text 228 18 delta ... elevation \, positiv direction from nose to +top of the head; +#X floatatom 52 76 6 -180 180 0 - - -; +#X obj 29 76 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X floatatom 128 76 6 -180 180 0 - - -; +#X text 129 59 rho_y; +#X text 54 59 rho_z; +#X floatatom 195 76 6 -180 180 0 - - -; +#X text 197 59 rho_x; +#X obj 127 149 pack 0 0 0; +#X obj 195 120 t b f; +#X obj 128 120 t b f; +#X obj 52 93 deg2rad; +#X obj 128 94 deg2rad; +#X obj 195 95 deg2rad; +#X text 241 6 AMBISONIC Encoder 4.Order 3-Dimensional; +#X text 254 73 umkehrung der matrizen multiplikation: funktioniert +nicht; +#X obj 63 393 print r1; +#X obj 174 390 print r2; +#X obj 292 389 print r3; +#X obj 407 387 print r4; +#X text 10 8 test-ambi_rot.pd; +#X obj 63 342 mtx_mul; +#X obj 389 275 pack 0 0 0; +#X obj 389 214 unpack 0 0 0; +#X obj 389 237 * -1; +#X obj 126 172 t l l; +#X obj 174 341 mtx_mul; +#X obj 292 339 mtx_mul; +#X obj 407 338 mtx_mul; +#X obj 422 238 * -1; +#X obj 455 237 * -1; +#X obj 389 300 ambi_rot 4; +#X obj 63 244 ambi_rot 4; +#X obj 63 365 round_zero 1e-007; +#X obj 174 364 round_zero 1e-007; +#X obj 292 365 round_zero 1e-007; +#X obj 407 362 round_zero 1e-007; +#X connect 2 0 12 0; +#X connect 3 0 2 0; +#X connect 4 0 13 0; +#X connect 7 0 14 0; +#X connect 9 0 26 0; +#X connect 10 0 9 0; +#X connect 10 1 9 2; +#X connect 11 0 9 0; +#X connect 11 1 9 1; +#X connect 12 0 9 0; +#X connect 13 0 11 0; +#X connect 14 0 10 0; +#X connect 22 0 34 0; +#X connect 23 0 32 0; +#X connect 24 0 25 0; +#X connect 24 1 30 0; +#X connect 24 2 31 0; +#X connect 25 0 23 0; +#X connect 26 0 33 0; +#X connect 26 1 24 0; +#X connect 27 0 35 0; +#X connect 28 0 36 0; +#X connect 29 0 37 0; +#X connect 30 0 23 1; +#X connect 31 0 23 2; +#X connect 32 0 22 1; +#X connect 32 1 27 1; +#X connect 32 2 28 1; +#X connect 32 3 29 1; +#X connect 33 0 22 0; +#X connect 33 1 27 0; +#X connect 33 2 28 0; +#X connect 33 3 29 0; +#X connect 34 0 17 0; +#X connect 35 0 18 0; +#X connect 36 0 19 0; +#X connect 37 0 20 0; diff --git a/src/Make.config.in b/src/Make.config.in new file mode 100644 index 0000000..8bba163 --- /dev/null +++ b/src/Make.config.in @@ -0,0 +1,28 @@ +LIBNAME =iem_bin_ambi + +PREFIX =@prefix@@PDLIBDIR@ + +INSTALL_BIN=$(PREFIX)/extra +INSTALL_DOC=$(PREFIX)/@REFERENCEPATH@$(LIBNAME) + +EXT = @EXT@ +DEFS = @DFLAGS@ +IFLAGS = -I. @INCLUDES@ + +CC = @CC@ +LD = @LD@ +STRIP = @STRIP@ +STRIPFLAGS= @STRIPFLAGS@ + +AFLAGS = +LFLAGS = @LFLAGS@ +WFLAGS = + +TARNAME = $(LIBNAME)-@IEMBINAMBI_VERSION@.tgz + +# ICCFLAGS=-march=pentiumiii -axK +Z_CFLAGS = $(IFLAGS) $(DEFS) -DPD $(WFLAGS) @CFLAGS@ $(CFLAGS) + +MAKEDEP_FLAGS = @MAKEDEP_FLAGS@ + +LIBS = @LIBS@ diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..8e18398 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,88 @@ +default: all + +.PHONEY: default all everything dist \ + clean realclean distclean \ + install install-bin install-doc install-abs + +SOURCES=$(sort $(filter %.c, $(wildcard *.c))) + +ifeq (,$(findstring clean, $(MAKECMDGOALS))) +Make.config: Make.config.in configure + ./configure +endif + +iem_bin_ambi_sources.c iem_bin_ambi_sources.h: + ./makesource.sh + +configure: configure.ac + autoconf + +## uaehh, here comes some magic +## 1st we don't want depend and config-makefiles to be included on "clean"-targets + +ifeq (,$(findstring clean, $(MAKECMDGOALS))) +-include $(SOURCES:.c=.d) +endif + +-include Make.config + +## 2nd only generate depend-files when we have Make.config included +## and thus MAKEDEP_FLAGS defined +ifdef MAKEDEP_FLAGS +## dependencies: as proposed by the GNU-make documentation +## see http://www.gnu.org/software/make/manual/html_node/make_47.html#SEC51 +%.d: %.c + @set -e; rm -f $@; \ + $(CPP) $(MAKEDEP_FLAGS) $(Z_CFLAGS) $< > $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ +endif + +.SUFFIXES: .$(EXT) + +TARGETS = $(SOURCES:.c=.o) + + +all: $(LIBNAME) + cp $(LIBNAME).$(EXT) .. + +$(LIBNAME): $(TARGETS) iem_bin_ambi_sources.c iem_bin_ambi_sources.h + $(LD) $(LFLAGS) -o $(LIBNAME).$(EXT) *.o $(LIBS) + $(STRIP) $(STRIPFLAGS) $(LIBNAME).$(EXT) + +$(TARGETS): %.o : %.c + $(CC) $(Z_CFLAGS) -c -o $@ $*.c + + +clean: + -rm -f *.$(EXT) *.o + +realclean: clean + -rm -f *~ _* config.* + -rm -f *.d *.d.* + +distclean: realclean + -rm -f Make.config ../*.$(EXT) + -rm -f *.exp *.lib *.ncb \ + *.opt *.plg + -rm -rf autom4te.cache/ + +install: install-bin install-doc install-abs + +install-bin: + -install -d $(INSTALL_BIN) + -install -m 644 $(LIBNAME).$(EXT) $(INSTALL_BIN) + +install-doc: + -install -d $(INSTALL_DOC) + -install -m 644 ../examples/*.pd $(INSTALL_DOC) + +install-abs: + -install -d $(INSTALL_BIN) + -install -m 644 ../abs/*.pd $(INSTALL_BIN) + +dist: all realclean + (cd ../..;tar czvf $(TARNAME) $(LIBNAME)) + +everything: clean all install distclean + diff --git a/src/ambi_decode.c b/src/ambi_decode.c new file mode 100644 index 0000000..db030cf --- /dev/null +++ b/src/ambi_decode.c @@ -0,0 +1,724 @@ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. + +iem_ambi written by Thomas Musil, Copyright (c) IEM KUG Graz Austria 2000 - 2005 */ + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + + +#include "m_pd.h" +#include "iemlib.h" +#include +#include +#include + + + +/* -------------------------- ambi_decode ------------------------------ */ +/* + ** berechnet ein reduziertes Ambisonic-Decoder-Set in die HRTF-Spektren ** + ** Inputs: ls + Liste von 3 floats: Index [1 .. 25] + Elevation [-90 .. +90 degree] + Azimut [0 .. 360 degree] ** + ** Inputs: calc_inv ** + ** Inputs: load_HRIR + float index1..25 ** + ** Outputs: List of 2 symbols: left-HRIR-File-name + HRIR-table-name ** + ** Inputs: calc_reduced ** + ** "output" ... writes the HRTF into tables ** + ** ** + ** ** + ** setzt voraus , dass die HRIR-tabele-names von LS1_L_HRIR .. LS25_L_HRIR heissen und existieren ** + ** setzt voraus , dass die HRTF-tabele-names von LS1_HRTF_re .. LS25_HRTF_re heissen und existieren ** + ** setzt voraus , dass die HRTF-tabele-names von LS1_HRTF_im .. LS25_HRTF_im heissen und existieren ** + */ + +typedef struct _ambi_decode +{ + t_object x_obj; + t_atom *x_at; + double *x_inv_work1; + double *x_inv_work2; + double *x_inv_buf2; + double *x_transp; + double *x_ls_encode; + double *x_prod; + double *x_ambi_channel_weight; + double x_sing_range; + int x_n_ambi; + int x_n_order; + int x_n_ls; + int x_n_phls; + int x_n_dim; + t_symbol *x_s_matrix; + double x_sqrt3; + double x_sqrt10_4; + double x_sqrt15_2; + double x_sqrt6_4; + double x_sqrt35_8; + double x_sqrt70_4; + double x_sqrt5_2; + double x_sqrt126_16; + double x_sqrt315_8; + double x_sqrt105_4; + double x_pi_over_180; +} t_ambi_decode; + +static t_class *ambi_decode_class; + +static void ambi_decode_copy_row2buf(t_ambi_decode *x, int row) +{ + int n_ambi2 = 2*x->x_n_ambi; + int i; + double *dw=x->x_inv_work2; + double *db=x->x_inv_buf2; + + dw += row*n_ambi2; + for(i=0; ix_n_ambi; + int i; + double *dw=x->x_inv_work2; + double *db=x->x_inv_buf2; + + dw += row*n_ambi2; + for(i=0; ix_n_ambi; + int i; + double *dw_src=x->x_inv_work2; + double *dw_dst=x->x_inv_work2; + + dw_src += src_row*n_ambi2; + dw_dst += dst_row*n_ambi2; + for(i=0; ix_n_ambi; + int i; + double *dw=x->x_inv_work2; + + dw += row*n_ambi2; + for(i=0; ix_n_ambi; + int i; + double *dw=x->x_inv_work2; + double *db=x->x_inv_buf2; + + dw += row*n_ambi2; + for(i=0; ix_n_ambi; + int n_ambi2 = 2*n_ambi; + int i, j; + double *dw=x->x_inv_work2; + double singrange=x->x_sing_range; + int ret=-1; + + dw += start_row*n_ambi2 + col; + j = 0; + for(i=start_row; i singrange) || (*dw < -singrange)) + { + ret = i; + i = n_ambi+1; + } + dw += n_ambi2; + } + return(ret); +} + +static void ambi_decode_mul1(t_ambi_decode *x) +{ + double *vec1, *beg1=x->x_ls_encode; + double *vec2, *beg2=x->x_ls_encode; + double *inv=x->x_inv_work1; + double sum; + int n_ls=x->x_n_ls+x->x_n_phls; + int n_ambi=x->x_n_ambi; + int i, j, k; + + for(k=0; kx_ls_encode; + for(j=0; jx_n_ls+x->x_n_phls; + int n_ambi=x->x_n_ambi; + int n_ambi2=2*n_ambi; + int i, j, k; + double *vec1, *beg1=x->x_transp; + double *vec2, *beg2=x->x_inv_work2+n_ambi; + double *vec3=x->x_prod; + double *acw_vec=x->x_ambi_channel_weight; + double sum; + + for(k=0; kx_inv_work2+n_ambi; + for(j=0; jx_transp; + double *straight=x->x_ls_encode; + int n_ls=x->x_n_ls+x->x_n_phls; + int n_ambi=x->x_n_ambi; + int i, j; + + for(j=0; jx_n_ambi; + int n_ambi2 = 2*n_ambi; + int i, j, nz; + int r,c; + double *src=x->x_inv_work1; + double *db=x->x_inv_work2; + double rcp, *dv; + + dv = db; + for(i=0; i=0; i--) + { + dv = db + i*n_ambi2 + i; + ambi_decode_copy_row2buf(x, i); + for(j=i-1; j>=0; j--) + { + dv -= n_ambi2; + rcp = -(*dv); + ambi_decode_mul_buf_and_add2row(x, j, rcp); + } + } + + post("matrix_inverse regular"); +} + +static void ambi_decode_pinv(t_ambi_decode *x) +{ + t_atom *at=x->x_at; + int i, n=x->x_n_ls*x->x_n_ambi; + double *dv=x->x_prod; + + ambi_decode_transp_back(x); + ambi_decode_mul1(x); + ambi_decode_inverse(x); + ambi_decode_mul2(x); + at += 2; + for(i=0; ix_obj.ob_outlet, x->x_s_matrix, n+2, x->x_at); +} + +static void ambi_decode_encode_ls_2d(t_ambi_decode *x, int argc, t_atom *argv, int ls0_ph1) +{ + double phi; + double *dw = x->x_transp; + int index; + int n_ls=x->x_n_ls; + int n_phls=x->x_n_phls; + int order=x->x_n_order; + + if(argc < 2) + { + post("ambi_decode ERROR: ls-input needs 1 index and 1 angle: ls_index + phi [degree]"); + return; + } + index = (int)atom_getint(argv++) - 1; + phi = (double)atom_getfloat(argv); + + if(index < 0) + index = 0; + if(ls0_ph1) + { + if(n_phls) + { + if(index >= n_phls) + index = n_phls - 1; + index += n_ls; + } + else + return; + } + else + { + if(index >= n_ls) + index = n_ls - 1; + } + + phi *= x->x_pi_over_180; + + dw += index * x->x_n_ambi; + + *dw++ = 1.0; + *dw++ = cos(phi); + *dw++ = sin(phi); + + if(order >= 2) + { + *dw++ = cos(2.0*phi); + *dw++ = sin(2.0*phi); + + if(order >= 3) + { + *dw++ = cos(3.0*phi); + *dw++ = sin(3.0*phi); + if(order >= 4) + { + *dw++ = cos(4.0*phi); + *dw++ = sin(4.0*phi); + + if(order >= 5) + { + *dw++ = cos(5.0*phi); + *dw++ = sin(5.0*phi); + + if(order >= 6) + { + *dw++ = cos(6.0*phi); + *dw++ = sin(6.0*phi); + + if(order >= 7) + { + *dw++ = cos(7.0*phi); + *dw++ = sin(7.0*phi); + + if(order >= 8) + { + *dw++ = cos(8.0*phi); + *dw++ = sin(8.0*phi); + + if(order >= 9) + { + *dw++ = cos(9.0*phi); + *dw++ = sin(9.0*phi); + + if(order >= 10) + { + *dw++ = cos(10.0*phi); + *dw++ = sin(10.0*phi); + + if(order >= 11) + { + *dw++ = cos(11.0*phi); + *dw++ = sin(11.0*phi); + + if(order >= 12) + { + *dw++ = cos(12.0*phi); + *dw++ = sin(12.0*phi); + } + } + } + } + } + } + } + } + } + } + } +} + +static void ambi_decode_encode_ls_3d(t_ambi_decode *x, int argc, t_atom *argv, int ls0_ph1) +{ + double delta, phi; + double cd, sd, cd2, cd3, sd2, csd, cp, sp, cp2, sp2, cp3, sp3, cp4, sp4; + double *dw = x->x_transp; + int index; + int n_ls=x->x_n_ls; + int n_phls=x->x_n_phls; + int order=x->x_n_order; + + if(argc < 3) + { + post("ambi_decode ERROR: ls-input needs 1 index and 2 angles: ls index + delta [degree] + phi [degree]"); + return; + } + index = (int)atom_getint(argv++) - 1; + delta = atom_getfloat(argv++); + phi = atom_getfloat(argv); + + if(index < 0) + index = 0; + if(ls0_ph1) + { + if(n_phls) + { + if(index >= n_phls) + index = n_phls - 1; + index += n_ls; + } + else + return; + } + else + { + if(index >= n_ls) + index = n_ls - 1; + } + + delta *= x->x_pi_over_180; + phi *= x->x_pi_over_180; + + dw += index * x->x_n_ambi; + + cd = cos(delta); + sd = sin(delta); + cp = cos(phi); + sp = sin(phi); + + + *dw++ = 1.0; + *dw++ = cd * cp; + *dw++ = cd * sp; + *dw++ = sd; + + if(order >= 2) + { + cp2 = cos(2.0*phi); + sp2 = sin(2.0*phi); + cd2 = cd * cd; + sd2 = sd * sd; + csd = cd * sd; + *dw++ = 0.5 * x->x_sqrt3 * cd2 * cp2; + *dw++ = 0.5 * x->x_sqrt3 * cd2 * sp2; + *dw++ = x->x_sqrt3 * csd * cp; + *dw++ = x->x_sqrt3 * csd * sp; + *dw++ = 0.5 * (3.0 * sd2 - 1.0); + + if(order >= 3) + { + cp3 = cos(3.0*phi); + sp3 = sin(3.0*phi); + cd3 = cd2 * cd; + *dw++ = x->x_sqrt10_4 * cd3 * cp3; + *dw++ = x->x_sqrt10_4 * cd3 * sp3; + *dw++ = x->x_sqrt15_2 * cd * csd * cp2; + *dw++ = x->x_sqrt15_2 * cd * csd * sp2; + *dw++ = x->x_sqrt6_4 * cd * (5.0 * sd2 - 1.0) * cp; + *dw++ = x->x_sqrt6_4 * cd * (5.0 * sd2 - 1.0) * sp; + *dw++ = 0.5 * sd * (5.0 * sd2 - 3.0); + + if(order >= 4) + { + cp4 = cos(4.0*phi); + sp4 = sin(4.0*phi); + *dw++ = x->x_sqrt35_8 * cd2 * cd2 * cp4; + *dw++ = x->x_sqrt35_8 * cd2 * cd2 * sp4; + *dw++ = x->x_sqrt70_4 * cd2 * csd * cp3; + *dw++ = x->x_sqrt70_4 * cd2 * csd * sp3; + *dw++ = 0.5 * x->x_sqrt5_2 * cd2 * (7.0 * sd2 - 1.0) * cp2; + *dw++ = 0.5 * x->x_sqrt5_2 * cd2 * (7.0 * sd2 - 1.0) * sp2; + *dw++ = x->x_sqrt10_4 * csd * (7.0 * sd2 - 3.0) * cp; + *dw++ = x->x_sqrt10_4 * csd * (7.0 * sd2 - 3.0) * sp; + *dw++ = 0.125 * (sd2 * (35.0 * sd2 - 30.0) + 3.0); + + if(order >= 5) + { + *dw++ = x->x_sqrt126_16 * cd3 * cd2 * cos(5.0*phi); + *dw++ = x->x_sqrt126_16 * cd3 * cd2 * sin(5.0*phi); + *dw++ = x->x_sqrt315_8 * cd3 * csd * cp4; + *dw++ = x->x_sqrt315_8 * cd3 * csd * sp4; + *dw++ = 0.25 * x->x_sqrt70_4 * cd3 * (9.0 * sd2 - 1.0) * cp3; + *dw++ = 0.25 * x->x_sqrt70_4 * cd3 * (9.0 * sd2 - 1.0) * sp3; + *dw++ = x->x_sqrt105_4 * cd * csd * (3.0 * sd2 - 1.0) * cp2; + *dw++ = x->x_sqrt105_4 * cd * csd * (3.0 * sd2 - 1.0) * sp2; + *dw++ = 0.25 * x->x_sqrt15_2 * cd * (sd2 * (21.0 * sd2 - 14.0) + 1.0) * cp; + *dw++ = 0.25 * x->x_sqrt15_2 * cd * (sd2 * (21.0 * sd2 - 14.0) + 1.0) * sp; + *dw = 0.125 * sd * (sd2 * (63.0 * sd2 - 70.0) + 15.0); + } + } + } + } +} + +static void ambi_decode_ls(t_ambi_decode *x, t_symbol *s, int argc, t_atom *argv) +{ + if(x->x_n_dim == 2) + ambi_decode_encode_ls_2d(x, argc, argv, 0); + else + ambi_decode_encode_ls_3d(x, argc, argv, 0); +} + +static void ambi_decode_phls(t_ambi_decode *x, t_symbol *s, int argc, t_atom *argv) +{ + if(x->x_n_dim == 2) + ambi_decode_encode_ls_2d(x, argc, argv, 1); + else + ambi_decode_encode_ls_3d(x, argc, argv, 1); +} + +static void ambi_decode_ambi_weight(t_ambi_decode *x, t_symbol *s, int argc, t_atom *argv) +{ + if(argc > x->x_n_order) + { + int i, k=0, n=x->x_n_order; + double d; + + x->x_ambi_channel_weight[k] = atom_getfloat(argv++); + k++; + if(x->x_n_dim == 2) + { + for(i=1; i<=n; i++) + { + d = atom_getfloat(argv++); + x->x_ambi_channel_weight[k] = d; + k++; + x->x_ambi_channel_weight[k] = d; + k++; + } + } + else + { + int j, m; + + for(i=1; i<=n; i++) + { + d = atom_getfloat(argv++); + m = 2*i + 1; + for(j=0; jx_ambi_channel_weight[k] = d; + k++; + } + } + } + } + else + post("ambi_decode-ERROR: ambi_weight needs %d float weights", x->x_n_order+1); +} + +static void ambi_decode_sing_range(t_ambi_decode *x, t_floatarg f) +{ + if(f < 0.0f) + x->x_sing_range = -(double)f; + else + x->x_sing_range = (double)f; +} + +static void ambi_decode_free(t_ambi_decode *x) +{ + freebytes(x->x_inv_work1, x->x_n_ambi * x->x_n_ambi * sizeof(double)); + freebytes(x->x_inv_work2, 2 * x->x_n_ambi * x->x_n_ambi * sizeof(double)); + freebytes(x->x_inv_buf2, 2 * x->x_n_ambi * sizeof(double)); + freebytes(x->x_transp, (x->x_n_ls+x->x_n_phls) * x->x_n_ambi * sizeof(double)); + freebytes(x->x_ls_encode, (x->x_n_ls+x->x_n_phls) * x->x_n_ambi * sizeof(double)); + freebytes(x->x_prod, (x->x_n_ls+x->x_n_phls) * x->x_n_ambi * sizeof(double)); + freebytes(x->x_ambi_channel_weight, x->x_n_ambi * sizeof(double)); + freebytes(x->x_at, (x->x_n_ls * x->x_n_ambi + 2) * sizeof(t_atom)); +} + +static void *ambi_decode_new(t_symbol *s, int argc, t_atom *argv) +{ + t_ambi_decode *x = (t_ambi_decode *)pd_new(ambi_decode_class); + int nls, order, dim, i; + int nphls=0;/* phantom_loudspeaker */ + + if(argc < 3) + { + post("ambi_decode-ERROR: need following arguments: ambi_order dimension number_of_loudspeakers (number_of_phantom_speakers)"); + return(0); + } + else + { + order = (int)atom_getint(argv++); + dim = (int)atom_getint(argv++); + nls = (int)atom_getint(argv++); + if((argc > 3)&&IS_A_FLOAT(argv,0)) + nphls=(int)atom_getint(argv); + + if(order < 1) + order = 1; + if(dim != 3) + { + dim = 2; + if(order > 12) + order = 12; + x->x_n_ambi = 2*order + 1; + } + else + { + if(order > 5) + order = 5; + x->x_n_ambi = (order + 1)*(order + 1); + } + x->x_n_dim = dim; + x->x_n_order = order; + if(nls < 1) + nls = 1; + if(nphls < 0) + nphls = 0; + if(nls < x->x_n_ambi) + post("ambi_decode-WARNING: Number of Loudspeakers < Number of Ambisonic-Channels !!!!"); + if(nphls > nls) + { + post("ambi_decode-WARNING: Number of Phantom-Loudspeakers > Number of Loudspeakers !!!!"); + nphls = nls; + } + x->x_n_ls = nls; + x->x_n_phls = nphls; + x->x_inv_work1 = (double *)getbytes(x->x_n_ambi * x->x_n_ambi * sizeof(double)); + x->x_inv_work2 = (double *)getbytes(2 * x->x_n_ambi * x->x_n_ambi * sizeof(double)); + x->x_inv_buf2 = (double *)getbytes(2 * x->x_n_ambi * sizeof(double)); + x->x_transp = (double *)getbytes((x->x_n_ls+x->x_n_phls) * x->x_n_ambi * sizeof(double)); + x->x_ls_encode = (double *)getbytes((x->x_n_ls+x->x_n_phls) * x->x_n_ambi * sizeof(double)); + x->x_prod = (double *)getbytes((x->x_n_ls+x->x_n_phls) * x->x_n_ambi * sizeof(double)); + x->x_ambi_channel_weight = (double *)getbytes(x->x_n_ambi * sizeof(double)); + x->x_at = (t_atom *)getbytes((x->x_n_ls * x->x_n_ambi + 2) * sizeof(t_atom)); + x->x_s_matrix = gensym("matrix"); + /*change*/ + SETFLOAT(x->x_at, (float)x->x_n_ls); + SETFLOAT(x->x_at+1, (float)x->x_n_ambi); + x->x_sqrt3 = sqrt(3.0); + x->x_sqrt5_2 = sqrt(5.0) / 2.0; + x->x_sqrt6_4 = sqrt(6.0) / 4.0; + x->x_sqrt10_4 = sqrt(10.0) / 4.0; + x->x_sqrt15_2 = sqrt(15.0) / 2.0; + x->x_sqrt35_8 = sqrt(35.0) / 8.0; + x->x_sqrt70_4 = sqrt(70.0) / 4.0; + x->x_sqrt126_16 = sqrt(126.0) / 16.0; + x->x_sqrt315_8 = sqrt(315.0) / 8.0; + x->x_sqrt105_4 = sqrt(105.0) / 4.0; + x->x_pi_over_180 = 4.0 * atan(1.0) / 180.0; + x->x_sing_range = 1.0e-10; + for(i=0; ix_n_ambi; i++) + x->x_ambi_channel_weight[i] = 1.0; + outlet_new(&x->x_obj, &s_list); + return (x); + } +} + +void ambi_decode_setup(void) +{ + ambi_decode_class = class_new(gensym("ambi_decode"), (t_newmethod)ambi_decode_new, (t_method)ambi_decode_free, + sizeof(t_ambi_decode), 0, A_GIMME, 0); + class_addmethod(ambi_decode_class, (t_method)ambi_decode_ls, gensym("ls"), A_GIMME, 0); + class_addmethod(ambi_decode_class, (t_method)ambi_decode_phls, gensym("phls"), A_GIMME, 0); + class_addmethod(ambi_decode_class, (t_method)ambi_decode_ambi_weight, gensym("ambi_weight"), A_GIMME, 0); + class_addmethod(ambi_decode_class, (t_method)ambi_decode_sing_range, gensym("sing_range"), A_DEFFLOAT, 0); + class_addmethod(ambi_decode_class, (t_method)ambi_decode_pinv, gensym("pinv"), 0); + class_sethelpsymbol(ambi_decode_class, gensym("iemhelp2/help-ambi_decode")); +} diff --git a/src/ambi_decode2.c b/src/ambi_decode2.c new file mode 100644 index 0000000..2e5caf9 --- /dev/null +++ b/src/ambi_decode2.c @@ -0,0 +1,824 @@ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. + +iem_ambi written by Thomas Musil, Copyright (c) IEM KUG Graz Austria 2000 - 2005 */ + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + + +#include "m_pd.h" +#include "iemlib.h" +#include "iem_ambi.h" +#include +#include +#include + + + +/* -------------------------- ambi_decode2 ------------------------------ */ +/* + ** berechnet ein reduziertes Ambisonic-Decoder-Set in die HRTF-Spektren ** + ** Inputs: ls + Liste von 3 floats: Index [1 .. 25] + Elevation [-90 .. +90 degree] + Azimut [0 .. 360 degree] ** + ** Inputs: calc_inv ** + ** Inputs: load_HRIR + float index1..25 ** + ** Outputs: List of 2 symbols: left-HRIR-File-name + HRIR-table-name ** + ** Inputs: calc_reduced ** + ** "output" ... writes the HRTF into tables ** + ** ** + ** ** + ** setzt voraus , dass die HRIR-tabele-names von LS1_L_HRIR .. LS25_L_HRIR heissen und existieren ** + ** setzt voraus , dass die HRTF-tabele-names von LS1_HRTF_re .. LS25_HRTF_re heissen und existieren ** + ** setzt voraus , dass die HRTF-tabele-names von LS1_HRTF_im .. LS25_HRTF_im heissen und existieren ** + */ + + +typedef struct _ambi_decode2 +{ + t_object x_obj; + t_atom *x_at; + double *x_inv_work1; + double *x_inv_work2; + double *x_inv_buf2; + double *x_transp; + double *x_ls_encode; + double *x_prod; + double *x_ambi_channel_weight; + double x_mirror_weight; + double x_sing_range; + int x_n_ambi; + int x_n_order; + int x_n_ls; + int x_n_ph_ls; + int x_n_mir_ls; + int x_n_dim; + t_symbol *x_s_matrix; + double x_sqrt3; + double x_sqrt10_4; + double x_sqrt15_2; + double x_sqrt6_4; + double x_sqrt35_8; + double x_sqrt70_4; + double x_sqrt5_2; + double x_sqrt126_16; + double x_sqrt315_8; + double x_sqrt105_4; + double x_pi_over_180; +} t_ambi_decode2; + +static t_class *ambi_decode2_class; + +static void ambi_decode2_copy_row2buf(t_ambi_decode2 *x, int row) +{ + int n_ambi2 = 2*x->x_n_ambi; + int i; + double *dw=x->x_inv_work2; + double *db=x->x_inv_buf2; + + dw += row*n_ambi2; + for(i=0; ix_n_ambi; + int i; + double *dw=x->x_inv_work2; + double *db=x->x_inv_buf2; + + dw += row*n_ambi2; + for(i=0; ix_n_ambi; + int i; + double *dw_src=x->x_inv_work2; + double *dw_dst=x->x_inv_work2; + + dw_src += src_row*n_ambi2; + dw_dst += dst_row*n_ambi2; + for(i=0; ix_n_ambi; + int i; + double *dw=x->x_inv_work2; + + dw += row*n_ambi2; + for(i=0; ix_n_ambi; + int i; + double *dw=x->x_inv_work2; + double *db=x->x_inv_buf2; + + dw += row*n_ambi2; + for(i=0; ix_n_ambi; + int n_ambi2 = 2*n_ambi; + int i, j; + double *dw=x->x_inv_work2; + double singrange=x->x_sing_range; + int ret=-1; + + dw += start_row*n_ambi2 + col; + j = 0; + for(i=start_row; i singrange) || (*dw < -singrange)) + { + ret = i; + i = n_ambi+1; + } + dw += n_ambi2; + } + return(ret); +} + +static void ambi_decode2_mul1(t_ambi_decode2 *x) +{ + double *vec1, *beg1=x->x_ls_encode; + double *vec2, *beg2=x->x_ls_encode; + double *inv=x->x_inv_work1; + double sum; + int n_ls=x->x_n_ls+2*x->x_n_mir_ls+x->x_n_ph_ls; + int n_ambi=x->x_n_ambi; + int i, j, k; + + for(k=0; kx_ls_encode; + for(j=0; jx_n_ls+2*x->x_n_mir_ls+x->x_n_ph_ls; + int n_ambi=x->x_n_ambi; + int n_ambi2=2*n_ambi; + int i, j, k; + double *vec1, *beg1=x->x_transp; + double *vec2, *beg2=x->x_inv_work2+n_ambi; + double *vec3=x->x_prod; + double *acw_vec=x->x_ambi_channel_weight; + double sum; + + for(k=0; kx_inv_work2+n_ambi; + for(j=0; jx_transp; + double *straight=x->x_ls_encode; + int n_ls=x->x_n_ls+2*x->x_n_mir_ls+x->x_n_ph_ls; + int n_ambi=x->x_n_ambi; + int i, j; + + for(j=0; jx_n_ambi; + int n_ambi2 = 2*n_ambi; + int i, j, nz; + int r,c; + double *src=x->x_inv_work1; + double *db=x->x_inv_work2; + double rcp, *dv; + + dv = db; + for(i=0; i=0; i--) + { + dv = db + i*n_ambi2 + i; + ambi_decode2_copy_row2buf(x, i); + for(j=i-1; j>=0; j--) + { + dv -= n_ambi2; + rcp = -(*dv); + ambi_decode2_mul_buf_and_add2row(x, j, rcp); + } + } + + post("matrix_inverse regular"); +} + +static void ambi_decode2_pseudo_inverse(t_ambi_decode2 *x, t_symbol *s, int argc, t_atom *argv) +{ + t_atom *at=x->x_at; + int i, n=x->x_n_ls*x->x_n_ambi; + double *dv1=x->x_prod; + double *dv2=x->x_prod; + double mw=x->x_mirror_weight; + + ambi_decode2_transp_back(x); + ambi_decode2_mul1(x); + ambi_decode2_inverse(x); + ambi_decode2_mul2(x); + at += 2; + for(i=0; ix_n_mir_ls*x->x_n_ambi; + dv2 += n; + for(i=0; ix_obj.ob_outlet, x->x_s_matrix, x->x_n_ambi*(x->x_n_ls+x->x_n_mir_ls)+2, x->x_at); +} + +static void ambi_decode2_encode_ls_2d(t_ambi_decode2 *x, int argc, t_atom *argv, int mode) +{ + double phi; + double *dw = x->x_transp; + int index; + int order=x->x_n_order; + + if(argc < 2) + { + post("ambi_decode2 ERROR: ls-input needs 1 index and 1 angle: ls_index + phi [degree]"); + return; + } + index = (int)atom_getint(argv++) - 1; + phi = (double)atom_getfloat(argv); + + if(index < 0) + index = 0; + + if(mode == AMBI_LS_IND) + { + if(index >= x->x_n_ls) + index = x->x_n_ls - 1; + } + else if(mode == AMBI_LS_MRG) + { + if(x->x_n_mir_ls) + { + if(index >= x->x_n_mir_ls) + index = x->x_n_mir_ls - 1; + index += x->x_n_ls; + } + else + return; + } + else if(mode == AMBI_LS_MIR) + { + if(x->x_n_mir_ls) + { + if(index >= x->x_n_mir_ls) + index = x->x_n_mir_ls - 1; + index += x->x_n_ls; + index += x->x_n_mir_ls; + } + else + return; + } + else if(mode == AMBI_LS_PHT) + { + if(x->x_n_ph_ls) + { + if(index >= x->x_n_ph_ls) + index = x->x_n_ph_ls - 1; + index += x->x_n_ls; + index += 2*x->x_n_mir_ls; + } + else + return; + } + else + return; + + phi *= x->x_pi_over_180; + + dw += index * x->x_n_ambi; + + *dw++ = 1.0; + *dw++ = cos(phi); + *dw++ = sin(phi); + + if(order >= 2) + { + *dw++ = cos(2.0*phi); + *dw++ = sin(2.0*phi); + + if(order >= 3) + { + *dw++ = cos(3.0*phi); + *dw++ = sin(3.0*phi); + if(order >= 4) + { + *dw++ = cos(4.0*phi); + *dw++ = sin(4.0*phi); + + if(order >= 5) + { + *dw++ = cos(5.0*phi); + *dw++ = sin(5.0*phi); + + if(order >= 6) + { + *dw++ = cos(6.0*phi); + *dw++ = sin(6.0*phi); + + if(order >= 7) + { + *dw++ = cos(7.0*phi); + *dw++ = sin(7.0*phi); + + if(order >= 8) + { + *dw++ = cos(8.0*phi); + *dw++ = sin(8.0*phi); + + if(order >= 9) + { + *dw++ = cos(9.0*phi); + *dw++ = sin(9.0*phi); + + if(order >= 10) + { + *dw++ = cos(10.0*phi); + *dw++ = sin(10.0*phi); + + if(order >= 11) + { + *dw++ = cos(11.0*phi); + *dw++ = sin(11.0*phi); + + if(order >= 12) + { + *dw++ = cos(12.0*phi); + *dw++ = sin(12.0*phi); + } + } + } + } + } + } + } + } + } + } + } +} + +static void ambi_decode2_encode_ls_3d(t_ambi_decode2 *x, int argc, t_atom *argv, int mode) +{ + double delta, phi; + double cd, sd, cd2, cd3, sd2, csd, cp, sp, cp2, sp2, cp3, sp3, cp4, sp4; + double *dw = x->x_transp; + int index; + int order=x->x_n_order; + + if(argc < 3) + { + post("ambi_decode2 ERROR: ls-input needs 1 index and 2 angles: ls index + delta [degree] + phi [degree]"); + return; + } + index = (int)atom_getint(argv++) - 1; + delta = atom_getfloat(argv++); + phi = atom_getfloat(argv); + + if(index < 0) + index = 0; + + if(mode == AMBI_LS_IND) + { + if(index >= x->x_n_ls) + index = x->x_n_ls - 1; + } + else if(mode == AMBI_LS_MRG) + { + if(x->x_n_mir_ls) + { + if(index >= x->x_n_mir_ls) + index = x->x_n_mir_ls - 1; + index += x->x_n_ls; + } + else + return; + } + else if(mode == AMBI_LS_MIR) + { + if(x->x_n_mir_ls) + { + if(index >= x->x_n_mir_ls) + index = x->x_n_mir_ls - 1; + index += x->x_n_ls; + index += x->x_n_mir_ls; + } + else + return; + } + else if(mode == AMBI_LS_PHT) + { + if(x->x_n_ph_ls) + { + if(index >= x->x_n_ph_ls) + index = x->x_n_ph_ls - 1; + index += x->x_n_ls; + index += 2*x->x_n_mir_ls; + } + else + return; + } + else + return; + + delta *= x->x_pi_over_180; + phi *= x->x_pi_over_180; + + dw += index * x->x_n_ambi; + + cd = cos(delta); + sd = sin(delta); + cp = cos(phi); + sp = sin(phi); + + + *dw++ = 1.0; + *dw++ = cd * cp; + *dw++ = cd * sp; + *dw++ = sd; + + if(order >= 2) + { + cp2 = cos(2.0*phi); + sp2 = sin(2.0*phi); + cd2 = cd * cd; + sd2 = sd * sd; + csd = cd * sd; + *dw++ = 0.5 * x->x_sqrt3 * cd2 * cp2; + *dw++ = 0.5 * x->x_sqrt3 * cd2 * sp2; + *dw++ = x->x_sqrt3 * csd * cp; + *dw++ = x->x_sqrt3 * csd * sp; + *dw++ = 0.5 * (3.0 * sd2 - 1.0); + + if(order >= 3) + { + cp3 = cos(3.0*phi); + sp3 = sin(3.0*phi); + cd3 = cd2 * cd; + *dw++ = x->x_sqrt10_4 * cd3 * cp3; + *dw++ = x->x_sqrt10_4 * cd3 * sp3; + *dw++ = x->x_sqrt15_2 * cd * csd * cp2; + *dw++ = x->x_sqrt15_2 * cd * csd * sp2; + *dw++ = x->x_sqrt6_4 * cd * (5.0 * sd2 - 1.0) * cp; + *dw++ = x->x_sqrt6_4 * cd * (5.0 * sd2 - 1.0) * sp; + *dw++ = 0.5 * sd * (5.0 * sd2 - 3.0); + + if(order >= 4) + { + cp4 = cos(4.0*phi); + sp4 = sin(4.0*phi); + *dw++ = x->x_sqrt35_8 * cd2 * cd2 * cp4; + *dw++ = x->x_sqrt35_8 * cd2 * cd2 * sp4; + *dw++ = x->x_sqrt70_4 * cd2 * csd * cp3; + *dw++ = x->x_sqrt70_4 * cd2 * csd * sp3; + *dw++ = 0.5 * x->x_sqrt5_2 * cd2 * (7.0 * sd2 - 1.0) * cp2; + *dw++ = 0.5 * x->x_sqrt5_2 * cd2 * (7.0 * sd2 - 1.0) * sp2; + *dw++ = x->x_sqrt10_4 * csd * (7.0 * sd2 - 3.0) * cp; + *dw++ = x->x_sqrt10_4 * csd * (7.0 * sd2 - 3.0) * sp; + *dw++ = 0.125 * (sd2 * (35.0 * sd2 - 30.0) + 3.0); + + if(order >= 5) + { + *dw++ = x->x_sqrt126_16 * cd3 * cd2 * cos(5.0*phi); + *dw++ = x->x_sqrt126_16 * cd3 * cd2 * sin(5.0*phi); + *dw++ = x->x_sqrt315_8 * cd3 * csd * cp4; + *dw++ = x->x_sqrt315_8 * cd3 * csd * sp4; + *dw++ = 0.25 * x->x_sqrt70_4 * cd3 * (9.0 * sd2 - 1.0) * cp3; + *dw++ = 0.25 * x->x_sqrt70_4 * cd3 * (9.0 * sd2 - 1.0) * sp3; + *dw++ = x->x_sqrt105_4 * cd * csd * (3.0 * sd2 - 1.0) * cp2; + *dw++ = x->x_sqrt105_4 * cd * csd * (3.0 * sd2 - 1.0) * sp2; + *dw++ = 0.25 * x->x_sqrt15_2 * cd * (sd2 * (21.0 * sd2 - 14.0) + 1.0) * cp; + *dw++ = 0.25 * x->x_sqrt15_2 * cd * (sd2 * (21.0 * sd2 - 14.0) + 1.0) * sp; + *dw = 0.125 * sd * (sd2 * (63.0 * sd2 - 70.0) + 15.0); + } + } + } + } +} + +static void ambi_decode2_ind_ls(t_ambi_decode2 *x, t_symbol *s, int argc, t_atom *argv) +{ + if(x->x_n_dim == 2) + ambi_decode2_encode_ls_2d(x, argc, argv, AMBI_LS_IND); + else + ambi_decode2_encode_ls_3d(x, argc, argv, AMBI_LS_IND); +} + +static void ambi_decode2_mrg_ls(t_ambi_decode2 *x, t_symbol *s, int argc, t_atom *argv) +{ + if(x->x_n_dim == 2) + ambi_decode2_encode_ls_2d(x, argc, argv, AMBI_LS_MRG); + else + ambi_decode2_encode_ls_3d(x, argc, argv, AMBI_LS_MRG); +} + +static void ambi_decode2_mir_ls(t_ambi_decode2 *x, t_symbol *s, int argc, t_atom *argv) +{ + if(x->x_n_dim == 2) + ambi_decode2_encode_ls_2d(x, argc, argv, AMBI_LS_MIR); + else + ambi_decode2_encode_ls_3d(x, argc, argv, AMBI_LS_MIR); +} + +static void ambi_decode2_pht_ls(t_ambi_decode2 *x, t_symbol *s, int argc, t_atom *argv) +{ + if(x->x_n_dim == 2) + ambi_decode2_encode_ls_2d(x, argc, argv, AMBI_LS_PHT); + else + ambi_decode2_encode_ls_3d(x, argc, argv, AMBI_LS_PHT); +} + +static void ambi_decode2_ambi_weight(t_ambi_decode2 *x, t_symbol *s, int argc, t_atom *argv) +{ + if(argc > x->x_n_order) + { + int i, k=0, n=x->x_n_order; + double d; + + x->x_ambi_channel_weight[k] = atom_getfloat(argv++); + k++; + if(x->x_n_dim == 2) + { + for(i=1; i<=n; i++) + { + d = atom_getfloat(argv++); + x->x_ambi_channel_weight[k] = d; + k++; + x->x_ambi_channel_weight[k] = d; + k++; + } + } + else + { + int j, m; + + for(i=1; i<=n; i++) + { + d = atom_getfloat(argv++); + m = 2*i + 1; + for(j=0; jx_ambi_channel_weight[k] = d; + k++; + } + } + } + } + else + post("ambi_decode2-ERROR: ambi_weight needs %d float weights", x->x_n_order+1); +} + +static void ambi_decode2_mirror_weight(t_ambi_decode2 *x, t_floatarg f) +{ + x->x_mirror_weight = (double)f; +} + +static void ambi_decode2_sing_range(t_ambi_decode2 *x, t_floatarg f) +{ + if(f < 0.0f) + x->x_sing_range = -(double)f; + else + x->x_sing_range = (double)f; +} + +static void ambi_decode2_free(t_ambi_decode2 *x) +{ + freebytes(x->x_inv_work1, x->x_n_ambi * x->x_n_ambi * sizeof(double)); + freebytes(x->x_inv_work2, 2 * x->x_n_ambi * x->x_n_ambi * sizeof(double)); + freebytes(x->x_inv_buf2, 2 * x->x_n_ambi * sizeof(double)); + freebytes(x->x_transp, (x->x_n_ls+2*x->x_n_mir_ls+x->x_n_ph_ls) * x->x_n_ambi * sizeof(double)); + freebytes(x->x_ls_encode, (x->x_n_ls+2*x->x_n_mir_ls+x->x_n_ph_ls) * x->x_n_ambi * sizeof(double)); + freebytes(x->x_prod, (x->x_n_ls+2*x->x_n_mir_ls+x->x_n_ph_ls) * x->x_n_ambi * sizeof(double)); + freebytes(x->x_ambi_channel_weight, x->x_n_ambi * sizeof(double)); + freebytes(x->x_at, ((x->x_n_ls+x->x_n_mir_ls) * x->x_n_ambi + 2) * sizeof(t_atom)); +} + +static void *ambi_decode2_new(t_symbol *s, int argc, t_atom *argv) +{ + t_ambi_decode2 *x = (t_ambi_decode2 *)pd_new(ambi_decode2_class); + int order, dim, i; + int n_ls=0;/* number of loudspeakers */ + int n_mir_ls=0;/* number of mirror_loudspeakers */ + int n_ph_ls=0;/* number of phantom_loudspeakers */ + + if((argc >= 5) && + IS_A_FLOAT(argv,0) && + IS_A_FLOAT(argv,1) && + IS_A_FLOAT(argv,2) && + IS_A_FLOAT(argv,3) && + IS_A_FLOAT(argv,4)) + { + order = (int)atom_getint(argv++); + dim = (int)atom_getint(argv++); + n_ls = (int)atom_getint(argv++); + n_mir_ls = (int)atom_getint(argv++); + n_ph_ls = (int)atom_getint(argv); + + if(order < 1) + order = 1; + if(dim != 3) + { + dim = 2; + if(order > 12) + order = 12; + x->x_n_ambi = 2*order + 1; + } + else + { + if(order > 5) + order = 5; + x->x_n_ambi = (order + 1)*(order + 1); + } + x->x_n_dim = dim; + x->x_n_order = order; + if(n_ls < 1) + n_ls = 1; + if(n_mir_ls < 0) + n_mir_ls = 0; + if(n_ph_ls < 0) + n_ph_ls = 0; + if((n_ls + 2*n_mir_ls + n_ph_ls) < x->x_n_ambi) + post("ambi_decode2-WARNING: Number of Loudspeakers < Number of Ambisonic-Channels !!!!"); + + x->x_n_ls = n_ls; + x->x_n_mir_ls = n_mir_ls; + x->x_n_ph_ls = n_ph_ls; + x->x_inv_work1 = (double *)getbytes(x->x_n_ambi * x->x_n_ambi * sizeof(double)); + x->x_inv_work2 = (double *)getbytes(2 * x->x_n_ambi * x->x_n_ambi * sizeof(double)); + x->x_inv_buf2 = (double *)getbytes(2 * x->x_n_ambi * sizeof(double)); + x->x_transp = (double *)getbytes((x->x_n_ls+2*x->x_n_mir_ls+x->x_n_ph_ls) * x->x_n_ambi * sizeof(double)); + x->x_ls_encode = (double *)getbytes((x->x_n_ls+2*x->x_n_mir_ls+x->x_n_ph_ls) * x->x_n_ambi * sizeof(double)); + x->x_prod = (double *)getbytes((x->x_n_ls+2*x->x_n_mir_ls+x->x_n_ph_ls) * x->x_n_ambi * sizeof(double)); + x->x_ambi_channel_weight = (double *)getbytes(x->x_n_ambi * sizeof(double)); + x->x_at = (t_atom *)getbytes(((x->x_n_ls+x->x_n_mir_ls) * x->x_n_ambi + 2) * sizeof(t_atom)); + x->x_s_matrix = gensym("matrix"); + /*change*/ + SETFLOAT(x->x_at, (float)(x->x_n_ls+x->x_n_mir_ls)); + SETFLOAT(x->x_at+1, (float)x->x_n_ambi); + x->x_mirror_weight = 0.0; + + x->x_sqrt3 = sqrt(3.0); + x->x_sqrt5_2 = sqrt(5.0) / 2.0; + x->x_sqrt6_4 = sqrt(6.0) / 4.0; + x->x_sqrt10_4 = sqrt(10.0) / 4.0; + x->x_sqrt15_2 = sqrt(15.0) / 2.0; + x->x_sqrt35_8 = sqrt(35.0) / 8.0; + x->x_sqrt70_4 = sqrt(70.0) / 4.0; + x->x_sqrt126_16 = sqrt(126.0) / 16.0; + x->x_sqrt315_8 = sqrt(315.0) / 8.0; + x->x_sqrt105_4 = sqrt(105.0) / 4.0; + x->x_pi_over_180 = 4.0 * atan(1.0) / 180.0; + x->x_sing_range = 1.0e-10; + for(i=0; ix_n_ambi; i++) + x->x_ambi_channel_weight[i] = 1.0; + outlet_new(&x->x_obj, &s_list); + return (x); + } + else + { + post("ambi_decode2-ERROR: need 5 float arguments: ambi_order dimension number_of_independent_loudspeakers number_of_merged_and_mirrored_speakers number_of_canceled_phantom_speakers"); + return(0); + } +} + +void ambi_decode2_setup(void) +{ + ambi_decode2_class = class_new(gensym("ambi_decode2"), (t_newmethod)ambi_decode2_new, (t_method)ambi_decode2_free, + sizeof(t_ambi_decode2), 0, A_GIMME, 0); + class_addmethod(ambi_decode2_class, (t_method)ambi_decode2_ind_ls, gensym("ind_ls"), A_GIMME, 0); + class_addmethod(ambi_decode2_class, (t_method)ambi_decode2_mrg_ls, gensym("mrg_ls"), A_GIMME, 0); + class_addmethod(ambi_decode2_class, (t_method)ambi_decode2_mir_ls, gensym("mir_ls"), A_GIMME, 0); + class_addmethod(ambi_decode2_class, (t_method)ambi_decode2_pht_ls, gensym("pht_ls"), A_GIMME, 0); + class_addmethod(ambi_decode2_class, (t_method)ambi_decode2_mirror_weight, gensym("mirror_weight"), A_DEFFLOAT, 0); + class_addmethod(ambi_decode2_class, (t_method)ambi_decode2_ambi_weight, gensym("ambi_weight"), A_GIMME, 0); + class_addmethod(ambi_decode2_class, (t_method)ambi_decode2_sing_range, gensym("sing_range"), A_DEFFLOAT, 0); + class_addmethod(ambi_decode2_class, (t_method)ambi_decode2_pseudo_inverse, gensym("pseudo_inverse"), A_GIMME, 0); + class_sethelpsymbol(ambi_decode2_class, gensym("iemhelp2/help-ambi_decode2")); +} diff --git a/src/ambi_decode3.c b/src/ambi_decode3.c new file mode 100644 index 0000000..6724924 --- /dev/null +++ b/src/ambi_decode3.c @@ -0,0 +1,772 @@ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. + +iem_ambi written by Thomas Musil, Copyright (c) IEM KUG Graz Austria 2000 - 2005 */ + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + + +#include "m_pd.h" +#include "iemlib.h" +#include "iem_ambi.h" +#include +#include +#include + + + +/* -------------------------- ambi_decode3 ------------------------------ */ +/* + ** berechnet ein reduziertes Ambisonic-Decoder-Set in die HRTF-Spektren ** + ** Inputs: ls + Liste von 3 floats: Index [1 .. 25] + Elevation [-90 .. +90 degree] + Azimut [0 .. 360 degree] ** + ** Inputs: calc_inv ** + ** Inputs: load_HRIR + float index1..25 ** + ** Outputs: List of 2 symbols: left-HRIR-File-name + HRIR-table-name ** + ** Inputs: calc_reduced ** + ** "output" ... writes the HRTF into tables ** + ** ** + ** ** + ** setzt voraus , dass die HRIR-tabele-names von LS1_L_HRIR .. LS25_L_HRIR heissen und existieren ** + ** setzt voraus , dass die HRTF-tabele-names von LS1_HRTF_re .. LS25_HRTF_re heissen und existieren ** + ** setzt voraus , dass die HRTF-tabele-names von LS1_HRTF_im .. LS25_HRTF_im heissen und existieren ** + */ + +typedef struct _ambi_decode3 +{ + t_object x_obj; + t_atom *x_at; + double *x_inv_work1; + double *x_inv_work2; + double *x_inv_buf2; + double *x_transp; + double *x_ls_encode; + double *x_prod; + double *x_ambi_channel_weight; + double x_sing_range; + int x_n_ambi; + int x_n_order; + int x_n_real_ls; + int x_n_pht_ls; + int x_n_dim; + t_symbol *x_s_matrix; + double x_sqrt3; + double x_sqrt10_4; + double x_sqrt15_2; + double x_sqrt6_4; + double x_sqrt35_8; + double x_sqrt70_4; + double x_sqrt5_2; + double x_sqrt126_16; + double x_sqrt315_8; + double x_sqrt105_4; + double x_pi_over_180; +} t_ambi_decode3; + +static t_class *ambi_decode3_class; + +static void ambi_decode3_copy_row2buf(t_ambi_decode3 *x, int row) +{ + int n_ambi2 = 2*x->x_n_ambi; + int i; + double *dw=x->x_inv_work2; + double *db=x->x_inv_buf2; + + dw += row*n_ambi2; + for(i=0; ix_n_ambi; + int i; + double *dw=x->x_inv_work2; + double *db=x->x_inv_buf2; + + dw += row*n_ambi2; + for(i=0; ix_n_ambi; + int i; + double *dw_src=x->x_inv_work2; + double *dw_dst=x->x_inv_work2; + + dw_src += src_row*n_ambi2; + dw_dst += dst_row*n_ambi2; + for(i=0; ix_n_ambi; + int i; + double *dw=x->x_inv_work2; + + dw += row*n_ambi2; + for(i=0; ix_n_ambi; + int i; + double *dw=x->x_inv_work2; + double *db=x->x_inv_buf2; + + dw += row*n_ambi2; + for(i=0; ix_n_ambi; + int n_ambi2 = 2*n_ambi; + int i, j; + double *dw=x->x_inv_work2; + double singrange=x->x_sing_range; + int ret=-1; + + dw += start_row*n_ambi2 + col; + j = 0; + for(i=start_row; i singrange) || (*dw < -singrange)) + { + ret = i; + i = n_ambi+1; + } + dw += n_ambi2; + } + return(ret); +} + +static void ambi_decode3_mul1(t_ambi_decode3 *x) +{ + double *vec1, *beg1=x->x_ls_encode; + double *vec2, *beg2=x->x_ls_encode; + double *inv=x->x_inv_work1; + double sum; + int n_ls=x->x_n_real_ls+x->x_n_pht_ls; + int n_ambi=x->x_n_ambi; + int i, j, k; + + for(k=0; kx_ls_encode; + for(j=0; jx_n_real_ls+x->x_n_pht_ls; + int n_ambi=x->x_n_ambi; + int n_ambi2=2*n_ambi; + int i, j, k; + double *vec1, *beg1=x->x_transp; + double *vec2, *beg2=x->x_inv_work2+n_ambi; + double *vec3=x->x_prod; + double *acw_vec=x->x_ambi_channel_weight; + double sum; + + for(k=0; kx_inv_work2+n_ambi; + for(j=0; jx_transp; + double *straight=x->x_ls_encode; + int n_ls=x->x_n_real_ls+x->x_n_pht_ls; + int n_ambi=x->x_n_ambi; + int i, j; + + for(j=0; jx_n_ambi; + int n_ambi2 = 2*n_ambi; + int i, j, nz; + int r,c; + double *src=x->x_inv_work1; + double *db=x->x_inv_work2; + double rcp, *dv; + + dv = db; + for(i=0; i=0; i--) + { + dv = db + i*n_ambi2 + i; + ambi_decode3_copy_row2buf(x, i); + for(j=i-1; j>=0; j--) + { + dv -= n_ambi2; + rcp = -(*dv); + ambi_decode3_mul_buf_and_add2row(x, j, rcp); + } + } + + post("matrix_inverse regular"); +} + +static void ambi_decode3_begin_pseudo_inverse(t_ambi_decode3 *x) +{ + t_atom *at=x->x_at; + int i, n=x->x_n_real_ls*x->x_n_ambi; + double *dv1=x->x_prod; + + ambi_decode3_transp_back(x); + ambi_decode3_mul1(x); + ambi_decode3_inverse(x); + ambi_decode3_mul2(x); + at += 2; + for(i=0; ix_at; + int i, n=x->x_n_ambi; + int pht_index, real_index; + double mw; + float dat1; + double *dv2=x->x_prod; + + if(argc < 3) + { + post("ambi_decode3 ERROR: ipht_ireal_muladd needs 2 index and 1 mirrorweight: pht_ls_index + real_ls_index + mirror_weight_element"); + return; + } + pht_index = (int)atom_getint(argv++) - 1; + real_index = (int)atom_getint(argv++) - 1; + mw = (double)atom_getfloat(argv); + + if(pht_index < 0) + pht_index = 0; + if(real_index < 0) + real_index = 0; + if(real_index >= x->x_n_real_ls) + real_index = x->x_n_real_ls - 1; + if(pht_index >= x->x_n_pht_ls) + pht_index = x->x_n_pht_ls - 1; + + at += 2 + (real_index)*x->x_n_ambi; + dv2 += (x->x_n_real_ls+pht_index)*x->x_n_ambi; + for(i=0; ix_obj.ob_outlet, x->x_s_matrix, x->x_n_ambi*x->x_n_real_ls+2, x->x_at); +} + +static void ambi_decode3_encode_ls_2d(t_ambi_decode3 *x, int argc, t_atom *argv, int mode) +{ + double phi; + double *dw = x->x_transp; + int index; + int order=x->x_n_order; + + if(argc < 2) + { + post("ambi_decode3 ERROR: ls-input needs 1 index and 1 angle: ls_index + phi [degree]"); + return; + } + index = (int)atom_getint(argv++) - 1; + phi = (double)atom_getfloat(argv); + + if(index < 0) + index = 0; + + if(mode == AMBI_LS_REAL) + { + if(index >= x->x_n_real_ls) + index = x->x_n_real_ls - 1; + } + else if(mode == AMBI_LS_PHT) + { + if(x->x_n_pht_ls) + { + if(index >= x->x_n_pht_ls) + index = x->x_n_pht_ls - 1; + index += x->x_n_real_ls; + } + else + return; + } + else + return; + + phi *= x->x_pi_over_180; + + dw += index * x->x_n_ambi; + + *dw++ = 1.0; + *dw++ = cos(phi); + *dw++ = sin(phi); + + if(order >= 2) + { + *dw++ = cos(2.0*phi); + *dw++ = sin(2.0*phi); + + if(order >= 3) + { + *dw++ = cos(3.0*phi); + *dw++ = sin(3.0*phi); + if(order >= 4) + { + *dw++ = cos(4.0*phi); + *dw++ = sin(4.0*phi); + + if(order >= 5) + { + *dw++ = cos(5.0*phi); + *dw++ = sin(5.0*phi); + + if(order >= 6) + { + *dw++ = cos(6.0*phi); + *dw++ = sin(6.0*phi); + + if(order >= 7) + { + *dw++ = cos(7.0*phi); + *dw++ = sin(7.0*phi); + + if(order >= 8) + { + *dw++ = cos(8.0*phi); + *dw++ = sin(8.0*phi); + + if(order >= 9) + { + *dw++ = cos(9.0*phi); + *dw++ = sin(9.0*phi); + + if(order >= 10) + { + *dw++ = cos(10.0*phi); + *dw++ = sin(10.0*phi); + + if(order >= 11) + { + *dw++ = cos(11.0*phi); + *dw++ = sin(11.0*phi); + + if(order >= 12) + { + *dw++ = cos(12.0*phi); + *dw++ = sin(12.0*phi); + } + } + } + } + } + } + } + } + } + } + } +} + +static void ambi_decode3_encode_ls_3d(t_ambi_decode3 *x, int argc, t_atom *argv, int mode) +{ + double delta, phi; + double cd, sd, cd2, cd3, sd2, csd, cp, sp, cp2, sp2, cp3, sp3, cp4, sp4; + double *dw = x->x_transp; + int index; + int order=x->x_n_order; + + if(argc < 3) + { + post("ambi_decode3 ERROR: ls-input needs 1 index and 2 angles: ls index + delta [degree] + phi [degree]"); + return; + } + index = (int)atom_getint(argv++) - 1; + delta = atom_getfloat(argv++); + phi = atom_getfloat(argv); + + if(index < 0) + index = 0; + + if(mode == AMBI_LS_REAL) + { + if(index >= x->x_n_real_ls) + index = x->x_n_real_ls - 1; + } + else if(mode == AMBI_LS_PHT) + { + if(x->x_n_pht_ls) + { + if(index >= x->x_n_pht_ls) + index = x->x_n_pht_ls - 1; + index += x->x_n_real_ls; + } + else + return; + } + else + return; + + delta *= x->x_pi_over_180; + phi *= x->x_pi_over_180; + + dw += index * x->x_n_ambi; + + cd = cos(delta); + sd = sin(delta); + cp = cos(phi); + sp = sin(phi); + + + *dw++ = 1.0; + *dw++ = cd * cp; + *dw++ = cd * sp; + *dw++ = sd; + + if(order >= 2) + { + cp2 = cos(2.0*phi); + sp2 = sin(2.0*phi); + cd2 = cd * cd; + sd2 = sd * sd; + csd = cd * sd; + *dw++ = 0.5 * x->x_sqrt3 * cd2 * cp2; + *dw++ = 0.5 * x->x_sqrt3 * cd2 * sp2; + *dw++ = x->x_sqrt3 * csd * cp; + *dw++ = x->x_sqrt3 * csd * sp; + *dw++ = 0.5 * (3.0 * sd2 - 1.0); + + if(order >= 3) + { + cp3 = cos(3.0*phi); + sp3 = sin(3.0*phi); + cd3 = cd2 * cd; + *dw++ = x->x_sqrt10_4 * cd3 * cp3; + *dw++ = x->x_sqrt10_4 * cd3 * sp3; + *dw++ = x->x_sqrt15_2 * cd * csd * cp2; + *dw++ = x->x_sqrt15_2 * cd * csd * sp2; + *dw++ = x->x_sqrt6_4 * cd * (5.0 * sd2 - 1.0) * cp; + *dw++ = x->x_sqrt6_4 * cd * (5.0 * sd2 - 1.0) * sp; + *dw++ = 0.5 * sd * (5.0 * sd2 - 3.0); + + if(order >= 4) + { + cp4 = cos(4.0*phi); + sp4 = sin(4.0*phi); + *dw++ = x->x_sqrt35_8 * cd2 * cd2 * cp4; + *dw++ = x->x_sqrt35_8 * cd2 * cd2 * sp4; + *dw++ = x->x_sqrt70_4 * cd2 * csd * cp3; + *dw++ = x->x_sqrt70_4 * cd2 * csd * sp3; + *dw++ = 0.5 * x->x_sqrt5_2 * cd2 * (7.0 * sd2 - 1.0) * cp2; + *dw++ = 0.5 * x->x_sqrt5_2 * cd2 * (7.0 * sd2 - 1.0) * sp2; + *dw++ = x->x_sqrt10_4 * csd * (7.0 * sd2 - 3.0) * cp; + *dw++ = x->x_sqrt10_4 * csd * (7.0 * sd2 - 3.0) * sp; + *dw++ = 0.125 * (sd2 * (35.0 * sd2 - 30.0) + 3.0); + + if(order >= 5) + { + *dw++ = x->x_sqrt126_16 * cd3 * cd2 * cos(5.0*phi); + *dw++ = x->x_sqrt126_16 * cd3 * cd2 * sin(5.0*phi); + *dw++ = x->x_sqrt315_8 * cd3 * csd * cp4; + *dw++ = x->x_sqrt315_8 * cd3 * csd * sp4; + *dw++ = 0.25 * x->x_sqrt70_4 * cd3 * (9.0 * sd2 - 1.0) * cp3; + *dw++ = 0.25 * x->x_sqrt70_4 * cd3 * (9.0 * sd2 - 1.0) * sp3; + *dw++ = x->x_sqrt105_4 * cd * csd * (3.0 * sd2 - 1.0) * cp2; + *dw++ = x->x_sqrt105_4 * cd * csd * (3.0 * sd2 - 1.0) * sp2; + *dw++ = 0.25 * x->x_sqrt15_2 * cd * (sd2 * (21.0 * sd2 - 14.0) + 1.0) * cp; + *dw++ = 0.25 * x->x_sqrt15_2 * cd * (sd2 * (21.0 * sd2 - 14.0) + 1.0) * sp; + *dw = 0.125 * sd * (sd2 * (63.0 * sd2 - 70.0) + 15.0); + } + } + } + } +} + +static void ambi_decode3_real_ls(t_ambi_decode3 *x, t_symbol *s, int argc, t_atom *argv) +{ + if(x->x_n_dim == 2) + ambi_decode3_encode_ls_2d(x, argc, argv, AMBI_LS_REAL); + else + ambi_decode3_encode_ls_3d(x, argc, argv, AMBI_LS_REAL); +} + +static void ambi_decode3_pht_ls(t_ambi_decode3 *x, t_symbol *s, int argc, t_atom *argv) +{ + if(x->x_n_dim == 2) + ambi_decode3_encode_ls_2d(x, argc, argv, AMBI_LS_PHT); + else + ambi_decode3_encode_ls_3d(x, argc, argv, AMBI_LS_PHT); +} + +static void ambi_decode3_ambi_weight(t_ambi_decode3 *x, t_symbol *s, int argc, t_atom *argv) +{ + if(argc > x->x_n_order) + { + int i, k=0, n=x->x_n_order; + double d; + + x->x_ambi_channel_weight[k] = atom_getfloat(argv++); + k++; + if(x->x_n_dim == 2) + { + for(i=1; i<=n; i++) + { + d = atom_getfloat(argv++); + x->x_ambi_channel_weight[k] = d; + k++; + x->x_ambi_channel_weight[k] = d; + k++; + } + } + else + { + int j, m; + + for(i=1; i<=n; i++) + { + d = atom_getfloat(argv++); + m = 2*i + 1; + for(j=0; jx_ambi_channel_weight[k] = d; + k++; + } + } + } + } + else + post("ambi_decode3-ERROR: ambi_weight needs %d float weights", x->x_n_order+1); +} + +static void ambi_decode3_sing_range(t_ambi_decode3 *x, t_floatarg f) +{ + if(f < 0.0f) + x->x_sing_range = -(double)f; + else + x->x_sing_range = (double)f; +} + +static void ambi_decode3_free(t_ambi_decode3 *x) +{ + freebytes(x->x_inv_work1, x->x_n_ambi * x->x_n_ambi * sizeof(double)); + freebytes(x->x_inv_work2, 2 * x->x_n_ambi * x->x_n_ambi * sizeof(double)); + freebytes(x->x_inv_buf2, 2 * x->x_n_ambi * sizeof(double)); + freebytes(x->x_transp, (x->x_n_real_ls+x->x_n_pht_ls) * x->x_n_ambi * sizeof(double)); + freebytes(x->x_ls_encode, (x->x_n_real_ls+x->x_n_pht_ls) * x->x_n_ambi * sizeof(double)); + freebytes(x->x_prod, (x->x_n_real_ls+x->x_n_pht_ls) * x->x_n_ambi * sizeof(double)); + freebytes(x->x_ambi_channel_weight, x->x_n_ambi * sizeof(double)); + freebytes(x->x_at, (x->x_n_real_ls * x->x_n_ambi + 2) * sizeof(t_atom)); +} + +static void *ambi_decode3_new(t_symbol *s, int argc, t_atom *argv) +{ + t_ambi_decode3 *x = (t_ambi_decode3 *)pd_new(ambi_decode3_class); + int order, dim, i; + int n_real_ls=0;/* number of loudspeakers */ + int n_pht_ls=0;/* number of phantom_loudspeakers */ + + if((argc >= 4) && + IS_A_FLOAT(argv,0) && + IS_A_FLOAT(argv,1) && + IS_A_FLOAT(argv,2) && + IS_A_FLOAT(argv,3)) + { + order = (int)atom_getint(argv++); + dim = (int)atom_getint(argv++); + n_real_ls = (int)atom_getint(argv++); + n_pht_ls = (int)atom_getint(argv); + + if(order < 1) + order = 1; + if(dim != 3) + { + dim = 2; + if(order > 12) + order = 12; + x->x_n_ambi = 2*order + 1; + } + else + { + if(order > 5) + order = 5; + x->x_n_ambi = (order + 1)*(order + 1); + } + x->x_n_dim = dim; + x->x_n_order = order; + if(n_real_ls < 1) + n_real_ls = 1; + if(n_pht_ls < 0) + n_pht_ls = 0; + if((n_real_ls + n_pht_ls) < x->x_n_ambi) + post("ambi_decode3-WARNING: Number of Loudspeakers < Number of Ambisonic-Channels !!!!"); + + x->x_n_real_ls = n_real_ls; + x->x_n_pht_ls = n_pht_ls; + x->x_inv_work1 = (double *)getbytes(x->x_n_ambi * x->x_n_ambi * sizeof(double)); + x->x_inv_work2 = (double *)getbytes(2 * x->x_n_ambi * x->x_n_ambi * sizeof(double)); + x->x_inv_buf2 = (double *)getbytes(2 * x->x_n_ambi * sizeof(double)); + x->x_transp = (double *)getbytes((x->x_n_real_ls+x->x_n_pht_ls) * x->x_n_ambi * sizeof(double)); + x->x_ls_encode = (double *)getbytes((x->x_n_real_ls+x->x_n_pht_ls) * x->x_n_ambi * sizeof(double)); + x->x_prod = (double *)getbytes((x->x_n_real_ls+x->x_n_pht_ls) * x->x_n_ambi * sizeof(double)); + x->x_ambi_channel_weight = (double *)getbytes(x->x_n_ambi * sizeof(double)); + x->x_at = (t_atom *)getbytes((x->x_n_real_ls * x->x_n_ambi + 2) * sizeof(t_atom)); + x->x_s_matrix = gensym("matrix"); + /*change*/ + SETFLOAT(x->x_at, (float)x->x_n_real_ls); + SETFLOAT(x->x_at+1, (float)x->x_n_ambi); + + x->x_sqrt3 = sqrt(3.0); + x->x_sqrt5_2 = sqrt(5.0) / 2.0; + x->x_sqrt6_4 = sqrt(6.0) / 4.0; + x->x_sqrt10_4 = sqrt(10.0) / 4.0; + x->x_sqrt15_2 = sqrt(15.0) / 2.0; + x->x_sqrt35_8 = sqrt(35.0) / 8.0; + x->x_sqrt70_4 = sqrt(70.0) / 4.0; + x->x_sqrt126_16 = sqrt(126.0) / 16.0; + x->x_sqrt315_8 = sqrt(315.0) / 8.0; + x->x_sqrt105_4 = sqrt(105.0) / 4.0; + x->x_pi_over_180 = 4.0 * atan(1.0) / 180.0; + x->x_sing_range = 1.0e-10; + for(i=0; ix_n_ambi; i++) + x->x_ambi_channel_weight[i] = 1.0; + outlet_new(&x->x_obj, &s_list); + return (x); + } + else + { + post("ambi_decode3-ERROR: need 4 float arguments: ambi_order dimension number_of_real_loudspeakers number_of_canceled_phantom_speakers"); + return(0); + } +} + +void ambi_decode3_setup(void) +{ + ambi_decode3_class = class_new(gensym("ambi_decode3"), (t_newmethod)ambi_decode3_new, (t_method)ambi_decode3_free, + sizeof(t_ambi_decode3), 0, A_GIMME, 0); + class_addmethod(ambi_decode3_class, (t_method)ambi_decode3_real_ls, gensym("real_ls"), A_GIMME, 0); + class_addmethod(ambi_decode3_class, (t_method)ambi_decode3_pht_ls, gensym("pht_ls"), A_GIMME, 0); + class_addmethod(ambi_decode3_class, (t_method)ambi_decode3_ambi_weight, gensym("ambi_weight"), A_GIMME, 0); + class_addmethod(ambi_decode3_class, (t_method)ambi_decode3_sing_range, gensym("sing_range"), A_DEFFLOAT, 0); + class_addmethod(ambi_decode3_class, (t_method)ambi_decode3_begin_pseudo_inverse, gensym("begin_pseudo_inverse"), 0); + class_addmethod(ambi_decode3_class, (t_method)ambi_decode3_ipht_ireal_muladd, gensym("ipht_ireal_muladd"), A_GIMME, 0); + class_addmethod(ambi_decode3_class, (t_method)ambi_decode3_end_pseudo_inverse, gensym("end_pseudo_inverse"), 0); + class_sethelpsymbol(ambi_decode3_class, gensym("iemhelp2/help-ambi_decode3")); +} diff --git a/src/ambi_decode_cube.c b/src/ambi_decode_cube.c new file mode 100644 index 0000000..741781d --- /dev/null +++ b/src/ambi_decode_cube.c @@ -0,0 +1,799 @@ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. + +iem_ambi written by Thomas Musil, Copyright (c) IEM KUG Graz Austria 2000 - 2005 */ + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + + +#include "m_pd.h" +#include "iemlib.h" +#include +#include +#include + + + +/* -------------------------- ambi_decode_cube ------------------------------ */ +/* + ** berechnet ein reduziertes Ambisonic-Decoder-Set in die HRTF-Spektren ** + ** Inputs: ls + Liste von 3 floats: Index [1 .. 25] + Elevation [-90 .. +90 degree] + Azimut [0 .. 360 degree] ** + ** Inputs: calc_inv ** + ** Inputs: load_HRIR + float index1..25 ** + ** Outputs: List of 2 symbols: left-HRIR-File-name + HRIR-table-name ** + ** Inputs: calc_reduced ** + ** "output" ... writes the HRTF into tables ** + ** ** + ** ** + ** setzt voraus , dass die HRIR-tabele-names von LS1_L_HRIR .. LS25_L_HRIR heissen und existieren ** + ** setzt voraus , dass die HRTF-tabele-names von LS1_HRTF_re .. LS25_HRTF_re heissen und existieren ** + ** setzt voraus , dass die HRTF-tabele-names von LS1_HRTF_im .. LS25_HRTF_im heissen und existieren ** + */ + +typedef struct _ambi_decode_cube +{ + t_object x_obj; + t_atom *x_at; + double *x_inv_work1; + double *x_inv_work2; + double *x_inv_buf2; + double *x_transp; + double *x_ls_encode; + double *x_prod; + double *x_ambi_channel_weight; + double x_mir_wght; + int x_n_ambi; + int x_n_order; + int x_n_ls; + int x_n_phls; + int x_n_dim; + int x_realsum_beg; + int x_realsum_end; + int x_mirrorsum_beg; + int x_mirrorsum_end; + t_symbol *x_s_matrix; + double x_sqrt3; + double x_sqrt10_4; + double x_sqrt15_2; + double x_sqrt6_4; + double x_sqrt35_8; + double x_sqrt70_4; + double x_sqrt5_2; + double x_sqrt126_16; + double x_sqrt315_8; + double x_sqrt105_4; + double x_pi_over_180; +} t_ambi_decode_cube; + +static t_class *ambi_decode_cube_class; + +static void ambi_decode_cube_copy_row2buf(t_ambi_decode_cube *x, int row) +{ + int n_ambi2 = 2*x->x_n_ambi; + int i; + double *dw=x->x_inv_work2; + double *db=x->x_inv_buf2; + + dw += row*n_ambi2; + for(i=0; ix_n_ambi; + int i; + double *dw=x->x_inv_work2; + double *db=x->x_inv_buf2; + + dw += row*n_ambi2; + for(i=0; ix_n_ambi; + int i; + double *dw_src=x->x_inv_work2; + double *dw_dst=x->x_inv_work2; + + dw_src += src_row*n_ambi2; + dw_dst += dst_row*n_ambi2; + for(i=0; ix_n_ambi; + int i; + double *dw=x->x_inv_work2; + + dw += row*n_ambi2; + for(i=0; ix_n_ambi; + int i; + double *dw=x->x_inv_work2; + double *db=x->x_inv_buf2; + + dw += row*n_ambi2; + for(i=0; ix_n_ambi; + int n_ambi2 = 2*n_ambi; + int i, j; + double *dw=x->x_inv_work2; + int ret=-1; + + dw += start_row*n_ambi2 + col; + j = 0; + for(i=start_row; i 1.0e-10) || (*dw < -1.0e-10)) + { + ret = i; + i = n_ambi+1; + } + dw += n_ambi2; + } + return(ret); +} + +static void ambi_decode_cube_mul1(t_ambi_decode_cube *x) +{ + double *vec1, *beg1=x->x_ls_encode; + double *vec2, *beg2=x->x_ls_encode; + double *inv=x->x_inv_work1; + double sum; + int n_ls=x->x_n_ls+x->x_n_phls; + int n_ambi=x->x_n_ambi; + int i, j, k; + + for(k=0; kx_ls_encode; + for(j=0; jx_n_ls+x->x_n_phls; + int n_ambi=x->x_n_ambi; + int n_ambi2=2*n_ambi; + int i, j, k; + double *vec1, *beg1=x->x_transp; + double *vec2, *beg2=x->x_inv_work2+n_ambi; + double *vec3=x->x_prod; + double *acw_vec=x->x_ambi_channel_weight; + double sum; + + for(k=0; kx_inv_work2+n_ambi; + for(j=0; jx_transp; + double *straight=x->x_ls_encode; + int n_ls=x->x_n_ls+x->x_n_phls; + int n_ambi=x->x_n_ambi; + int i, j; + + for(j=0; jx_n_ambi; + int n_ambi2 = 2*n_ambi; + int i, j, nz; + int r,c; + double *src=x->x_inv_work1; + double *db=x->x_inv_work2; + double rcp, *dv; + + dv = db; + for(i=0; i=0; i--) + { + dv = db + i*n_ambi2 + i; + ambi_decode_cube_copy_row2buf(x, i); + for(j=i-1; j>=0; j--) + { + dv -= n_ambi2; + rcp = -(*dv); + ambi_decode_cube_mul_buf_and_add2row(x, j, rcp); + } + } + + post("matrix_inverse regular"); +} + +static void ambi_decode_cube_pinv(t_ambi_decode_cube *x) +{ + t_atom *at=x->x_at; + + ambi_decode_cube_transp_back(x); + ambi_decode_cube_mul1(x); + ambi_decode_cube_inverse(x); + ambi_decode_cube_mul2(x); + if((x->x_mirrorsum_end > x->x_mirrorsum_beg)&& + (x->x_realsum_end > x->x_realsum_beg)&& + ((x->x_mirrorsum_end - x->x_mirrorsum_beg) == (x->x_realsum_end - x->x_realsum_beg))) + { + double *mir=x->x_prod+x->x_mirrorsum_beg*x->x_n_ambi; + double *real=x->x_prod+x->x_realsum_beg*x->x_n_ambi; + double mwght=x->x_mir_wght; + int i, n=(x->x_mirrorsum_end - x->x_mirrorsum_beg)*x->x_n_ambi; + +// post("mirror"); + for(i=0; ix_mirrorsum_beg*x->x_n_ambi; + real=x->x_prod; + SETFLOAT(at, (float)x->x_n_ambi); + at++; + SETFLOAT(at, (float)x->x_mirrorsum_beg); + at++; + for(i=0; ix_obj.ob_outlet, x->x_s_matrix, n+2, x->x_at); + } + else + { + int i, n=x->x_n_ls*x->x_n_ambi; + double *dv=x->x_prod; + +// post("real"); + SETFLOAT(at, (float)x->x_n_ambi); + at++; + SETFLOAT(at, (float)x->x_n_ls); + at++; + for(i=0; ix_obj.ob_outlet, x->x_s_matrix, n+2, x->x_at); + } +} + +static void ambi_decode_cube_encode_ls_2d(t_ambi_decode_cube *x, int argc, t_atom *argv, int ls0_ph1) +{ + double phi; + double *dw = x->x_transp; + int index; + int n_ls=x->x_n_ls; + int n_phls=x->x_n_phls; + int order=x->x_n_order; + + if(argc < 2) + { + post("ambi_decode_cube ERROR: ls-input needs 1 index and 1 angle: ls_index + phi [degree]"); + return; + } + index = (int)atom_getint(argv++) - 1; + phi = (double)atom_getfloat(argv); + + if(index < 0) + index = 0; + if(ls0_ph1) + { + if(n_phls) + { + if(index >= n_phls) + index = n_phls - 1; + index += n_ls; + } + else + return; + } + else + { + if(index >= n_ls) + index = n_ls - 1; + } + + phi *= x->x_pi_over_180; + + dw += index * x->x_n_ambi; + + *dw++ = 1.0; + *dw++ = cos(phi); + *dw++ = sin(phi); + + if(order >= 2) + { + *dw++ = cos(2.0*phi); + *dw++ = sin(2.0*phi); + + if(order >= 3) + { + *dw++ = cos(3.0*phi); + *dw++ = sin(3.0*phi); + + if(order >= 4) + { + *dw++ = cos(4.0*phi); + *dw++ = sin(4.0*phi); + + if(order >= 5) + { + *dw++ = cos(5.0*phi); + *dw++ = sin(5.0*phi); + + if(order >= 6) + { + *dw++ = cos(6.0*phi); + *dw++ = sin(6.0*phi); + + if(order >= 7) + { + *dw++ = cos(7.0*phi); + *dw++ = sin(7.0*phi); + + if(order >= 8) + { + *dw++ = cos(8.0*phi); + *dw++ = sin(8.0*phi); + + if(order >= 9) + { + *dw++ = cos(9.0*phi); + *dw++ = sin(9.0*phi); + + if(order >= 10) + { + *dw++ = cos(10.0*phi); + *dw++ = sin(10.0*phi); + + if(order >= 11) + { + *dw++ = cos(11.0*phi); + *dw++ = sin(11.0*phi); + + if(order >= 12) + { + *dw++ = cos(12.0*phi); + *dw++ = sin(12.0*phi); + } + } + } + } + } + } + } + } + } + } + } +} + +static void ambi_decode_cube_encode_ls_3d(t_ambi_decode_cube *x, int argc, t_atom *argv, int ls0_ph1) +{ + double delta, phi; + double cd, sd, cd2, cd3, sd2, csd, cp, sp, cp2, sp2, cp3, sp3, cp4, sp4; + double *dw = x->x_transp; + int index; + int n_ls=x->x_n_ls; + int n_phls=x->x_n_phls; + int order=x->x_n_order; + + if(argc < 3) + { + post("ambi_decode_cube ERROR: ls-input needs 1 index and 2 angles: ls index + delta [degree] + phi [degree]"); + return; + } + index = (int)atom_getint(argv++) - 1; + delta = atom_getfloat(argv++); + phi = atom_getfloat(argv); + + if(index < 0) + index = 0; + if(ls0_ph1) + { + if(n_phls) + { + if(index >= n_phls) + index = n_phls - 1; + index += n_ls; + } + else + return; + } + else + { + if(index >= n_ls) + index = n_ls - 1; + } + + delta *= x->x_pi_over_180; + phi *= x->x_pi_over_180; + + dw += index * x->x_n_ambi; + + cd = cos(delta); + sd = sin(delta); + cp = cos(phi); + sp = sin(phi); + + *dw++ = 1.0; + *dw++ = cd * cp; + *dw++ = cd * sp; + *dw++ = sd; + + if(order >= 2) + { + cp2 = cos(2.0*phi); + sp2 = sin(2.0*phi); + cd2 = cd * cd; + sd2 = sd * sd; + csd = cd * sd; + *dw++ = 0.5 * x->x_sqrt3 * cd2 * cp2; + *dw++ = 0.5 * x->x_sqrt3 * cd2 * sp2; + *dw++ = x->x_sqrt3 * csd * cp; + *dw++ = x->x_sqrt3 * csd * sp; + *dw++ = 0.5 * (3.0 * sd2 - 1.0); + + if(order >= 3) + { + cp3 = cos(3.0*phi); + sp3 = sin(3.0*phi); + cd3 = cd2 * cd; + *dw++ = x->x_sqrt10_4 * cd3 * cp3; + *dw++ = x->x_sqrt10_4 * cd3 * sp3; + *dw++ = x->x_sqrt15_2 * cd * csd * cp2; + *dw++ = x->x_sqrt15_2 * cd * csd * sp2; + *dw++ = x->x_sqrt6_4 * cd * (5.0 * sd2 - 1.0) * cp; + *dw++ = x->x_sqrt6_4 * cd * (5.0 * sd2 - 1.0) * sp; + *dw++ = 0.5 * sd * (5.0 * sd2 - 3.0); + + if(order >= 4) + { + cp4 = cos(4.0*phi); + sp4 = sin(4.0*phi); + *dw++ = x->x_sqrt35_8 * cd2 * cd2 * cp4; + *dw++ = x->x_sqrt35_8 * cd2 * cd2 * sp4; + *dw++ = x->x_sqrt70_4 * cd2 * csd * cp3; + *dw++ = x->x_sqrt70_4 * cd2 * csd * sp3; + *dw++ = 0.5 * x->x_sqrt5_2 * cd2 * (7.0 * sd2 - 1.0) * cp2; + *dw++ = 0.5 * x->x_sqrt5_2 * cd2 * (7.0 * sd2 - 1.0) * sp2; + *dw++ = x->x_sqrt10_4 * csd * (7.0 * sd2 - 3.0) * cp; + *dw++ = x->x_sqrt10_4 * csd * (7.0 * sd2 - 3.0) * sp; + *dw++ = 0.125 * (sd2 * (35.0 * sd2 - 30.0) + 3.0); + + if(order >= 5) + { + *dw++ = x->x_sqrt126_16 * cd3 * cd2 * cos(5.0*phi); + *dw++ = x->x_sqrt126_16 * cd3 * cd2 * sin(5.0*phi); + *dw++ = x->x_sqrt315_8 * cd3 * csd * cp4; + *dw++ = x->x_sqrt315_8 * cd3 * csd * sp4; + *dw++ = 0.25 * x->x_sqrt70_4 * cd3 * (9.0 * sd2 - 1.0) * cp3; + *dw++ = 0.25 * x->x_sqrt70_4 * cd3 * (9.0 * sd2 - 1.0) * sp3; + *dw++ = x->x_sqrt105_4 * cd * csd * (3.0 * sd2 - 1.0) * cp2; + *dw++ = x->x_sqrt105_4 * cd * csd * (3.0 * sd2 - 1.0) * sp2; + *dw++ = 0.25 * x->x_sqrt15_2 * cd * (sd2 * (21.0 * sd2 - 14.0) + 1.0) * cp; + *dw++ = 0.25 * x->x_sqrt15_2 * cd * (sd2 * (21.0 * sd2 - 14.0) + 1.0) * sp; + *dw = 0.125 * sd * (sd2 * (63.0 * sd2 - 70.0) + 15.0); + } + } + } + } +} + +static void ambi_decode_cube_ls(t_ambi_decode_cube *x, t_symbol *s, int argc, t_atom *argv) +{ + if(x->x_n_dim == 2) + ambi_decode_cube_encode_ls_2d(x, argc, argv, 0); + else + ambi_decode_cube_encode_ls_3d(x, argc, argv, 0); +} + +static void ambi_decode_cube_phls(t_ambi_decode_cube *x, t_symbol *s, int argc, t_atom *argv) +{ + if(x->x_n_dim == 2) + ambi_decode_cube_encode_ls_2d(x, argc, argv, 1); + else + ambi_decode_cube_encode_ls_3d(x, argc, argv, 1); +} + +static void ambi_decode_cube_ambi_weight(t_ambi_decode_cube *x, t_symbol *s, int argc, t_atom *argv) +{ + if(argc > x->x_n_order) + { + int i, k=0, n=x->x_n_order; + double d; + + x->x_ambi_channel_weight[k] = atom_getfloat(argv++); + k++; + if(x->x_n_dim == 2) + { + for(i=1; i<=n; i++) + { + d = atom_getfloat(argv++); + x->x_ambi_channel_weight[k] = d; + k++; + x->x_ambi_channel_weight[k] = d; + k++; + } + } + else + { + int j, m; + + for(i=1; i<=n; i++) + { + d = atom_getfloat(argv++); + m = 2*i + 1; + for(j=0; jx_ambi_channel_weight[k] = d; + k++; + } + } + } + } + else + post("ambi_decode_cube-ERROR: ambi_weight needs %d float weights", x->x_n_order+1); +} + +static void ambi_decode_cube_mirror_weight(t_ambi_decode_cube *x, t_floatarg mwght) +{ + x->x_mir_wght = mwght; +} + +static void ambi_decode_cube_mirror_range(t_ambi_decode_cube *x, t_floatarg beg, t_floatarg end) +{ + int b=(int)beg; + int e=(int)end; + + if(b < 0) + b = 0; + if(b > x->x_n_ls) + b = x->x_n_ls; + if(e < 0) + e = 0; + if(e > x->x_n_ls) + e = x->x_n_ls; + x->x_mirrorsum_beg = b; + x->x_mirrorsum_end = e; +} + +static void ambi_decode_cube_real_sum_range(t_ambi_decode_cube *x, t_floatarg beg, t_floatarg end) +{ + int b=(int)beg; + int e=(int)end; + + if(b < 0) + b = 0; + if(b > x->x_n_ls) + b = x->x_n_ls; + if(e < 0) + e = 0; + if(e > x->x_n_ls) + e = x->x_n_ls; + x->x_realsum_beg = b; + x->x_realsum_end = e; +} + +static void ambi_decode_cube_free(t_ambi_decode_cube *x) +{ + freebytes(x->x_inv_work1, x->x_n_ambi * x->x_n_ambi * sizeof(double)); + freebytes(x->x_inv_work2, 2 * x->x_n_ambi * x->x_n_ambi * sizeof(double)); + freebytes(x->x_inv_buf2, 2 * x->x_n_ambi * sizeof(double)); + freebytes(x->x_transp, (x->x_n_ls+x->x_n_phls) * x->x_n_ambi * sizeof(double)); + freebytes(x->x_ls_encode, (x->x_n_ls+x->x_n_phls) * x->x_n_ambi * sizeof(double)); + freebytes(x->x_prod, (x->x_n_ls+x->x_n_phls) * x->x_n_ambi * sizeof(double)); + freebytes(x->x_ambi_channel_weight, x->x_n_ambi * sizeof(double)); + freebytes(x->x_at, (x->x_n_ls * x->x_n_ambi + 2) * sizeof(t_atom)); +} + +static void *ambi_decode_cube_new(t_symbol *s, int argc, t_atom *argv) +{ + t_ambi_decode_cube *x = (t_ambi_decode_cube *)pd_new(ambi_decode_cube_class); + int nls, order, dim, i; + int nphls=0;/* phantom_loudspeaker */ + + if(argc < 3) + { + post("ambi_decode_cube-ERROR: need following arguments: ambi_order dimension number_of_loudspeakers (number_of_phantom_speakers)"); + return(0); + } + else + { + order = (int)atom_getint(argv++); + dim = (int)atom_getint(argv++); + nls = (int)atom_getint(argv++); + if((argc > 3)&&IS_A_FLOAT(argv,0)) + nphls=(int)atom_getint(argv); + + if(order < 1) + order = 1; + if(dim != 3) + { + dim = 2; + if(order > 12) + order = 12; + x->x_n_ambi = 2*order + 1; + } + else + { + if(order > 5) + order = 5; + x->x_n_ambi = (order + 1)*(order + 1); + } + x->x_n_dim = dim; + x->x_n_order = order; + if(nls < 1) + nls = 1; + if(nphls < 0) + nphls = 0; + if(nls < x->x_n_ambi) + post("ambi_decode_cube-WARNING: Number of Loudspeakers < Number of Ambisonic-Channels !!!!"); + if(nphls > nls) + { + post("ambi_decode_cube-WARNING: Number of Phantom-Loudspeakers > Number of Loudspeakers !!!!"); + nphls = nls; + } + x->x_n_ls = nls; + x->x_n_phls = nphls; + x->x_inv_work1 = (double *)getbytes(x->x_n_ambi * x->x_n_ambi * sizeof(double)); + x->x_inv_work2 = (double *)getbytes(2 * x->x_n_ambi * x->x_n_ambi * sizeof(double)); + x->x_inv_buf2 = (double *)getbytes(2 * x->x_n_ambi * sizeof(double)); + x->x_transp = (double *)getbytes((x->x_n_ls+x->x_n_phls) * x->x_n_ambi * sizeof(double)); + x->x_ls_encode = (double *)getbytes((x->x_n_ls+x->x_n_phls) * x->x_n_ambi * sizeof(double)); + x->x_prod = (double *)getbytes((x->x_n_ls+x->x_n_phls) * x->x_n_ambi * sizeof(double)); + x->x_ambi_channel_weight = (double *)getbytes(x->x_n_ambi * sizeof(double)); + x->x_at = (t_atom *)getbytes((x->x_n_ls * x->x_n_ambi + 2) * sizeof(t_atom)); + x->x_s_matrix = gensym("matrix"); + /*change*/ + SETFLOAT(x->x_at, (float)x->x_n_ls); + SETFLOAT(x->x_at+1, (float)x->x_n_ambi); + x->x_sqrt3 = sqrt(3.0); + x->x_sqrt5_2 = sqrt(5.0) / 2.0; + x->x_sqrt6_4 = sqrt(6.0) / 4.0; + x->x_sqrt10_4 = sqrt(10.0) / 4.0; + x->x_sqrt15_2 = sqrt(15.0) / 2.0; + x->x_sqrt35_8 = sqrt(35.0) / 8.0; + x->x_sqrt70_4 = sqrt(70.0) / 4.0; + x->x_sqrt126_16 = sqrt(126.0) / 16.0; + x->x_sqrt315_8 = sqrt(315.0) / 8.0; + x->x_sqrt105_4 = sqrt(105.0) / 4.0; + x->x_pi_over_180 = 4.0 * atan(1.0) / 180.0; + x->x_mirrorsum_beg = x->x_n_ls; + x->x_mirrorsum_end = x->x_n_ls; + x->x_realsum_beg = 0; + x->x_realsum_end = 0; + for(i=0; ix_n_ambi; i++) + x->x_ambi_channel_weight[i] = 1.0; + x->x_mir_wght = 1.0; + outlet_new(&x->x_obj, &s_list); + return (x); + } +} + +void ambi_decode_cube_setup(void) +{ + ambi_decode_cube_class = class_new(gensym("ambi_decode_cube"), (t_newmethod)ambi_decode_cube_new, (t_method)ambi_decode_cube_free, + sizeof(t_ambi_decode_cube), 0, A_GIMME, 0); + class_addmethod(ambi_decode_cube_class, (t_method)ambi_decode_cube_ls, gensym("ls"), A_GIMME, 0); + class_addmethod(ambi_decode_cube_class, (t_method)ambi_decode_cube_phls, gensym("phls"), A_GIMME, 0); + class_addmethod(ambi_decode_cube_class, (t_method)ambi_decode_cube_ambi_weight, gensym("ambi_weight"), A_GIMME, 0); + class_addmethod(ambi_decode_cube_class, (t_method)ambi_decode_cube_pinv, gensym("pinv"), 0); + class_addmethod(ambi_decode_cube_class, (t_method)ambi_decode_cube_mirror_weight, gensym("mirror_weight"), A_DEFFLOAT, 0); + class_addmethod(ambi_decode_cube_class, (t_method)ambi_decode_cube_mirror_range, gensym("mirror_range"), A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(ambi_decode_cube_class, (t_method)ambi_decode_cube_real_sum_range, gensym("real_sum_range"), A_DEFFLOAT, A_DEFFLOAT, 0); + class_sethelpsymbol(ambi_decode_cube_class, gensym("iemhelp/help-ambi_decode_cube")); +} diff --git a/src/ambi_encode.c b/src/ambi_encode.c new file mode 100644 index 0000000..3ca69a2 --- /dev/null +++ b/src/ambi_encode.c @@ -0,0 +1,433 @@ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. + +iem_ambi written by Thomas Musil, Copyright (c) IEM KUG Graz Austria 2000 - 2005 */ + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + + +#include "m_pd.h" +#include "iemlib.h" +#include +#include +#include + +/* -------------------------- ambi_encode ------------------------------ */ + +typedef struct _ambi_encode +{ + t_object x_obj; + t_atom *x_at; + int x_size; + int x_size2d; + int x_size3d; + float x_sqrt3; + float x_sqrt10_4; + float x_sqrt15; + float x_sqrt6_4; + float x_sqrt35_2; + float x_sqrt70_4; + float x_sqrt5_2; + float x_sqrt126_16; + float x_sqrt315_2; + float x_sqrt105_2; + float x_pi_over_180; + float *x_ambi_order_weight; + int x_colrow; + int x_n_order; +} t_ambi_encode; + +static t_class *ambi_encode_class; + +static void ambi_encode_ambi_weight(t_ambi_encode *x, t_symbol *s, int argc, t_atom *argv) +{ + if(argc > x->x_n_order) + { + int i, n=x->x_n_order; + + for(i=0; i<=n; i++) + { + x->x_ambi_order_weight[i] = atom_getfloat(argv++); + } + } + else + post("ambi_encode-ERROR: ambi_weight needs %d float weights", x->x_n_order+1); +} + +static void ambi_encode_do_2d(t_ambi_encode *x, t_floatarg phi) +{ + float c, s, cc, ss, c2, s2, c3, s3, s4, c4, s5, c5, s6, c6; + float *awght = x->x_ambi_order_weight; + t_atom *at=x->x_at; + + phi *= x->x_pi_over_180; + c = cos(phi); + s = sin(phi); + cc = c*c; + ss = s*s; + + SETFLOAT(at, (float)x->x_colrow); + at++; + + SETFLOAT(at, awght[0]); + at++; + + SETFLOAT(at, c*awght[1]); + at++; + SETFLOAT(at, s*awght[1]); + at++; + + if(x->x_n_order >= 2) + { + c2 = cc - ss; + s2 = 2.0f*s*c; + SETFLOAT(at, c2*awght[2]); + at++; + SETFLOAT(at, s2*awght[2]); + at++; + + if(x->x_n_order >= 3) + { + c3 = c*(4.0f*cc - 3.0f); + s3 = s*(3.0f - 4.0f*ss); + SETFLOAT(at, c3*awght[3]); + at++; + SETFLOAT(at, s3*awght[3]); + at++; + + if(x->x_n_order >= 4) + { + c4 = 1.0f + 8.0f*cc*(cc - 1.0f); + s4 = 2.0f*s2*c2; + SETFLOAT(at, c4*awght[4]); + at++; + SETFLOAT(at, s4*awght[4]); + at++; + + if(x->x_n_order >= 5) + { + c5 = c*(1.0f + 4.0f*ss*(ss - 3.0f*cc)); + s5 = s*(1.0f + 4.0f*cc*(cc - 3.0f*ss)); + SETFLOAT(at, c5*awght[5]); + at++; + SETFLOAT(at, s5*awght[5]); + at++; + + if(x->x_n_order >= 6) + { + c6 = c3*c3 - s3*s3; + s6 = 2.0f*s3*c3; + SETFLOAT(at, c6*awght[6]); + at++; + SETFLOAT(at, s6*awght[6]); + at++; + + if(x->x_n_order >= 7) + { + SETFLOAT(at, cos(7.0f*phi)*awght[7]); + at++; + SETFLOAT(at, sin(7.0f*phi)*awght[7]); + at++; + + if(x->x_n_order >= 8) + { + SETFLOAT(at, (c4*c4 - s4*s4)*awght[8]); + at++; + SETFLOAT(at, 2.0f*s4*c4*awght[8]); + at++; + + if(x->x_n_order >= 9) + { + SETFLOAT(at, cos(9.0f*phi)*awght[9]); + at++; + SETFLOAT(at, sin(9.0f*phi)*awght[9]); + at++; + + if(x->x_n_order >= 10) + { + SETFLOAT(at, (c5*c5 - s5*s5)*awght[10]); + at++; + SETFLOAT(at, 2.0f*s5*c5*awght[10]); + at++; + + if(x->x_n_order >= 11) + { + SETFLOAT(at, cos(11.0f*phi)*awght[11]); + at++; + SETFLOAT(at, sin(11.0f*phi)*awght[11]); + at++; + + if(x->x_n_order >= 12) + { + SETFLOAT(at, (c6*c6 - s6*s6)*awght[12]); + at++; + SETFLOAT(at, 2.0f*s6*c6*awght[12]); + } + + if(x->x_n_order >= 13) + post("ambi_encode-ERROR: do not support Ambisonic-Order greater than 12 in 2d !!!"); + + } + } + } + } + } + } + } + } + } + } +} + +static void ambi_encode_do_3d(t_ambi_encode *x, t_symbol *s, int argc, t_atom *argv) +{ + float delta, phi; + float cd, x1, y, z, x2, y2, z2, x2my2, x2m3y2, p3x2my2, xy, xz, yz, m1p5z2, m1p7z2, m3p7z2; + float *awght = x->x_ambi_order_weight; + t_atom *at=x->x_at; + + delta = atom_getfloat(argv++)*x->x_pi_over_180; + phi = atom_getfloat(argv)*x->x_pi_over_180; + + cd = cos(delta); + x1 = cd * cos(phi); + y = cd * sin(phi); + z = sin(delta); + + xy = x1*y; + xz = x1*z; + yz = y*z; + x2 = x1*x1; + y2 = y*y; + z2 = z*z; + + x2my2 = x2 - y2; + x2m3y2 = x2my2 - 2.0f*y2; + p3x2my2 = 2.0f*x2 + x2my2; + m1p5z2 = 5.0f*z2 - 1.0f; + m1p7z2 = 2.0f*z2 + m1p5z2; + m3p7z2 = m1p7z2 - 2.0f; + + SETFLOAT(at, (float)x->x_colrow); + at++; + + SETFLOAT(at, awght[0]); + at++; + + SETFLOAT(at, x1*awght[1]); + at++; + SETFLOAT(at, y*awght[1]); + at++; + SETFLOAT(at, z*awght[1]); + at++; + + if(x->x_n_order >= 2) + { + SETFLOAT(at, 0.5f*x->x_sqrt3*x2my2*awght[2]); + at++; + SETFLOAT(at, x->x_sqrt3*xy*awght[2]); + at++; + SETFLOAT(at, x->x_sqrt3*xz*awght[2]); + at++; + SETFLOAT(at, x->x_sqrt3*yz*awght[2]); + at++; + SETFLOAT(at, 0.5f*(3.0f*z2 - 1.0f)*awght[2]); + at++; + + if(x->x_n_order >= 3) + { + SETFLOAT(at, x->x_sqrt10_4*x1*x2m3y2*awght[3]); + at++; + SETFLOAT(at, x->x_sqrt10_4*y*p3x2my2*awght[3]); + at++; + SETFLOAT(at, 0.5f*x->x_sqrt15*z*x2my2*awght[3]); + at++; + SETFLOAT(at, x->x_sqrt15*xy*z*awght[3]); + at++; + SETFLOAT(at, x->x_sqrt6_4*x1*m1p5z2*awght[3]); + at++; + SETFLOAT(at, x->x_sqrt6_4*y*m1p5z2*awght[3]); + at++; + SETFLOAT(at, 0.5f*z*(m1p5z2 - 2.0f)*awght[3]); + at++; + + if(x->x_n_order >= 4) + { + SETFLOAT(at, 0.25f*x->x_sqrt35_2*(x2my2*x2my2 - 4.0f*x2*y2)*awght[4]); + at++; + SETFLOAT(at, x->x_sqrt35_2*xy*x2my2*awght[4]); + at++; + SETFLOAT(at, x->x_sqrt70_4*xz*x2m3y2*awght[4]); + at++; + SETFLOAT(at, x->x_sqrt70_4*yz*p3x2my2*awght[4]); + at++; + SETFLOAT(at, 0.5f*x->x_sqrt5_2*x2my2*m1p7z2*awght[4]); + at++; + SETFLOAT(at, x->x_sqrt5_2*xy*m1p7z2*awght[4]); + at++; + SETFLOAT(at, x->x_sqrt10_4*xz*m3p7z2*awght[4]); + at++; + SETFLOAT(at, x->x_sqrt10_4*yz*m3p7z2*awght[4]); + at++; + SETFLOAT(at, 0.125f*(5.0f*(z2 - 1.0f)*(m1p7z2 + 2.0f) + 8.0f)*awght[4]); + at++; + + if(x->x_n_order >= 5) + { + SETFLOAT(at, x->x_sqrt126_16*x1*(x2*(x2 - 10.0f*y2) + 5.0f*y2*y2)*awght[5]); + at++; + SETFLOAT(at, x->x_sqrt126_16*y*(y2*(y2 - 10.0f*x2) + 5.0f*x2*x2)*awght[5]); + at++; + SETFLOAT(at, 0.25f*x->x_sqrt315_2*z*(y2*(y2 - 6.0f*x2) + x2*x2)*awght[5]); + at++; + SETFLOAT(at, x->x_sqrt315_2*xy*z*x2my2*awght[5]); + at++; + SETFLOAT(at, 0.25f*x->x_sqrt70_4*x1*(9.0f*z2 - 1.0f)*x2m3y2*awght[5]); + at++; + SETFLOAT(at, 0.25f*x->x_sqrt70_4*y*(9.0f*z2 - 1.0f)*p3x2my2*awght[5]); + at++; + SETFLOAT(at, 0.5f*x->x_sqrt105_2*x2my2*z*(3.0f*z2 - 1.0f)*awght[5]); + at++; + SETFLOAT(at, x->x_sqrt105_2*xy*z*(3.0f*z2 - 1.0f)*awght[5]); + at++; + SETFLOAT(at, 0.125f*x->x_sqrt15*x1*(z2*(21.0f*z2 - 14.0f) + 1.0f)*awght[5]); + at++; + SETFLOAT(at, 0.125f*x->x_sqrt15*y*(z2*(21.0f*z2 - 14.0f) + 1.0f)*awght[5]); + at++; + SETFLOAT(at, 0.125f*z*(z2*(63.0f*z2 - 70.0f) + 15.0f)*awght[5]); + } + + if(x->x_n_order > 5) + post("ambi_encode-ERROR: do not support Ambisonic-Order greater than 5 in 3d !!!"); + } + } + } +} + +static void ambi_encode_float(t_ambi_encode *x, t_floatarg phi) +{ + x->x_colrow = -1; + ambi_encode_do_2d(x, phi); + outlet_list(x->x_obj.ob_outlet, &s_list, x->x_size2d, x->x_at+1); +} + +static void ambi_encode_list(t_ambi_encode *x, t_symbol *s, int argc, t_atom *argv) +{ + if(argc <= 0) + { + post("ambi_encode ERROR: list-input needs 2 angles: delta [rad] and phi [rad]"); + return; + } + else if(argc == 1) + { + ambi_encode_float(x, atom_getfloat(argv)); + } + else + { + x->x_colrow = -1; + ambi_encode_do_3d(x, &s_list, 2, argv); + outlet_list(x->x_obj.ob_outlet, &s_list, x->x_size3d, x->x_at+1); + } +} + +static void ambi_encode_row(t_ambi_encode *x, t_symbol *s, int argc, t_atom *argv) +{ + if(argc == 2) + { + x->x_colrow = (int)atom_getint(argv++); + ambi_encode_do_2d(x, atom_getfloat(argv)); + outlet_anything(x->x_obj.ob_outlet, s, x->x_size2d+1, x->x_at); + } + else if(argc >= 3) + { + x->x_colrow = (int)atom_getint(argv++); + ambi_encode_do_3d(x, &s_list, 2, argv); + outlet_anything(x->x_obj.ob_outlet, s, x->x_size3d+1, x->x_at); + } + else + { + post("ambi_encode-ERROR: row needs row-index + angle ( + angle)"); + } +} + +static void ambi_encode_col(t_ambi_encode *x, t_symbol *s, int argc, t_atom *argv) +{ + if(argc == 2) + { + x->x_colrow = (int)atom_getint(argv++); + ambi_encode_do_2d(x, atom_getfloat(argv)); + outlet_anything(x->x_obj.ob_outlet, s, x->x_size2d+1, x->x_at); + } + else if(argc >= 3) + { + x->x_colrow = (int)atom_getint(argv++); + ambi_encode_do_3d(x, &s_list, 2, argv); + outlet_anything(x->x_obj.ob_outlet, s, x->x_size3d+1, x->x_at); + } + else + { + post("ambi_encode-ERROR: col needs col-index + angle ( + angle)"); + } +} + +static void ambi_encode_free(t_ambi_encode *x) +{ + freebytes(x->x_ambi_order_weight, (x->x_n_order+1) * sizeof(float)); + freebytes(x->x_at, x->x_size * sizeof(t_atom)); +} + +static void *ambi_encode_new(t_floatarg forder) +{ + t_ambi_encode *x = (t_ambi_encode *)pd_new(ambi_encode_class); + t_atom *at; + int i=(int)forder; + + if(i < 1) + i = 1; + if(i > 12) + i = 12; + x->x_n_order = i; + x->x_size = 6*6 + 1; + x->x_size2d = 2*i + 1; + x->x_size3d = (i + 1)*(i + 1); + + x->x_sqrt3 = (float)(sqrt(3.0)); + x->x_sqrt5_2 = (float)(sqrt(5.0) / 2.0); + x->x_sqrt6_4 = (float)(sqrt(6.0) / 4.0); + x->x_sqrt10_4 = (float)(sqrt(10.0) / 4.0); + x->x_sqrt15 = (float)(sqrt(15.0)); + x->x_sqrt35_2 = (float)(sqrt(35.0) / 2.0); + x->x_sqrt70_4 = (float)(sqrt(70.0) / 4.0); + x->x_sqrt126_16 = (float)(sqrt(126.0) / 16.0); + x->x_sqrt315_2 = (float)(sqrt(315.0) / 2.0); + x->x_sqrt105_2 = (float)(sqrt(105.0) / 2.0); + x->x_pi_over_180 = (float)(4.0 * atan(1.0)/180.0); + x->x_colrow = 0; + x->x_ambi_order_weight = (float *)getbytes((x->x_n_order+1) * sizeof(float)); + x->x_at = (t_atom *)getbytes(x->x_size * sizeof(t_atom)); + at=x->x_at; + SETFLOAT(at, -1.0f);/*row index*/ + at++; + SETFLOAT(at, 1.0f);/*W channel*/ + + for(i=0; i<=x->x_n_order; i++) + x->x_ambi_order_weight[i] = 1.0f; + + outlet_new(&x->x_obj, &s_list); + return (x); +} + +void ambi_encode_setup(void) +{ + ambi_encode_class = class_new(gensym("ambi_encode"), (t_newmethod)ambi_encode_new, (t_method)ambi_encode_free, + sizeof(t_ambi_encode), 0, A_DEFFLOAT, 0); + class_addlist(ambi_encode_class, (t_method)ambi_encode_list); + class_addfloat(ambi_encode_class, (t_method)ambi_encode_float); + class_addmethod(ambi_encode_class, (t_method)ambi_encode_row, gensym("row"), A_GIMME, 0); + class_addmethod(ambi_encode_class, (t_method)ambi_encode_col, gensym("col"), A_GIMME, 0); + class_addmethod(ambi_encode_class, (t_method)ambi_encode_ambi_weight, gensym("ambi_weight"), A_GIMME, 0); + class_sethelpsymbol(ambi_encode_class, gensym("iemhelp2/help-ambi_encode")); +} diff --git a/src/ambi_rot.c b/src/ambi_rot.c new file mode 100644 index 0000000..2e23a10 --- /dev/null +++ b/src/ambi_rot.c @@ -0,0 +1,1534 @@ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. + +iem_ambi written by Thomas Musil, Copyright (c) IEM KUG Graz Austria 2000 - 2005 */ + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + + +#include "m_pd.h" +#include "iemlib.h" +#include +#include +#include + + + +/* -------------------------- ambi_rot ------------------------------ */ +/* +ambi_rot : 1. uebergabe-argument : ambisonic-ordnung 1 .. 4; + + input: nur z-rotation; + input: mit 2 floats: nur z*y-rotation; + input: mit 3 floats: z*y*x-rotation; + + output: je nach ordnung: 1 .. 4 -outputs mit selector "matrix" + row + col + ordnung*ordnung-coeff.; +*/ + +typedef struct _ambi_rot +{ + t_object x_obj; + t_atom *x_at2; + int x_size2; + t_atom *x_at3; + int x_size3; + void *x_out3; + t_atom *x_at5; + int x_size5; + void *x_out5; + t_atom *x_at7; + int x_size7; + void *x_out7; + t_atom *x_at9; + int x_size9; + void *x_out9; + t_atom *x_at11; + int x_size11; + void *x_out11; + void *x_out13; + void *x_out15; + void *x_out17; + void *x_out19; + void *x_out21; + void *x_out23; + void *x_out25; + float x_sqrt2_16; + float x_sqrt3_2; + float x_sqrt5_32; + float x_sqrt6_4; + float x_sqrt7_8; + float x_sqrt10_4; + float x_sqrt14_16; + float x_sqrt15_8; + float x_sqrt35_64; + float x_sqrt70_32; + float x_pi_over_180; + t_symbol *x_s_matrix; + int x_order; +} t_ambi_rot; + +static t_class *ambi_rot_class; + +static void ambi_rot_float(t_ambi_rot *x, t_floatarg rho_z) /* = ambi_rot_z(); */ +{ + float c, s, cc, ss, c2, s2, c3, s3, s4, c4, s5, c5, s6, c6, sx, cx; + t_atom *at; + + rho_z *= x->x_pi_over_180; + + c = cos(rho_z); + s = sin(rho_z); + cc = c*c; + ss = s*s; + + if(x->x_order >= 2) + { + c2 = cc - ss; + s2 = 2.0f*s*c; + if(x->x_order >= 3) + { + c3 = c*(4.0f*cc - 3.0f); + s3 = s*(3.0f - 4.0f*ss); + if(x->x_order >= 4) + { + c4 = 1.0f + 8.0f*cc*(cc - 1.0f); + s4 = 2.0f*s2*c2; + if(x->x_order >= 5) + { + c5 = c*(1.0f + 4.0f*ss*(ss - 3.0f*cc)); + s5 = s*(1.0f + 4.0f*cc*(cc - 3.0f*ss)); + if(x->x_order >= 6) + { + c6 = c3*c3 - s3*s3; + s6 = 2.0f*s3*c3; + if(x->x_order >= 7) + { + if(x->x_order >= 8) + { + if(x->x_order >= 9) + { + if(x->x_order >= 10) + { + if(x->x_order >= 11) + { + if(x->x_order >= 12) + { + if(x->x_order >= 13) + post("ambi_rot-ERROR: do not support Ambisonic-Order greater than 12 in z-Rotation !!!"); + + at = x->x_at2; + at += 2; + cx = c6*c6 - s6*s6; + sx = 2.0f*s6*c6; + SETFLOAT(at, cx); + at++; + SETFLOAT(at, -sx); + at++; + SETFLOAT(at, sx); + at++; + SETFLOAT(at, cx); + outlet_anything(x->x_out25, x->x_s_matrix, x->x_size2, x->x_at2); + } + at = x->x_at2; + at += 2; + cx = cos(11.0f*rho_z); + sx = sin(11.0f*rho_z); + SETFLOAT(at, cx); + at++; + SETFLOAT(at, -sx); + at++; + SETFLOAT(at, sx); + at++; + SETFLOAT(at, cx); + outlet_anything(x->x_out23, x->x_s_matrix, x->x_size2, x->x_at2); + } + at = x->x_at2; + at += 2; + cx = c5*c5 - s5*s5; + sx = 2.0f*s5*c5; + SETFLOAT(at, cx); + at++; + SETFLOAT(at, -sx); + at++; + SETFLOAT(at, sx); + at++; + SETFLOAT(at, cx); + outlet_anything(x->x_out21, x->x_s_matrix, x->x_size2, x->x_at2); + } + at = x->x_at2; + at += 2; + cx = cos(9.0f*rho_z); + sx = sin(9.0f*rho_z); + SETFLOAT(at, cx); + at++; + SETFLOAT(at, -sx); + at++; + SETFLOAT(at, sx); + at++; + SETFLOAT(at, cx); + outlet_anything(x->x_out19, x->x_s_matrix, x->x_size2, x->x_at2); + } + at = x->x_at2; + at += 2; + cx = c4*c4 - s4*s4; + sx = 2.0f*s4*c4; + SETFLOAT(at, cx); + at++; + SETFLOAT(at, -sx); + at++; + SETFLOAT(at, sx); + at++; + SETFLOAT(at, cx); + outlet_anything(x->x_out17, x->x_s_matrix, x->x_size2, x->x_at2); + } + at = x->x_at2; + at += 2; + cx = cos(7.0f*rho_z); + sx = sin(7.0f*rho_z); + SETFLOAT(at, cx); + at++; + SETFLOAT(at, -sx); + at++; + SETFLOAT(at, sx); + at++; + SETFLOAT(at, cx); + outlet_anything(x->x_out15, x->x_s_matrix, x->x_size2, x->x_at2); + } + at = x->x_at2; + at += 2; + SETFLOAT(at, c6); + at++; + SETFLOAT(at, -s6); + at++; + SETFLOAT(at, s6); + at++; + SETFLOAT(at, c6); + outlet_anything(x->x_out13, x->x_s_matrix, x->x_size2, x->x_at2); + } + at = x->x_at2; + at += 2; + SETFLOAT(at, c5); + at++; + SETFLOAT(at, -s5); + at++; + SETFLOAT(at, s5); + at++; + SETFLOAT(at, c5); + outlet_anything(x->x_out11, x->x_s_matrix, x->x_size2, x->x_at2); + } + at = x->x_at2; + at += 2; + SETFLOAT(at, c4); + at++; + SETFLOAT(at, -s4); + at++; + SETFLOAT(at, s4); + at++; + SETFLOAT(at, c4); + outlet_anything(x->x_out9, x->x_s_matrix, x->x_size2, x->x_at2); + } + at = x->x_at2; + at += 2; + SETFLOAT(at, c3); + at++; + SETFLOAT(at, -s3); + at++; + SETFLOAT(at, s3); + at++; + SETFLOAT(at, c3); + outlet_anything(x->x_out7, x->x_s_matrix, x->x_size2, x->x_at2); + } + at = x->x_at2; + at += 2; + SETFLOAT(at, c2); + at++; + SETFLOAT(at, -s2); + at++; + SETFLOAT(at, s2); + at++; + SETFLOAT(at, c2); + outlet_anything(x->x_out5, x->x_s_matrix, x->x_size2, x->x_at2); + } + at = x->x_at2; + at += 2; + SETFLOAT(at, c); + at++; + SETFLOAT(at, -s); + at++; + SETFLOAT(at, s); + at++; + SETFLOAT(at, c); + outlet_anything(x->x_out3, x->x_s_matrix, x->x_size2, x->x_at2); +} + +static void ambi_rot_zy(t_ambi_rot *x, float rho_z, float rho_y) +{ + float cy, sy, ccy, ssy, c2y, s2y, c3y, s3y, c4y, s4y; + float cz, sz, ccz, ssz, c2z, s2z, c3z, s3z, c4z, s4z; + float r9_y[9][9]; + int i; + t_atom *at; + + rho_z *= x->x_pi_over_180; + rho_y *= x->x_pi_over_180; + + cz = cos(rho_z); + sz = sin(rho_z); + ccz = cz*cz; + ssz = sz*sz; + + cy = cos(rho_y); + sy = sin(rho_y); + ccy = cy*cy; + ssy = sy*sy; + + if(x->x_order >= 2) + { + c2z = ccz - ssz; + s2z = 2.0f*sz*cz; + c2y = ccy - ssy; + s2y = 2.0f*sy*cy; + if(x->x_order >= 3) + { + c3z = cz*(4.0f*ccz - 3.0f); + s3z = sz*(3.0f - 4.0f*ssz); + c3y = cy*(4.0f*ccy - 3.0f); + s3y = sy*(3.0f - 4.0f*ssy); + if(x->x_order >= 4) + { + if(x->x_order >= 5) + post("ambi_rot-ERROR: do not support Ambisonic-Order greater than 5 in zy-Rotation !!!"); + + /*y + r9_11=(35 + 28*c2 + c4)/64; + r9_22=(7c + c3)/8; + r9_31 = x->x_sqrt2*(14*s2 + s4)/32; + r9_33=(7*c2 + c4)/8; + r9_42 = x->x_sqrt2*(7*s + 3*s3)/16; + r9_44=(7*c + 9*c3)/16; + r9_51 = x->x_sqrt7*(5 - 4*c2 - c4)/32; + r9_53 = x->x_sqrt14*(2*s2 + s4)/16; + r9_55=(5 + 4*c2 + 7*c4)/16; + r9_62 = x->x_sqrt7*(c - c3)/8; + r9_64 = x->x_sqrt14*(-s + 3*s3)/16; + r9_66=(c + 7*c3)/8; + r9_71 = x->x_sqrt14*(2*s2 - s4)/32; + r9_73 = x->x_sqrt7*(c2 - c4)/8; + r9_75 = x->x_sqrt2*(-2*s2 + 7*s4)/16; + r9_77=(c2 + 7*c4)/8; + r9_82 = x->x_sqrt14*(3*s - s3)/16; + r9_84 = x->x_sqrt7*(3*c - 3*c3)/16; + r9_86 = x->x_sqrt2*(3*s + 7*s3)/16; + r9_88=(9*c + 7*c3)/16; + r9_91 = x->x_sqrt35*(3 - 4*c2 + c4)/64; + r9_93 = x->x_sqrt70*(2*s2 - s4)/32; + r9_95 = x->x_sqrt5*(3 + 4*c2 - 7*c4)/32; + r9_97 = x->x_sqrt10*(2*s2 + 7*s4)/32; + r9_99=(9 + 20*c2 + 35*c4)/64; + */ + + c4y = 1.0f + 8.0f*ccy*(ccy - 1.0f); + s4y = 2.0f*s2y*c2y; + + c4z = 1.0f + 8.0f*ccz*(ccz - 1.0f); + s4z = 2.0f*s2z*c2z; + + r9_y[0][0] = (35.0f + 28.0f*c2y + c4y)*0.015625f;/* -r9_31y, r9_51y, -r9_71y, r9_91y; */ + r9_y[1][1] = (7.0f*cy + c3y)*0.125f;/* -r9_42y, r9_62y, -r9_82y;*/ + r9_y[2][0] = x->x_sqrt2_16*(14.0f*s2y + s4y)*0.5f; + r9_y[2][2] = (7.0f*c2y + c4y)*0.125f;/* -r9_53y, r9_73y, -r9_93y;*/ + r9_y[3][1] = x->x_sqrt2_16*(7.0f*sy + 3.0f*s3y); + r9_y[3][3] = (7.0f*cy + 9.0f*c3y)*0.0625f;/* -r9_64y, r9_84y;*/ + r9_y[4][0] = x->x_sqrt7_8*(5.0f - 4.0f*c2y - c4y)*0.25f; + r9_y[4][2] = x->x_sqrt14_16*(2.0f*s2y + s4y); + r9_y[4][4] = (5.0f + 4.0f*c2y + 7.0f*c4y)*0.0625f;/* -r9_75y, r9_95y;*/ + r9_y[5][1] = x->x_sqrt7_8*(cy - c3y); + r9_y[5][3] = x->x_sqrt14_16*(3.0f*s3y - sy); + r9_y[5][5] = (cy + 7.0f*c3y)*0.125f;/* -r9_86y;*/ + r9_y[6][0] = x->x_sqrt14_16*(2.0f*s2y - s4y)*0.5f; + r9_y[6][2] = x->x_sqrt7_8*(c2y - c4y); + r9_y[6][4] = x->x_sqrt2_16*(7.0f*s4y - 2.0f*s2y); + r9_y[6][6] = (c2y + 7.0f*c4y)*0.125f;/* -r9_97y;*/ + r9_y[7][1] = x->x_sqrt14_16*(3.0f*sy - s3y); + r9_y[7][3] = x->x_sqrt7_8*(cy - c3y)*1.5f; + r9_y[7][5] = x->x_sqrt2_16*(3.0f*sy + 7.0f*s3y); + r9_y[7][7] = (9.0f*cy + 7.0f*c3y)*0.0625f; + r9_y[8][0] = x->x_sqrt35_64*(3.0f - 4.0f*c2y + c4y); + r9_y[8][2] = x->x_sqrt70_32*(2.0f*s2y - s4y); + r9_y[8][4] = x->x_sqrt5_32*(3.0f + 4.0f*c2y - 7.0f*c4y); + r9_y[8][6] = x->x_sqrt10_4*(2.0f*s2y + 7.0f*s4y)*0.125f; + r9_y[8][8] = (9.0f + 20.0f*c2y + 35.0f*c4y)*0.015625f; + + r9_y[0][2] = -r9_y[2][0]; + r9_y[0][4] = r9_y[4][0]; + r9_y[0][6] = -r9_y[6][0]; + r9_y[0][8] = r9_y[8][0]; + r9_y[1][3] = -r9_y[3][1]; + r9_y[1][5] = r9_y[5][1]; + r9_y[1][7] = -r9_y[7][1]; + r9_y[2][4] = -r9_y[4][2]; + r9_y[2][6] = r9_y[6][2]; + r9_y[2][8] = -r9_y[8][2]; + r9_y[3][5] = -r9_y[5][3]; + r9_y[3][7] = r9_y[7][3]; + r9_y[4][6] = -r9_y[6][4]; + r9_y[4][8] = r9_y[8][4]; + r9_y[5][7] = -r9_y[7][5]; + r9_y[6][8] = -r9_y[8][6]; + + at = x->x_at9; + at += 2; + + for(i=0; i<8; i+=2) + { + SETFLOAT(at, c4z*r9_y[0][i]); + at++; + SETFLOAT(at, -s4z*r9_y[1][i+1]); + at++; + } + SETFLOAT(at, c4z*r9_y[0][8]); + at++; + + for(i=0; i<8; i+=2) + { + SETFLOAT(at, c4z*r9_y[0][i]); + at++; + SETFLOAT(at, s4z*r9_y[1][i+1]); + at++; + } + SETFLOAT(at, s4z*r9_y[0][8]); + at++; + + for(i=0; i<8; i+=2) + { + SETFLOAT(at, c3z*r9_y[2][i]); + at++; + SETFLOAT(at, -s3z*r9_y[3][i+1]); + at++; + } + SETFLOAT(at, c3z*r9_y[2][8]); + at++; + + for(i=0; i<8; i+=2) + { + SETFLOAT(at, c3z*r9_y[2][i]); + at++; + SETFLOAT(at, s3z*r9_y[3][i+1]); + at++; + } + SETFLOAT(at, s3z*r9_y[2][8]); + at++; + + for(i=0; i<8; i+=2) + { + SETFLOAT(at, c2z*r9_y[4][i]); + at++; + SETFLOAT(at, -s2z*r9_y[5][i+1]); + at++; + } + SETFLOAT(at, c2z*r9_y[4][8]); + at++; + + for(i=0; i<8; i+=2) + { + SETFLOAT(at, c2z*r9_y[4][i]); + at++; + SETFLOAT(at, s2z*r9_y[5][i+1]); + at++; + } + SETFLOAT(at, s2z*r9_y[4][8]); + at++; + + for(i=0; i<8; i+=2) + { + SETFLOAT(at, cz*r9_y[6][i]); + at++; + SETFLOAT(at, -sz*r9_y[7][i+1]); + at++; + } + SETFLOAT(at, cz*r9_y[6][8]); + at++; + + for(i=0; i<8; i+=2) + { + SETFLOAT(at, cz*r9_y[6][i]); + at++; + SETFLOAT(at, sz*r9_y[7][i+1]); + at++; + } + SETFLOAT(at, sz*r9_y[6][8]); + at++; + + for(i=0; i<8; i+=2) + { + SETFLOAT(at, r9_y[8][i]); + at++; + SETFLOAT(at, 0.0f); + at++; + } + SETFLOAT(at, r9_y[8][8]); + + outlet_anything(x->x_out9, x->x_s_matrix, x->x_size9, x->x_at9); + } + + /*y + r7_11=(15*c + c3)/16; + r7_22=(5 + 3*c2)/8; + r7_31 = x->x_sqrt6*(5*s + s3)/16; + r7_33=(5*c + 3*c3)/8; + r7_42 = x->x_sqrt6*(s2)/4; + r7_44=(c2); + r7_51 = x->x_sqrt15*(c - c3)/16; + r7_53 = x->x_sqrt10*(-s + 3*s3)/16; + r7_55=(c + 15*c3)/16; + r7_62 = x->x_sqrt15*(1 - c2)/8; + r7_64 = x->x_sqrt10*(s2)/4; + r7_66=(3 + 5*c2)/8; + r7_71 = x->x_sqrt10*(3*s - s3)/16; + r7_73 = x->x_sqrt15*(c - c3)/8 = 2*r7_51; + r7_75 = x->x_sqrt6*(s + 5*s3)/16; + r7_77=(3*c + 5*c3)/8; + + */ + r9_y[0][0] = (15.0f*cy + c3y)*0.0625f;/* -r7_31y, r7_51y, -r7_71y;*/ + r9_y[1][1] = (5.0f + 3.0f*c2y)*0.125f;/* -r7_42y, r7_62y;*/ + r9_y[2][0] = x->x_sqrt6_4*(5.0f*sy + s3y)*0.25f; + r9_y[2][2] = (5.0f*cy + 3.0f*c3y)*0.125f;/* -r7_53y, r7_73y;*/ + r9_y[3][1] = x->x_sqrt6_4*s2y; + r9_y[3][3] = c2y;/* -r7_64y;*/ + r9_y[6][2] = x->x_sqrt15_8*(cy - c3y); + r9_y[4][0] = r9_y[6][2]*0.5f; + r9_y[4][2] = x->x_sqrt10_4*(3.0f*s3y - sy)*0.25f; + r9_y[4][4] = (cy + 15.0f*c3y)*0.0625f;/* -r7_75y;*/ + r9_y[5][1] = x->x_sqrt15_8*(1.0f - c2y); + r9_y[5][3] = x->x_sqrt10_4*s2y; + r9_y[5][5] = (3.0f + 5.0f*c2y)*0.125f; + r9_y[6][0] = x->x_sqrt10_4*(3.0f*sy - s3y)*0.25f; + + r9_y[6][4] = x->x_sqrt6_4*(sy + 5.0f*s3y)*0.25f; + r9_y[6][6] = (3.0f*cy + 5.0f*c3y)*0.125f; + + r9_y[0][2] = -r9_y[2][0]; + r9_y[0][4] = r9_y[4][0]; + r9_y[0][6] = -r9_y[6][0]; + r9_y[1][3] = -r9_y[3][1]; + r9_y[1][5] = r9_y[5][1]; + r9_y[2][4] = -r9_y[4][2]; + r9_y[2][6] = r9_y[6][2]; + r9_y[3][5] = -r9_y[5][3]; + r9_y[4][6] = -r9_y[6][4]; + + at = x->x_at7; + at += 2; + + for(i=0; i<6; i+=2) + { + SETFLOAT(at, c3z*r9_y[0][i]); + at++; + SETFLOAT(at, -s3z*r9_y[1][i+1]); + at++; + } + SETFLOAT(at, c3z*r9_y[0][6]); + at++; + + for(i=0; i<6; i+=2) + { + SETFLOAT(at, c3z*r9_y[0][i]); + at++; + SETFLOAT(at, s3z*r9_y[1][i+1]); + at++; + } + SETFLOAT(at, s3z*r9_y[0][6]); + at++; + + for(i=0; i<6; i+=2) + { + SETFLOAT(at, c2z*r9_y[2][i]); + at++; + SETFLOAT(at, -s2z*r9_y[3][i+1]); + at++; + } + SETFLOAT(at, c2z*r9_y[2][6]); + at++; + + for(i=0; i<6; i+=2) + { + SETFLOAT(at, c2z*r9_y[2][i]); + at++; + SETFLOAT(at, s2z*r9_y[3][i+1]); + at++; + } + SETFLOAT(at, s2z*r9_y[2][6]); + at++; + + for(i=0; i<6; i+=2) + { + SETFLOAT(at, cz*r9_y[4][i]); + at++; + SETFLOAT(at, -sz*r9_y[5][i+1]); + at++; + } + SETFLOAT(at, cz*r9_y[4][6]); + at++; + + for(i=0; i<6; i+=2) + { + SETFLOAT(at, cz*r9_y[4][i]); + at++; + SETFLOAT(at, sz*r9_y[5][i+1]); + at++; + } + SETFLOAT(at, sz*r9_y[4][6]); + at++; + + for(i=0; i<6; i+=2) + { + SETFLOAT(at, r9_y[6][i]); + at++; + SETFLOAT(at, 0.0f); + at++; + } + SETFLOAT(at, r9_y[6][6]); + + outlet_anything(x->x_out7, x->x_s_matrix, x->x_size7, x->x_at7); + } + + /*y + r5_11=(3 + c2)/4; + r5_22=(c); + r5_31 = (s2)/2; + r5_33=(c2); + r5_42 = (s); + r5_44=(c); + r5_51 = x->x_sqrt3*(1 - c2)/4; + r5_53 = x->x_sqrt3*(s2)/2; + r5_55=(1 + 3*c2)/4; + */ + r9_y[0][0] = (3.0f + c2y)*0.25f;/* -r5_31y, r5_51y;*/ + r9_y[1][1] = cy;/* -r5_42y;*/ + r9_y[2][0] = s2y*0.5f; + r9_y[2][2] = c2y;/* -r5_53y;*/ + r9_y[3][1] = sy; + r9_y[3][3] = cy; + r9_y[4][0] = x->x_sqrt3_2*(1.0f - c2y)*0.5f; + r9_y[4][2] = x->x_sqrt3_2*s2y; + r9_y[4][4] = (1.0f + 3.0f*c2y)*0.25f; + + r9_y[0][2] = -r9_y[2][0]; + r9_y[0][4] = r9_y[4][0]; + r9_y[1][3] = -r9_y[3][1]; + r9_y[2][4] = -r9_y[4][2]; + + at = x->x_at5; + at += 2; + + for(i=0; i<4; i+=2) + { + SETFLOAT(at, c2z*r9_y[0][i]); + at++; + SETFLOAT(at, -s2z*r9_y[1][i+1]); + at++; + } + SETFLOAT(at, c2z*r9_y[0][4]); + at++; + + for(i=0; i<4; i+=2) + { + SETFLOAT(at, c2z*r9_y[0][i]); + at++; + SETFLOAT(at, s2z*r9_y[1][i+1]); + at++; + } + SETFLOAT(at, s2z*r9_y[0][4]); + at++; + + for(i=0; i<4; i+=2) + { + SETFLOAT(at, cz*r9_y[2][i]); + at++; + SETFLOAT(at, -sz*r9_y[3][i+1]); + at++; + } + SETFLOAT(at, cz*r9_y[2][4]); + at++; + + for(i=0; i<4; i+=2) + { + SETFLOAT(at, cz*r9_y[2][i]); + at++; + SETFLOAT(at, sz*r9_y[3][i+1]); + at++; + } + SETFLOAT(at, sz*r9_y[2][4]); + at++; + + for(i=0; i<4; i+=2) + { + SETFLOAT(at, r9_y[4][i]); + at++; + SETFLOAT(at, 0.0f); + at++; + } + SETFLOAT(at, r9_y[4][4]); + + outlet_anything(x->x_out5, x->x_s_matrix, x->x_size5, x->x_at5); + } + + /*y + r3_11=(c); + r3_22=(1); + r3_31 = (s); + r3_33=(c); + */ + r9_y[0][0] = cy;/* -r3_31y;*/ + r9_y[1][1] = 1.0f; + r9_y[2][0] = sy; + r9_y[2][2] = cy; + r9_y[0][2] = -r9_y[2][0]; + + at = x->x_at3; + at += 2; + + SETFLOAT(at, cz*r9_y[0][0]); + at++; + SETFLOAT(at, -sz*r9_y[1][1]); + at++; + SETFLOAT(at, cz*r9_y[0][2]); + at++; + + SETFLOAT(at, sz*r9_y[0][0]); + at++; + SETFLOAT(at, cz*r9_y[1][1]); + at++; + SETFLOAT(at, sz*r9_y[0][2]); + at++; + + SETFLOAT(at, r9_y[2][0]); + at++; + SETFLOAT(at, 0.0f); + at++; + SETFLOAT(at, r9_y[2][2]); + + outlet_anything(x->x_out3, x->x_s_matrix, x->x_size3, x->x_at3); +} + +static void ambi_rot_zyx(t_ambi_rot *x, float rho_z, float rho_y, float rho_x) +{ + float cx, sx, ccx, ssx, c2x, s2x, c3x, s3x, c4x, s4x; + float cy, sy, ccy, ssy, c2y, s2y, c3y, s3y, c4y, s4y; + float cz, sz, ccz, ssz, c2z, s2z, c3z, s3z, c4z, s4z; + float r9_zy[9][9]; + float r9_z[9][9]; + float r9_y[9][9]; + float r9_x[9][9]; + int i, j; + t_atom *at; + + rho_z *= x->x_pi_over_180; + rho_y *= x->x_pi_over_180; + rho_x *= x->x_pi_over_180; + + cz = cos(rho_z); + sz = sin(rho_z); + ccz = cz*cz; + ssz = sz*sz; + + cy = cos(rho_y); + sy = sin(rho_y); + ccy = cy*cy; + ssy = sy*sy; + + cx = cos(rho_x); + sx = sin(rho_x); + ccx = cx*cx; + ssx = sx*sx; + + if(x->x_order >= 2) + { + c2z = ccz - ssz; + s2z = 2.0f*sz*cz; + c2y = ccy - ssy; + s2y = 2.0f*sy*cy; + c2x = ccx - ssx; + s2x = 2.0f*sx*cx; + + if(x->x_order >= 3) + { + c3z = cz*(4.0f*ccz - 3.0f); + s3z = sz*(3.0f - 4.0f*ssz); + c3y = cy*(4.0f*ccy - 3.0f); + s3y = sy*(3.0f - 4.0f*ssy); + c3x = cx*(4.0f*ccx - 3.0f); + s3x = sx*(3.0f - 4.0f*ssx); + + if(x->x_order >= 4) + { + if(x->x_order >= 5) + post("ambi_rot-ERROR: do not support Ambisonic-Order greater than 5 in zyx-Rotation !!!"); + + c4z = 1.0f + 8.0f*ccz*(ccz - 1.0f); + s4z = 2.0f*s2z*c2z; + + c4y = 1.0f + 8.0f*ccy*(ccy - 1.0f); + s4y = 2.0f*s2y*c2y; + + c4x = 1.0f + 8.0f*ccx*(ccx - 1.0f); + s4x = 2.0f*s2x*c2x; + + r9_z[0][0] = c4z; + r9_z[0][1] = -s4z; + r9_z[1][0] = s4z; + r9_z[1][1] = c4z; + r9_z[2][2] = c3z; + r9_z[2][3] = -s3z; + r9_z[3][2] = s3z; + r9_z[3][3] = c3z; + r9_z[4][4] = c2z; + r9_z[4][5] = -s2z; + r9_z[5][4] = s2z; + r9_z[5][5] = c2z; + r9_z[6][6] = cz; + r9_z[6][7] = -sz; + r9_z[7][6] = sz; + r9_z[7][7] = cz; + r9_z[8][8] = 1.0f; + /*y + r9_11=(35 + 28*c2 + c4)/64; + r9_22=(7c + c3)/8; + r9_31 = x->x_sqrt2*(14*s2 + s4)/32; + r9_33=(7*c2 + c4)/8; + r9_42 = x->x_sqrt2*(7*s + 3*s3)/16; + r9_44=(7*c + 9*c3)/16; + r9_51 = x->x_sqrt7*(5 - 4*c2 - c4)/32; + r9_53 = x->x_sqrt14*(2*s2 + s4)/16; + r9_55=(5 + 4*c2 + 7*c4)/16; + r9_62 = x->x_sqrt7*(c - c3)/8; + r9_64 = x->x_sqrt14*(-s + 3*s3)/16; + r9_66=(c + 7*c3)/8; + r9_71 = x->x_sqrt14*(2*s2 - s4)/32; + r9_73 = x->x_sqrt7*(c2 - c4)/8; + r9_75 = x->x_sqrt2*(-2*s2 + 7*s4)/16; + r9_77=(c2 + 7*c4)/8; + r9_82 = x->x_sqrt14*(3*s - s3)/16; + r9_84 = x->x_sqrt7*(3*c - 3*c3)/16; + r9_86 = x->x_sqrt2*(3*s + 7*s3)/16; + r9_88=(9*c + 7*c3)/16; + r9_91 = x->x_sqrt35*(3 - 4*c2 + c4)/64; + r9_93 = x->x_sqrt70*(2*s2 - s4)/32; + r9_95 = x->x_sqrt5*(3 + 4*c2 - 7*c4)/32; + r9_97 = x->x_sqrt10*(2*s2 + 7*s4)/32; + r9_99=(9 + 20*c2 + 35*c4)/64; + */ + r9_y[0][0] = (35.0f + 28.0f*c2y + c4y)*0.015625f;/* -r9_31y, r9_51y, -r9_71y, r9_91y; */ + r9_y[1][1] = (7.0f*cy + c3y)*0.125f;/* -r9_42y, r9_62y, -r9_82y;*/ + r9_y[2][0] = x->x_sqrt2_16*(14.0f*s2y + s4y)*0.5f; + r9_y[2][2] = (7.0f*c2y + c4y)*0.125f;/* -r9_53y, r9_73y, -r9_93y;*/ + r9_y[3][1] = x->x_sqrt2_16*(7.0f*sy + 3.0f*s3y); + r9_y[3][3] = (7.0f*cy + 9.0f*c3y)*0.0625f;/* -r9_64y, r9_84y;*/ + r9_y[4][0] = x->x_sqrt7_8*(5.0f - 4.0f*c2y - c4y)*0.25f; + r9_y[4][2] = x->x_sqrt14_16*(2.0f*s2y + s4y); + r9_y[4][4] = (5.0f + 4.0f*c2y + 7.0f*c4y)*0.0625f;/* -r9_75y, r9_95y;*/ + r9_y[5][1] = x->x_sqrt7_8*(cy - c3y); + r9_y[5][3] = x->x_sqrt14_16*(3.0f*s3y - sy); + r9_y[5][5] = (cy + 7.0f*c3y)*0.125f;/* -r9_86y;*/ + r9_y[6][0] = x->x_sqrt14_16*(2.0f*s2y - s4y)*0.5f; + r9_y[6][2] = x->x_sqrt7_8*(c2y - c4y); + r9_y[6][4] = x->x_sqrt2_16*(7.0f*s4y - 2.0f*s2y); + r9_y[6][6] = (c2y + 7.0f*c4y)*0.125f;/* -r9_97y;*/ + r9_y[7][1] = x->x_sqrt14_16*(3.0f*sy - s3y); + r9_y[7][3] = x->x_sqrt7_8*(cy - c3y)*1.5f; + r9_y[7][5] = x->x_sqrt2_16*(3.0f*sy + 7.0f*s3y); + r9_y[7][7] = (9.0f*cy + 7.0f*c3y)*0.0625f; + r9_y[8][0] = x->x_sqrt35_64*(3.0f - 4.0f*c2y + c4y); + r9_y[8][2] = x->x_sqrt70_32*(2.0f*s2y - s4y); + r9_y[8][4] = x->x_sqrt5_32*(3.0f + 4.0f*c2y - 7.0f*c4y); + r9_y[8][6] = x->x_sqrt10_4*(2.0f*s2y + 7.0f*s4y)*0.125f; + r9_y[8][8] = (9.0f + 20.0f*c2y + 35.0f*c4y)*0.015625f; + + r9_y[0][2] = -r9_y[2][0]; + r9_y[0][4] = r9_y[4][0]; + r9_y[0][6] = -r9_y[6][0]; + r9_y[0][8] = r9_y[8][0]; + r9_y[1][3] = -r9_y[3][1]; + r9_y[1][5] = r9_y[5][1]; + r9_y[1][7] = -r9_y[7][1]; + r9_y[2][4] = -r9_y[4][2]; + r9_y[2][6] = r9_y[6][2]; + r9_y[2][8] = -r9_y[8][2]; + r9_y[3][5] = -r9_y[5][3]; + r9_y[3][7] = r9_y[7][3]; + r9_y[4][6] = -r9_y[6][4]; + r9_y[4][8] = r9_y[8][4]; + r9_y[5][7] = -r9_y[7][5]; + r9_y[6][8] = -r9_y[8][6]; + + /*x + r9_11=(35 + 28*c2 + c4)/64; + r9_22=(7c + c3)/8; + r9_32 = x->x_sqrt2*(7*s + 3*s3)/16; + r9_33=(7*c + 9*c3)/16; + r9_41 = x->x_sqrt2*(-14*s2 - s4)/32; + r9_44=(7*c2 + c4)/8; + r9_51 = x->x_sqrt7*(-5 + 4*c2 + c4)/32; + r9_54 = x->x_sqrt14*(2*s2 + s4)/16; + r9_55=(5 + 4*c2 + 7*c4)/16; + r9_62 = x->x_sqrt7*(-c + c3)/8; + r9_63 = x->x_sqrt14*(s - 3*s3)/16; + r9_66=(c + 7*c3)/8; + r9_72 = x->x_sqrt14*(-3s + s3)/16; + r9_73 = x->x_sqrt7*(-3*c + 3*c3)/16; + r9_76 = x->x_sqrt2*(3*s + 7*s3)/16; + r9_77=(9*c + 7*c3)/16; + r9_81 = x->x_sqrt14*(2*s2 - s4)/32; + r9_84 = x->x_sqrt7*(-c2 + c4)/8; + r9_85 = x->x_sqrt2*(2*s2 - 7*s4)/16; + r9_88=(c2 + 7*c4)/8; + r9_91 = x->x_sqrt35*(3 - 4*c2 + c4)/64; + r9_94 = x->x_sqrt70*(-2*s2 + s4)/32; + r9_95 = x->x_sqrt5*(-3 - 4*c2 + 7*c4)/32; + r9_98 = x->x_sqrt10*(2*s2 + 7*s4)/32; + r9_99=(9 + 20*c2 + 35*c4)/64; + */ + + r9_x[0][0] = (35.0f + 28.0f*c2x + c4x)*0.015625f;/* -r9_41x, r9_51x, -r9_81x, r9_91x;*/ + r9_x[1][1] = (7.0f*cx + c3x)*0.125f;/* -r9_32x, r9_62x, -r9_72x;*/ + r9_x[2][1] = x->x_sqrt2_16*(7.0f*sx + 3.0f*s3x); + r9_x[2][2] = (7.0f*cx + 9.0f*c3x)*0.0625f;/* -r9_63x, r9_73x;*/ + r9_x[3][0] = -x->x_sqrt2_16*(14.0f*s2x + s4x)*0.5f; + r9_x[3][3] = (7.0f*c2x + c4x)*0.125f;/* -r9_54x, r9_84x, -r9_94x;*/ + r9_x[4][0] = x->x_sqrt7_8*(4.0f*c2x + c4x - 5.0f)*0.25f; + r9_x[4][3] = x->x_sqrt14_16*(2.0f*s2x + s4x); + r9_x[4][4] = (5.0f + 4.0f*c2x + 7.0f*c4x)*0.0625f;/* -r9_85x, r9_95x;*/ + r9_x[5][1] = x->x_sqrt7_8*(c3x - cx); + r9_x[5][2] = x->x_sqrt14_16*(sx - 3.0f*s3x); + r9_x[5][5] = (cx + 7.0f*c3x)*0.125f;/* -r9_76x;*/ + r9_x[6][1] = x->x_sqrt14_16*(s3x - 3.0f*sx); + r9_x[6][2] = x->x_sqrt7_8*(c3x - cx)*1.5f; + r9_x[6][5] = x->x_sqrt2_16*(3.0f*sx + 7.0f*s3x); + r9_x[6][6] = (9.0f*cx + 7.0f*c3x)*0.0625f; + r9_x[7][0] = x->x_sqrt14_16*(2.0f*s2x - s4x)*0.5f; + r9_x[7][3] = x->x_sqrt7_8*(c4x - c2x); + r9_x[7][4] = x->x_sqrt2_16*(2.0f*s2x - 7.0f*s4x); + r9_x[7][7] = (c2x + 7.0f*c4x)*0.125f;/* -r9_98x*/ + r9_x[8][0] = x->x_sqrt35_64*(3.0f - 4.0f*c2x + c4x); + r9_x[8][3] = x->x_sqrt70_32*(s4x - 2.0f*s2x); + r9_x[8][4] = x->x_sqrt5_32*(7.0f*c4x - 3.0f - 4.0f*c2x); + r9_x[8][7] = x->x_sqrt10_4*(2.0f*s2x + 7.0f*s4x)*0.125f; + r9_x[8][8] = (9.0f + 20.0f*c2x + 35.0f*c4x)*0.015625f; + + r9_x[0][3] = -r9_x[3][0]; + r9_x[0][4] = r9_x[4][0]; + r9_x[0][7] = -r9_x[7][0]; + r9_x[0][8] = r9_x[8][0]; + r9_x[1][2] = -r9_x[2][1]; + r9_x[1][5] = r9_x[5][1]; + r9_x[1][6] = -r9_x[6][1]; + r9_x[2][5] = -r9_x[5][2]; + r9_x[2][6] = r9_x[6][2]; + r9_x[3][4] = -r9_x[4][3]; + r9_x[3][7] = r9_x[7][3]; + r9_x[3][8] = -r9_x[8][3]; + r9_x[4][7] = -r9_x[7][4]; + r9_x[4][8] = r9_x[8][4]; + r9_x[5][6] = -r9_x[6][5]; + r9_x[7][8] = -r9_x[8][7]; + + for(j=0; j<8; j+=2) + { + for(i=0; i<8; i+=2) + { + r9_zy[j][i] = r9_z[j][j]*r9_y[j][i]; + r9_zy[j][i+1] = r9_z[j][j+1]*r9_y[j+1][i+1]; + + r9_zy[j+1][i] = r9_z[j+1][j]*r9_y[j][i]; + r9_zy[j+1][i+1] = r9_z[j+1][j+1]*r9_y[j+1][i+1]; + } + r9_zy[j][8] = r9_z[j][j]*r9_y[j][8]; + r9_zy[j+1][8] = r9_z[j+1][j]*r9_y[j][8]; + } + for(i=0; i<=8; i+=2) + { + r9_zy[8][i] = r9_y[8][i]; + } + + at = x->x_at9; + at += 2; + + for(i=0; i<8; i++) + { + SETFLOAT(at, (r9_zy[i][0]*r9_x[0][0] + r9_zy[i][3]*r9_x[3][0] + r9_zy[i][4]*r9_x[4][0] + r9_zy[i][7]*r9_x[7][0] + r9_zy[i][8]*r9_x[8][0])); + at++; + SETFLOAT(at, (r9_zy[i][1]*r9_x[1][1] + r9_zy[i][2]*r9_x[2][1] + r9_zy[i][5]*r9_x[5][1] + r9_zy[i][6]*r9_x[6][1])); + at++; + SETFLOAT(at, (r9_zy[i][1]*r9_x[1][2] + r9_zy[i][2]*r9_x[2][2] + r9_zy[i][5]*r9_x[5][2] + r9_zy[i][6]*r9_x[6][2])); + at++; + SETFLOAT(at, (r9_zy[i][0]*r9_x[0][3] + r9_zy[i][3]*r9_x[3][3] + r9_zy[i][4]*r9_x[4][3] + r9_zy[i][7]*r9_x[7][3] + r9_zy[i][8]*r9_x[8][3])); + at++; + SETFLOAT(at, (r9_zy[i][0]*r9_x[0][4] + r9_zy[i][3]*r9_x[3][4] + r9_zy[i][4]*r9_x[4][4] + r9_zy[i][7]*r9_x[7][4] + r9_zy[i][8]*r9_x[8][4])); + at++; + SETFLOAT(at, (r9_zy[i][1]*r9_x[1][5] + r9_zy[i][2]*r9_x[2][5] + r9_zy[i][5]*r9_x[5][5] + r9_zy[i][6]*r9_x[6][5])); + at++; + SETFLOAT(at, (r9_zy[i][1]*r9_x[1][6] + r9_zy[i][2]*r9_x[2][6] + r9_zy[i][5]*r9_x[5][6] + r9_zy[i][6]*r9_x[6][6])); + at++; + SETFLOAT(at, (r9_zy[i][0]*r9_x[0][7] + r9_zy[i][3]*r9_x[3][7] + r9_zy[i][4]*r9_x[4][7] + r9_zy[i][7]*r9_x[7][7] + r9_zy[i][8]*r9_x[8][7])); + at++; + SETFLOAT(at, (r9_zy[i][0]*r9_x[0][8] + r9_zy[i][3]*r9_x[3][8] + r9_zy[i][4]*r9_x[4][8] + r9_zy[i][7]*r9_x[7][8] + r9_zy[i][8]*r9_x[8][8])); + at++; + } + + SETFLOAT(at, (r9_zy[8][0]*r9_x[0][0] + r9_zy[8][4]*r9_x[4][0] + r9_zy[8][8]*r9_x[8][0])); + at++; + SETFLOAT(at, (r9_zy[8][2]*r9_x[2][1] + r9_zy[8][6]*r9_x[6][1])); + at++; + SETFLOAT(at, (r9_zy[8][2]*r9_x[2][2] + r9_zy[8][6]*r9_x[6][2])); + at++; + SETFLOAT(at, (r9_zy[8][0]*r9_x[0][3] + r9_zy[8][4]*r9_x[4][3] + r9_zy[8][8]*r9_x[8][3])); + at++; + SETFLOAT(at, (r9_zy[8][0]*r9_x[0][4] + r9_zy[8][4]*r9_x[4][4] + r9_zy[8][8]*r9_x[8][4])); + at++; + SETFLOAT(at, (r9_zy[8][2]*r9_x[2][5] + r9_zy[8][6]*r9_x[6][5])); + at++; + SETFLOAT(at, (r9_zy[8][2]*r9_x[2][6] + r9_zy[8][6]*r9_x[6][6])); + at++; + SETFLOAT(at, (r9_zy[8][0]*r9_x[0][7] + r9_zy[8][4]*r9_x[4][7] + r9_zy[8][8]*r9_x[8][7])); + at++; + SETFLOAT(at, (r9_zy[8][0]*r9_x[0][8] + r9_zy[8][4]*r9_x[4][8] + r9_zy[8][8]*r9_x[8][8])); + + outlet_anything(x->x_out9, x->x_s_matrix, x->x_size9, x->x_at9); + } + + r9_z[0][0] = c3z; + r9_z[0][1] = -s3z; + r9_z[1][0] = s3z; + r9_z[1][1] = c3z; + r9_z[2][2] = c2z; + r9_z[2][3] = -s2z; + r9_z[3][2] = s2z; + r9_z[3][3] = c2z; + r9_z[4][4] = cz; + r9_z[4][5] = -sz; + r9_z[5][4] = sz; + r9_z[5][5] = cz; + r9_z[6][6] = 1.0f; + /*y + r7_11=(15*c + c3)/16; + r7_22=(5 + 3*c2)/8; + r7_31 = x->x_sqrt6*(5*s + s3)/16; + r7_33=(5*c + 3*c3)/8; + r7_42 = x->x_sqrt6*(s2)/4; + r7_44=(c2); + r7_51 = x->x_sqrt15*(c - c3)/16; + r7_53 = x->x_sqrt10*(-s + 3*s3)/16; + r7_55=(c + 15*c3)/16; + r7_62 = x->x_sqrt15*(1 - c2)/8; + r7_64 = x->x_sqrt10*(s2)/4; + r7_66=(3 + 5*c2)/8; + r7_71 = x->x_sqrt10*(3*s - s3)/16; + r7_73 = x->x_sqrt15*(c - c3)/8 = 2*r7_51; + r7_75 = x->x_sqrt6*(s + 5*s3)/16; + r7_77=(3*c + 5*c3)/8; + + */ + r9_y[0][0] = (15.0f*cy + c3y)*0.0625f;/* -r7_31y, r7_51y, -r7_71y;*/ + r9_y[1][1] = (5.0f + 3.0f*c2y)*0.125f;/* -r7_42y, r7_62y;*/ + r9_y[2][0] = x->x_sqrt6_4*(5.0f*sy + s3y)*0.25f; + r9_y[2][2] = (5.0f*cy + 3.0f*c3y)*0.125f;/* -r7_53y, r7_73y;*/ + r9_y[3][1] = x->x_sqrt6_4*s2y; + r9_y[3][3] = c2y;/* -r7_64y;*/ + r9_y[6][2] = x->x_sqrt15_8*(cy - c3y); + r9_y[4][0] = r9_y[6][2]*0.5f; + r9_y[4][2] = x->x_sqrt10_4*(3.0f*s3y - sy)*0.25f; + r9_y[4][4] = (cy + 15.0f*c3y)*0.0625f;/* -r7_75y;*/ + r9_y[5][1] = x->x_sqrt15_8*(1.0f - c2y); + r9_y[5][3] = x->x_sqrt10_4*s2y; + r9_y[5][5] = (3.0f + 5.0f*c2y)*0.125f; + r9_y[6][0] = x->x_sqrt10_4*(3.0f*sy - s3y)*0.25f; + + r9_y[6][4] = x->x_sqrt6_4*(sy + 5.0f*s3y)*0.25f; + r9_y[6][6] = (3.0f*cy + 5.0f*c3y)*0.125f; + + r9_y[0][2] = -r9_y[2][0]; + r9_y[0][4] = r9_y[4][0]; + r9_y[0][6] = -r9_y[6][0]; + r9_y[1][3] = -r9_y[3][1]; + r9_y[1][5] = r9_y[5][1]; + r9_y[2][4] = -r9_y[4][2]; + r9_y[2][6] = r9_y[6][2]; + r9_y[3][5] = -r9_y[5][3]; + r9_y[4][6] = -r9_y[6][4]; + + /*x + r7_11=(5 + 3*c2)/8; + r7_22=(15*c + c3)/16; + r7_32 = x->x_sqrt6*(5*s + s3)/16; + r7_33=(5*c + 3*c3)/8; + r7_41 = x->x_sqrt6*(-s2)/4; + r7_44=(c2); + r7_51 = x->x_sqrt15*(-1 + c2)/8; + r7_54 = x->x_sqrt10*(s2)/4; + r7_55=(3 + 5*c2)/8; + r7_62 = x->x_sqrt15*(-c + c3)/16; + r7_63 = x->x_sqrt10*(s - 3*s3)/16; + r7_66=(c + 15*c3)/16; + r7_72 = x->x_sqrt10*(-3*s + s3)/16; + r7_73 = x->x_sqrt15*(-c + c3)/8 = 2*r7_62; + r7_76 = x->x_sqrt6*(s + 5*s3)/16; + r7_77=(3*c + 5*c3)/8; + */ + + r9_x[0][0] = (5.0f + 3.0f*c2x)*0.125f;/* -r7_41, r7_51;*/ + r9_x[1][1] = (15.0f*cx + c3x)*0.0625f;/* -r7_32, r7_62, -r7_72;*/ + r9_x[2][1] = x->x_sqrt6_4*(5.0f*sx + s3x)*0.25f; + r9_x[2][2] = (5.0f*cx + 3.0f*c3x)*0.125f;/* */ + r9_x[3][0] = -x->x_sqrt6_4*s2x; + r9_x[3][3] = c2x; + r9_x[4][0] = x->x_sqrt15_8*(c2x - 1.0f); + r9_x[4][3] = x->x_sqrt10_4*s2x; + r9_x[4][4] = (3.0f + 5.0f*c2x)*0.125f; + r9_x[6][2] = x->x_sqrt15_8*(c3x - cx); + r9_x[5][1] = r9_x[6][2]*0.5f; + r9_x[5][2] = x->x_sqrt10_4*(sx - 3.0f*s3x)*0.25f; + r9_x[5][5] = (cx + 15.0f*c3x)*0.0625f; + r9_x[6][1] = x->x_sqrt10_4*(s3x - 3.0f*sx)*0.25f; + + r9_x[6][5] = x->x_sqrt6_4*(sx + 5.0f*s3x)*0.25f; + r9_x[6][6] = (3.0f*cx + 5.0f*c3x)*0.125f; + + r9_x[0][3] = -r9_x[3][0]; + r9_x[0][4] = r9_x[4][0]; + r9_x[1][2] = -r9_x[2][1]; + r9_x[1][5] = r9_x[5][1]; + r9_x[1][6] = -r9_x[6][1]; + r9_x[2][5] = -r9_x[5][2]; + r9_x[2][6] = r9_x[6][2]; + r9_x[3][4] = -r9_x[4][3]; + r9_x[5][6] = -r9_x[6][5]; + + for(j=0; j<6; j+=2) + { + for(i=0; i<6; i+=2) + { + r9_zy[j][i] = r9_z[j][j]*r9_y[j][i]; + r9_zy[j][i+1] = r9_z[j][j+1]*r9_y[j+1][i+1]; + + r9_zy[j+1][i] = r9_z[j+1][j]*r9_y[j][i]; + r9_zy[j+1][i+1] = r9_z[j+1][j+1]*r9_y[j+1][i+1]; + } + r9_zy[j][6] = r9_z[j][j]*r9_y[j][6]; + r9_zy[j+1][6] = r9_z[j+1][j]*r9_y[j][6]; + } + for(i=0; i<=6; i+=2) + { + r9_zy[6][i] = r9_y[6][i]; + } + + at = x->x_at7; + at += 2; + + for(i=0; i<6; i++) + { + SETFLOAT(at, (r9_zy[i][0]*r9_x[0][0] + r9_zy[i][3]*r9_x[3][0] + r9_zy[i][4]*r9_x[4][0])); + at++; + SETFLOAT(at, (r9_zy[i][1]*r9_x[1][1] + r9_zy[i][2]*r9_x[2][1] + r9_zy[i][5]*r9_x[5][1] + r9_zy[i][6]*r9_x[6][1])); + at++; + SETFLOAT(at, (r9_zy[i][1]*r9_x[1][2] + r9_zy[i][2]*r9_x[2][2] + r9_zy[i][5]*r9_x[5][2] + r9_zy[i][6]*r9_x[6][2])); + at++; + SETFLOAT(at, (r9_zy[i][0]*r9_x[0][3] + r9_zy[i][3]*r9_x[3][3] + r9_zy[i][4]*r9_x[4][3])); + at++; + SETFLOAT(at, (r9_zy[i][0]*r9_x[0][4] + r9_zy[i][3]*r9_x[3][4] + r9_zy[i][4]*r9_x[4][4])); + at++; + SETFLOAT(at, (r9_zy[i][1]*r9_x[1][5] + r9_zy[i][2]*r9_x[2][5] + r9_zy[i][5]*r9_x[5][5] + r9_zy[i][6]*r9_x[6][5])); + at++; + SETFLOAT(at, (r9_zy[i][1]*r9_x[1][6] + r9_zy[i][2]*r9_x[2][6] + r9_zy[i][5]*r9_x[5][6] + r9_zy[i][6]*r9_x[6][6])); + at++; + } + + SETFLOAT(at, (r9_zy[6][0]*r9_x[0][0] + r9_zy[6][4]*r9_x[4][0])); + at++; + SETFLOAT(at, (r9_zy[6][2]*r9_x[2][1] + r9_zy[6][6]*r9_x[6][1])); + at++; + SETFLOAT(at, (r9_zy[6][2]*r9_x[2][2] + r9_zy[6][6]*r9_x[6][2])); + at++; + SETFLOAT(at, (r9_zy[6][0]*r9_x[0][3] + r9_zy[6][4]*r9_x[4][3])); + at++; + SETFLOAT(at, (r9_zy[6][0]*r9_x[0][4] + r9_zy[6][4]*r9_x[4][4])); + at++; + SETFLOAT(at, (r9_zy[6][2]*r9_x[2][5] + r9_zy[6][6]*r9_x[6][5])); + at++; + SETFLOAT(at, (r9_zy[6][2]*r9_x[2][6] + r9_zy[6][6]*r9_x[6][6])); + + outlet_anything(x->x_out7, x->x_s_matrix, x->x_size7, x->x_at7); + } + + r9_z[0][0] = c2z; + r9_z[0][1] = -s2z; + r9_z[1][0] = s2z; + r9_z[1][1] = c2z; + r9_z[2][2] = cz; + r9_z[2][3] = -sz; + r9_z[3][2] = sz; + r9_z[3][3] = cz; + r9_z[4][4] = 1.0f; + /*y + r5_11=(3 + c2)/4; + r5_22=(c); + r5_31 = (s2)/2; + r5_33=(c2); + r5_42 = (s); + r5_44=(c); + r5_51 = x->x_sqrt3*(1 - c2)/4; + r5_53 = x->x_sqrt3*(s2)/2; + r5_55=(1 + 3*c2)/4; + */ + r9_y[0][0] = (3.0f + c2y)*0.25f;/* -r5_31y, r5_51y;*/ + r9_y[1][1] = cy;/* -r5_42y;*/ + r9_y[2][0] = s2y*0.5f; + r9_y[2][2] = c2y;/* -r5_53y;*/ + r9_y[3][1] = sy; + r9_y[3][3] = cy; + r9_y[4][0] = x->x_sqrt3_2*(1.0f - c2y)*0.5f; + r9_y[4][2] = x->x_sqrt3_2*s2y; + r9_y[4][4] = (1.0f + 3.0f*c2y)*0.25f; + + r9_y[0][2] = -r9_y[2][0]; + r9_y[0][4] = r9_y[4][0]; + r9_y[1][3] = -r9_y[3][1]; + r9_y[2][4] = -r9_y[4][2]; + + /*x + r5_11=(3 + c2)/4; + r5_22=(c); + r5_32 = (s); + r5_33=(c); + r5_41 = (-s2)/2; + r5_44=(c2); + r5_51 = x->x_sqrt3*(-1 + c2)/4; + r5_54 = x->x_sqrt3*(s2)/2; + r5_55=(1 + 3*c2)/4; + */ + + r9_x[0][0] = (3.0f + c2x)*0.25f; + r9_x[1][1] = cx; + r9_x[2][1] = sx; + r9_x[2][2] = cx; + r9_x[3][0] = -0.5f*s2x; + r9_x[3][3] = c2x; + r9_x[4][0] = x->x_sqrt3_2*(c2x - 1.0f)*0.5f; + r9_x[4][3] = x->x_sqrt3_2*s2x; + r9_x[4][4] = (1.0f + 3.0f*c2x)*0.25f; + + r9_x[0][3] = -r9_x[3][0]; + r9_x[0][4] = r9_x[4][0]; + r9_x[1][2] = -r9_x[2][1]; + r9_x[3][4] = -r9_x[4][3]; + + for(j=0; j<4; j+=2) + { + for(i=0; i<4; i+=2) + { + r9_zy[j][i] = r9_z[j][j]*r9_y[j][i]; + r9_zy[j][i+1] = r9_z[j][j+1]*r9_y[j+1][i+1]; + + r9_zy[j+1][i] = r9_z[j+1][j]*r9_y[j][i]; + r9_zy[j+1][i+1] = r9_z[j+1][j+1]*r9_y[j+1][i+1]; + } + r9_zy[j][4] = r9_z[j][j]*r9_y[j][4]; + r9_zy[j+1][4] = r9_z[j+1][j]*r9_y[j][4]; + } + for(i=0; i<=4; i+=2) + { + r9_zy[4][i] = r9_y[4][i]; + } + + at = x->x_at5; + at += 2; + + for(i=0; i<4; i++) + { + SETFLOAT(at, (r9_zy[i][0]*r9_x[0][0] + r9_zy[i][3]*r9_x[3][0] + r9_zy[i][4]*r9_x[4][0])); + at++; + SETFLOAT(at, (r9_zy[i][1]*r9_x[1][1] + r9_zy[i][2]*r9_x[2][1])); + at++; + SETFLOAT(at, (r9_zy[i][1]*r9_x[1][2] + r9_zy[i][2]*r9_x[2][2])); + at++; + SETFLOAT(at, (r9_zy[i][0]*r9_x[0][3] + r9_zy[i][3]*r9_x[3][3] + r9_zy[i][4]*r9_x[4][3])); + at++; + SETFLOAT(at, (r9_zy[i][0]*r9_x[0][4] + r9_zy[i][3]*r9_x[3][4] + r9_zy[i][4]*r9_x[4][4])); + at++; + } + + SETFLOAT(at, (r9_zy[4][0]*r9_x[0][0] + r9_zy[4][4]*r9_x[4][0])); + at++; + SETFLOAT(at, (r9_zy[4][2]*r9_x[2][1])); + at++; + SETFLOAT(at, (r9_zy[4][2]*r9_x[2][2])); + at++; + SETFLOAT(at, (r9_zy[4][0]*r9_x[0][3] + r9_zy[4][4]*r9_x[4][3])); + at++; + SETFLOAT(at, (r9_zy[4][0]*r9_x[0][4] + r9_zy[4][4]*r9_x[4][4])); + + outlet_anything(x->x_out5, x->x_s_matrix, x->x_size5, x->x_at5); + } + + r9_z[0][0] = cz; + r9_z[0][1] = -sz; + r9_z[1][0] = sz; + r9_z[1][1] = cz; + r9_z[2][2] = 1.0f; + /*y + r3_11=(c); + r3_22=(1); + r3_31 = (s); + r3_33=(c); + */ + r9_y[0][0] = cy;/* -r3_31y;*/ + r9_y[1][1] = 1.0f; + r9_y[2][0] = sy; + r9_y[2][2] = cy; + + r9_y[0][2] = -r9_y[2][0]; + + /*x + r3_11=(1); + r3_22=(c); + r3_32 = (s); + r3_33=(c); + */ + r9_x[0][0] = 1.0f; + r9_x[1][1] = cx;/* -r3_32x;*/ + r9_x[2][1] = sx; + r9_x[2][2] = cx; + + r9_x[1][2] = -r9_x[2][1]; + + r9_zy[0][0] = cz*r9_y[0][0]; + r9_zy[0][1] = -sz*r9_y[1][1]; + r9_zy[0][2] = cz*r9_y[0][2]; + + r9_zy[1][0] = sz*r9_y[0][0]; + r9_zy[1][1] = cz*r9_y[1][1]; + r9_zy[1][2] = sz*r9_y[0][2]; + + r9_zy[2][0] = r9_y[2][0]; + r9_zy[2][1] = 0.0f; + r9_zy[2][2] = r9_y[2][2]; + + at = x->x_at3; + at += 2; + + for(i=0; i<2; i++) + { + SETFLOAT(at, (r9_zy[i][0]*r9_x[0][0])); + at++; + SETFLOAT(at, (r9_zy[i][1]*r9_x[1][1] + r9_zy[i][2]*r9_x[2][1])); + at++; + SETFLOAT(at, (r9_zy[i][1]*r9_x[1][2] + r9_zy[i][2]*r9_x[2][2])); + at++; + } + + SETFLOAT(at, (r9_zy[2][0]*r9_x[0][0])); + at++; + SETFLOAT(at, (r9_zy[2][2]*r9_x[2][1])); + at++; + SETFLOAT(at, (r9_zy[2][2]*r9_x[2][2])); + + outlet_anything(x->x_out3, x->x_s_matrix, x->x_size3, x->x_at3); +} + +static void ambi_rot_list(t_ambi_rot *x, t_symbol *s, int argc, t_atom *argv) +{ + if(argc == 1) + ambi_rot_float(x, atom_getfloatarg(0, argc, argv));/* = ambi_rot_z(); */ + else if(argc == 2) + ambi_rot_zy(x, atom_getfloatarg(0, argc, argv), atom_getfloatarg(1, argc, argv)); + else if(argc >= 3) + ambi_rot_zyx(x, atom_getfloatarg(0, argc, argv), atom_getfloatarg(1, argc, argv), atom_getfloatarg(2, argc, argv)); +} + +static void ambi_rot_free(t_ambi_rot *x) +{ + if(x->x_size11) + freebytes(x->x_at11, x->x_size11 * sizeof(t_atom)); + if(x->x_size9) + freebytes(x->x_at9, x->x_size9 * sizeof(t_atom)); + if(x->x_size7) + freebytes(x->x_at7, x->x_size7 * sizeof(t_atom)); + if(x->x_size5) + freebytes(x->x_at5, x->x_size5 * sizeof(t_atom)); + if(x->x_size3) + freebytes(x->x_at3, x->x_size3 * sizeof(t_atom)); + if(x->x_size2) + freebytes(x->x_at2, x->x_size2 * sizeof(t_atom)); +} + +static void *ambi_rot_new(t_floatarg forder) +{ + t_ambi_rot *x = (t_ambi_rot *)pd_new(ambi_rot_class); + t_atom *at; + int i=(int)forder; + + if(i < 1) + i = 1; + if(i > 12) + i = 12; + x->x_order = i; + x->x_size2 = 2*2 + 2; + x->x_at2 = (t_atom *)getbytes(x->x_size2 * sizeof(t_atom)); + at = x->x_at2; + SETFLOAT(at, 2.0f); + at++; + SETFLOAT(at, 2.0f); + at++; + for(i=0; i<4; i++) + { + SETFLOAT(at, 0.0f); + at++; + } + x->x_size3 = 3*3 + 2; + x->x_at3 = (t_atom *)getbytes(x->x_size3 * sizeof(t_atom)); + at = x->x_at3; + SETFLOAT(at, 3.0f); + at++; + SETFLOAT(at, 3.0f); + at++; + for(i=0; i<9; i++) + { + SETFLOAT(at, 0.0f); + at++; + } + x->x_out3 = outlet_new(&x->x_obj, &s_list); + if(x->x_order >= 2) + { + x->x_size5 = 5*5 + 2; + x->x_at5 = (t_atom *)getbytes(x->x_size5 * sizeof(t_atom)); + at = x->x_at5; + SETFLOAT(at, 5.0f); + at++; + SETFLOAT(at, 5.0f); + at++; + for(i=0; i<25; i++) + { + SETFLOAT(at, 0.0f); + at++; + } + x->x_out5 = outlet_new(&x->x_obj, &s_list); + } + else + { + x->x_size5 = 0; + x->x_at5 = (t_atom *)0; + } + if(x->x_order >= 3) + { + x->x_size7 = 7*7 + 2; + x->x_at7 = (t_atom *)getbytes(x->x_size7 * sizeof(t_atom)); + at = x->x_at7; + SETFLOAT(at, 7.0f); + at++; + SETFLOAT(at, 7.0f); + at++; + for(i=0; i<49; i++) + { + SETFLOAT(at, 0.0f); + at++; + } + x->x_out7 = outlet_new(&x->x_obj, &s_list); + } + else + { + x->x_size7 = 0; + x->x_at7 = (t_atom *)0; + } + if(x->x_order >= 4) + { + x->x_size9 = 9*9 + 2; + x->x_at9 = (t_atom *)getbytes(x->x_size9 * sizeof(t_atom)); + at = x->x_at9; + SETFLOAT(at, 9.0f); + at++; + SETFLOAT(at, 9.0f); + at++; + for(i=0; i<81; i++) + { + SETFLOAT(at, 0.0f); + at++; + } + x->x_out9 = outlet_new(&x->x_obj, &s_list); + } + else + { + x->x_size9 = 0; + x->x_at9 = (t_atom *)0; + } + + if(x->x_order >= 5) + { + x->x_size11 = 11*11 + 2; + x->x_at11 = (t_atom *)getbytes(x->x_size11 * sizeof(t_atom)); + at = x->x_at11; + SETFLOAT(at, 11.0f); + at++; + SETFLOAT(at, 11.0f); + at++; + for(i=0; i<121; i++) + { + SETFLOAT(at, 0.0f); + at++; + } + x->x_out11 = outlet_new(&x->x_obj, &s_list); + } + else + { + x->x_size11 = 0; + x->x_at11 = (t_atom *)0; + } + + if(x->x_order >= 6) + x->x_out13 = outlet_new(&x->x_obj, &s_list); + + if(x->x_order >= 7) + x->x_out15 = outlet_new(&x->x_obj, &s_list); + + if(x->x_order >= 8) + x->x_out17 = outlet_new(&x->x_obj, &s_list); + + if(x->x_order >= 9) + x->x_out19 = outlet_new(&x->x_obj, &s_list); + + if(x->x_order >= 10) + x->x_out21 = outlet_new(&x->x_obj, &s_list); + + if(x->x_order >= 11) + x->x_out23 = outlet_new(&x->x_obj, &s_list); + + if(x->x_order >= 12) + x->x_out25 = outlet_new(&x->x_obj, &s_list); + + x->x_sqrt2_16 = (float)(sqrt(2.0) / 16.0); + x->x_sqrt3_2 = (float)(sqrt(3.0) / 2.0); + x->x_sqrt5_32 = (float)(sqrt(5.0) / 32.0); + x->x_sqrt6_4 = (float)(sqrt(6.0) / 4.0); + x->x_sqrt7_8 = (float)(sqrt(7.0) / 8.0); + x->x_sqrt10_4 = (float)(sqrt(10.0) / 4.0); + x->x_sqrt14_16 = (float)(sqrt(14.0) / 16.0); + x->x_sqrt15_8 = (float)(sqrt(15.0) / 8.0); + x->x_sqrt35_64 = (float)(sqrt(35.0) / 64.0); + x->x_sqrt70_32 = (float)(sqrt(70.0) / 32.0); + + x->x_pi_over_180 = (float)(4.0 * atan(1.0) / 180.0); + + x->x_s_matrix = gensym("matrix"); + return (x); +} + +void ambi_rot_setup(void) +{ + ambi_rot_class = class_new(gensym("ambi_rot"), (t_newmethod)ambi_rot_new, (t_method)ambi_rot_free, + sizeof(t_ambi_rot), 0, A_DEFFLOAT, 0); + class_addfloat(ambi_rot_class, (t_method)ambi_rot_float); + class_addlist(ambi_rot_class, (t_method)ambi_rot_list); + class_sethelpsymbol(ambi_rot_class, gensym("iemhelp2/help-ambi_rot")); +} diff --git a/src/configure.ac b/src/configure.ac new file mode 100644 index 0000000..937ec7f --- /dev/null +++ b/src/configure.ac @@ -0,0 +1,292 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(iem_bin_ambi.c) + +dnl Checks for programs. +AC_PROG_CC + +AC_SUBST(STK) +AC_SUBST(DFLAGS) +AC_SUBST(LFLAGS) +AC_SUBST(EXT) +AC_SUBST(LD) +AC_SUBST(STRIP) +AC_SUBST(STRIPFLAGS) +AC_SUBST(IEMBINAMBI_VERSION) +AC_SUBST(REFERENCEPATH) +AC_SUBST(PDLIBDIR) +AC_SUBST(INCLUDES) + + +AC_ARG_WITH(pdversion, [ --with-pdversion= enforce a certain pd-version (e.g. 0.37)]) +AC_ARG_WITH(version, [ --with-version= enforce a certain iem_bin_ambi-version (e.g. 0.1)]) +AC_ARG_WITH(extension, [ --with-extension= enforce a certain extension for the dynamic library (e.g. dll)]) +AC_ARG_WITH(pdpath, [ --with-pd= where to look for pd-headers and and -libs]) +AC_ARG_ENABLE(PIC, [ --disable-PIC disable compilation with PIC-flag]) + +dnl Checks for libraries. +dnl Replace `main' with a function in -lc: +AC_CHECK_LIB(c, main) +AC_CHECK_LIB(crtdll, fclose) + +dnl Replace `main' with a function in -lm: +AC_CHECK_LIB(m, main) +dnl Replace `main' with a function in -lpthread: +dnl AC_CHECK_LIB(pthread, main) +dnl Replace `main' with a function in -lstk: +dnl AC_CHECK_LIB(stk, main, STK=yes) + + +if test "x$with_pd" != "x"; then + if test -d "${with_pd}/src"; then + INCLUDES="-I${with_pd}/src ${INCLUDES}" + fi + if test -d "${with_pd}/bin"; then + LIBS="-L${with_pd}/bin ${LIBS}" + fi +fi + +if test "x$includedir" != "x"; then + for id in $includedir + do + if test -d $id; then INCLUDES="-I$id $INCLUDES"; fi + done +fi +if test "x$libdir" != "x"; then + for id in $libdir + do + if test -d $id; then LIBS="-L$id $LIBS"; fi + done +fi + +AC_CHECK_LIB(pd, nullfn) + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS(stdlib.h stdio.h string.h math.h time.h sys/time.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_HEADER_TIME + +dnl Checks for library functions. +AC_FUNC_MMAP +AC_CHECK_FUNCS(select socket strerror) + + +### make-depend flags +if test "x$ac_cv_c_compiler_gnu" = "xyes"; then + AC_SUBST(MAKEDEP_FLAGS, "-MM") +else + AC_SUBST(MAKEDEP_FLAGS, "-M") +fi + +dnl check for "-mms-bitfields" cflag +dnl why is there no generic compiler-check for a given flag ? +dnl it would make things so easy: AC_CHECK_FLAG([-mms-bitfields],,) +AC_MSG_CHECKING("ms-bitfields") +cat > conftest.c << EOF +int main(){ + return 0; +} +EOF +if ${CC} ${INCLUDES} ${DFLAGS} -o conftest.o conftest.c ${CFLAGS} -mms-bitfields > /dev/null 2>&1 +then + echo "yes" + CFLAGS="${CFLAGS} -mms-bitfields" +else + echo "no" +fi + + + + +dnl isn't there a better way to check for good linker/stripper ? + +dnl if we don't have $LD set, we set it to $(CC) +dnl LD=${LD:=$CC} +if test "x$LD" = "x" +then + if test "x$host" != "x" + then + LD=${host}-ld + if $(which ${LD} > /dev/null) + then + : + else + LD="" + fi + fi +fi +LD=${LD:=$CC} + +dnl if we don't have $STRIP set, we set it to ${host}-strip or strip +AC_CHECK_TOOL([STRIP], [strip], [true]) +AC_MSG_CHECKING([if strip is GNU strip]) +if $STRIP -V 2>&1 | grep GNU > /dev/null +then + AC_SUBST(STRIPFLAGS, "--strip-unneeded") + AC_MSG_RESULT([yes]) +else + AC_SUBST(STRIPFLAGS,"-x") + AC_MSG_RESULT([no]) +fi + +DFLAGS="" + + +if test "x$enable_PIC" != "xno"; then +AC_MSG_CHECKING("PIC") +cat > conftest.c << EOF +int main(){ + return 0; +} +EOF +if ${CC} ${INCLUDES} ${DFLAGS} -o conftest.o conftest.c ${CFLAGS} -fPIC > /dev/null 2>&1 +then + echo "yes" + CFLAGS="${CFLAGS} -fPIC" +else + echo "no" +fi +fi + + +dnl +dnl OK, checks for machines are here now +dnl +if test `uname -s` = Linux; +then + LFLAGS="-export_dynamic -shared" + CFLAGS="$CFLAGS" + EXT=pd_linux +fi + +dnl This should use '-bundle_loader /path/to/pd/bin/pd' instead of'-undefined suppress' +dnl then strip might do something +if test `uname -s` = Darwin; +then + LD=cc + LFLAGS="-bundle -undefined suppress -flat_namespace" + EXT=pd_darwin +fi + +if test `uname | sed -e 's/^MINGW.*/NT/'` = NT; +then + LD=gcc + INCLUDES="-I@prefix@/src" + DFLAGS="-D__WIN32__" + LFLAGS="-shared @prefix@/bin/pd.dll" + EXT=dll +else + PDLIBDIR="/lib/pd" +fi + +if test `uname -s` = IRIX64; +then + LFLAGS="-n32 -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \ + -OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \ + -shared -rdata_shared" + EXT=pd_irix6 + dnl DFLAGS="-DUNIX -DIRIX6" +fi + +if test `uname -s` = IRIX32; +then + LFLAGS="-o32 -DUNIX -DIRIX -O2 + -shared -rdata_shared" + EXT=pd_irix5 + dnl DFLAGS="-DUNIX -DIRIX5" +fi + + +if test "x$with_extension" != "x" +then + EXT=$with_extension +fi + + +dnl Checks for pd-version, to set the correct help-path +AC_MSG_CHECKING("pd\>=0.37") + +if test "$with_pdversion" != "" +then +echo -n "($with_pdversion)... " + PD_VERSION="$with_pdversion" +else +if test "x$cross_compiling" = "xno" +then + +cat > conftest.c << EOF +#include +#include "m_pd.h" +int main(){ + printf("%d.%d\n", PD_MAJOR_VERSION, PD_MINOR_VERSION); + return 0; +} +EOF + + if $CC $INCLUDES -o conftest.o conftest.c > /dev/null 2>&1 + then + PD_VERSION=`./conftest.o` + else + PD_VERSION="" + fi + echo -n $PD_VERSION +else +dnl we are cross-compiling... + echo -n "(X)..." + PD_VERSION="0.38" +fi +fi + +let PD_MAJORVERSION=`echo $PD_VERSION | cut -d"." -f1`+0 +let PD_MINORVERSION=`echo $PD_VERSION | cut -d"." -f2`+0 + + + +if test "$PD_MAJORVERSION" -gt 0 || test "$PD_MINORVERSION" -ge 37 +then + REFERENCEPATH=extra/help- + echo " yes" +else + REFERENCEPATH=doc/5.reference/ + echo " no" +fi + + +dnl check for iem_bin_ambi-version (but why...) +AC_MSG_CHECKING("iem_bin_ambi-version") + +if test "$with_version" != "" +then + echo -n "($with_version)... " + IEMBINAMBI_VERSION="$with_version" +else + +if test "x$cross_compiling" = "xno" +then +cat > conftest.c << EOF +#include +#include "iem_bin_ambi.h" +int main(){ + printf("%s\n", VERSION); + return 0; +} +EOF + +if $CC $INCLUDES -o conftest.o conftest.c > /dev/null 2>&1 +then + IEMBINAMBI_VERSION=`./conftest.o` + echo "$IEMBINAMBI_VERSION" +else + IEMBINAMBI_VERSION="" + echo "(unknown)" +fi +else + IEMBINAMBI_VERSION="X" + echo "(X)" +fi +fi + +AC_OUTPUT(Make.config) + +rm -f conftest.* diff --git a/src/iem_ambi.c b/src/iem_ambi.c new file mode 100644 index 0000000..7b06298 --- /dev/null +++ b/src/iem_ambi.c @@ -0,0 +1,44 @@ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. + +iem_ambi written by Thomas Musil, Copyright (c) IEM KUG Graz Austria 2000 - 2005 */ + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + + +#include "m_pd.h" +#include "iemlib.h" + +static t_class *iem_ambi_class; + +static void *iem_ambi_new(void) +{ + t_object *x = (t_object *)pd_new(iem_ambi_class); + + return (x); +} + +void ambi_encode_setup(void); +void ambi_decode_setup(void); +void ambi_decode2_setup(void); +void ambi_decode3_setup(void); +void ambi_decode_cube_setup(void); +void ambi_rot_setup(void); + +/* ------------------------ setup routine ------------------------- */ + +void iem_ambi_setup(void) +{ + ambi_encode_setup(); + ambi_decode_setup(); + ambi_decode2_setup(); + ambi_decode3_setup(); + ambi_decode_cube_setup(); + ambi_rot_setup(); + + post("iem_ambi (R-1.16) library loaded! (c) Thomas Musil 05.2005"); + post(" musil%ciem.at iem KUG Graz Austria", '@'); +} diff --git a/src/iem_ambi.dsp b/src/iem_ambi.dsp new file mode 100644 index 0000000..4285328 --- /dev/null +++ b/src/iem_ambi.dsp @@ -0,0 +1,85 @@ +# Microsoft Developer Studio Project File - Name="iem_ambi" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) External Target" 0x0106 + +CFG=iem_ambi - Win32 Debug +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "iem_ambi.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "iem_ambi.mak" CFG="iem_ambi - Win32 Debug" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "iem_ambi - Win32 Release" (basierend auf "Win32 (x86) External Target") +!MESSAGE "iem_ambi - Win32 Debug" (basierend auf "Win32 (x86) External Target") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "iem_ambi - Win32 Release" + +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Cmd_Line "NMAKE /f makefile_win" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "makefile_win.exe" +# PROP BASE Bsc_Name "makefile_win.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Cmd_Line "NMAKE /f makefile_win" +# PROP Rebuild_Opt "/a" +# PROP Target_File "iem_ambi.exe" +# PROP Bsc_Name "iem_ambi.bsc" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "iem_ambi - Win32 Debug" + +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Cmd_Line "NMAKE /f makefile_win" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "makefile_win.exe" +# PROP BASE Bsc_Name "makefile_win.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Cmd_Line "NMAKE /f makefile_win" +# PROP Rebuild_Opt "/a" +# PROP Target_File "iem_ambi.exe" +# PROP Bsc_Name "iem_ambi.bsc" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "iem_ambi - Win32 Release" +# Name "iem_ambi - Win32 Debug" + +!IF "$(CFG)" == "iem_ambi - Win32 Release" + +!ELSEIF "$(CFG)" == "iem_ambi - Win32 Debug" + +!ENDIF + +# Begin Source File + +SOURCE=.\makefile_win +# End Source File +# End Target +# End Project diff --git a/src/iem_ambi.dsw b/src/iem_ambi.dsw new file mode 100644 index 0000000..7674a52 --- /dev/null +++ b/src/iem_ambi.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN! + +############################################################################### + +Project: "iem_ambi"=.\iem_ambi.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/src/iem_ambi.h b/src/iem_ambi.h new file mode 100644 index 0000000..3283c98 --- /dev/null +++ b/src/iem_ambi.h @@ -0,0 +1,15 @@ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. + +iem_ambi written by Thomas Musil, Copyright (c) IEM KUG Graz Austria 2000 - 2005 */ + +#ifndef __IEMAMBI_H__ +#define __IEMAMBI_H__ + +#define AMBI_LS_REAL 0 +#define AMBI_LS_IND 0 +#define AMBI_LS_MRG 1 +#define AMBI_LS_MIR 2 +#define AMBI_LS_PHT 3 + +#endif diff --git a/src/iem_ambi_sources.h b/src/iem_ambi_sources.h new file mode 100644 index 0000000..cf24fb7 --- /dev/null +++ b/src/iem_ambi_sources.h @@ -0,0 +1,11 @@ +/* iem_bin_ambi-setup autogenerated header-file + * generated by "./makesource.sh" + * !! DO NOT MANUALLY EDIT !! + */ + +#ifndef IEMAMBI_SOURCES_H__ +#define IEMAMBI_SOURCES_H__ +void bin_ambi_calc_HRTF_setup(void); /* bin_ambi_calc_HRTF.c */ +void bin_ambi_reduced_decode_setup(void); /* bin_ambi_reduced_decode.c */ +#endif /* IEMBINAMBI_SOURCES_H__ */ + diff --git a/src/iem_bin_ambi_sources.c b/src/iem_bin_ambi_sources.c new file mode 100644 index 0000000..6d45134 --- /dev/null +++ b/src/iem_bin_ambi_sources.c @@ -0,0 +1,13 @@ +/* iem_bin_ambi-setup autogenerated setup-file + * generated by "./makesource.sh" + * !! DO NOT MANUALLY EDIT !! + */ + +#include "iem_bin_ambi_sources.h" + +void iem_bin_ambi_sources_setup(void) +{ + bin_ambi_calc_HRTF_setup(); /* bin_ambi_calc_HRTF.c */ + bin_ambi_reduced_decode_setup(); /* bin_ambi_reduced_decode.c */ +} + diff --git a/src/iemlib.h b/src/iemlib.h new file mode 100644 index 0000000..c71b0ed --- /dev/null +++ b/src/iemlib.h @@ -0,0 +1,102 @@ +/* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. + +iemlib.h written by Thomas Musil, Copyright (c) IEM KUG Graz Austria 2000 - 2005 */ + +#ifndef __IEMLIB_H__ +#define __IEMLIB_H__ + + +#define IS_A_POINTER(atom,index) ((atom+index)->a_type == A_POINTER) +#define IS_A_FLOAT(atom,index) ((atom+index)->a_type == A_FLOAT) +#define IS_A_SYMBOL(atom,index) ((atom+index)->a_type == A_SYMBOL) +#define IS_A_DOLLAR(atom,index) ((atom+index)->a_type == A_DOLLAR) +#define IS_A_DOLLSYM(atom,index) ((atom+index)->a_type == A_DOLLSYM) +#define IS_A_SEMI(atom,index) ((atom+index)->a_type == A_SEMI) +#define IS_A_COMMA(atom,index) ((atom+index)->a_type == A_COMMA) + + +#ifdef NT +int sys_noloadbang; +//t_symbol *iemgui_key_sym=0; +#include +#else +extern int sys_noloadbang; +//extern t_symbol *iemgui_key_sym; +#include +#endif + +#define DEFDELVS 64 +#define XTRASAMPS 4 +#define SAMPBLK 4 + + +#define UNITBIT32 1572864. /* 3*2^19; bit 32 has place value 1 */ + +/* machine-dependent definitions. These ifdefs really +should have been by CPU type and not by operating system! */ +#ifdef IRIX +/* big-endian. Most significant byte is at low address in memory */ +#define HIOFFSET 0 /* word offset to find MSB */ +#define LOWOFFSET 1 /* word offset to find LSB */ +#define int32 long /* a data type that has 32 bits */ +#else +#ifdef MSW +/* little-endian; most significant byte is at highest address */ +#define HIOFFSET 1 +#define LOWOFFSET 0 +#define int32 long +#else +#ifdef __FreeBSD__ +#include +#if BYTE_ORDER == LITTLE_ENDIAN +#define HIOFFSET 1 +#define LOWOFFSET 0 +#else +#define HIOFFSET 0 /* word offset to find MSB */ +#define LOWOFFSET 1 /* word offset to find LSB */ +#endif /* BYTE_ORDER */ +#include +#define int32 int32_t +#endif +#ifdef __linux__ + +#include + +#if !defined(__BYTE_ORDER) || !defined(__LITTLE_ENDIAN) +#error No byte order defined +#endif + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define HIOFFSET 1 +#define LOWOFFSET 0 +#else +#define HIOFFSET 0 /* word offset to find MSB */ +#define LOWOFFSET 1 /* word offset to find LSB */ +#endif /* __BYTE_ORDER */ + +#include +#define int32 int32_t + +#else +#ifdef __APPLE__ +#define HIOFFSET 0 /* word offset to find MSB */ +#define LOWOFFSET 1 /* word offset to find LSB */ +#define int32 int /* a data type that has 32 bits */ + +#endif /* __APPLE__ */ +#endif /* __linux__ */ +#endif /* MSW */ +#endif /* SGI */ + +union tabfudge +{ + double tf_d; + int32 tf_i[2]; +}; + +#define IEM_DENORMAL(f) ((((*(unsigned int*)&(f))&0x60000000)==0) || \ +(((*(unsigned int*)&(f))&0x60000000)==0x60000000)) +/* more stringent test: anything not between 1e-19 and 1e19 in absolute val */ + +#endif diff --git a/src/makefile_win b/src/makefile_win new file mode 100644 index 0000000..70a1bdb --- /dev/null +++ b/src/makefile_win @@ -0,0 +1,42 @@ + +all: iem_ambi.dll + +VIS_CPP_PATH = "C:\Programme\Microsoft Visual Studio\Vc98" + +PD_INST_PATH = "C:\Programme\pd" + +PD_WIN_INCLUDE_PATH = /I. /I$(PD_INST_PATH)\src /I$(VIS_CPP_PATH)\include + +PD_WIN_C_FLAGS = /nologo /W3 /WX /DMSW /DNT /DPD /DWIN32 /DWINDOWS /Ox -DPA_LITTLE_ENDIAN + +PD_WIN_L_FLAGS = /nologo + +PD_WIN_LIB = /NODEFAULTLIB:libc /NODEFAULTLIB:oldnames /NODEFAULTLIB:kernel /NODEFAULTLIB:uuid \ + $(VIS_CPP_PATH)\lib\libc.lib \ + $(VIS_CPP_PATH)\lib\oldnames.lib \ + $(VIS_CPP_PATH)\lib\kernel32.lib \ + $(VIS_CPP_PATH)\lib\wsock32.lib \ + $(VIS_CPP_PATH)\lib\winmm.lib \ + $(PD_INST_PATH)\bin\pd.lib + + +SRC = ambi_decode.c \ + ambi_decode2.c \ + ambi_decode3.c \ + ambi_decode_cube.c \ + ambi_encode.c \ + ambi_rot.c \ + iem_ambi.c + + +OBJ = $(SRC:.c=.obj) + +.c.obj: + cl $(PD_WIN_C_FLAGS) $(PD_WIN_INCLUDE_PATH) /c $*.c + +iem_ambi.dll: $(OBJ) + link $(PD_WIN_L_FLAGS) /dll /export:iem_ambi_setup \ + /out:iem_ambi.dll $(OBJ) $(PD_WIN_LIB) + +clean: + del *.obj diff --git a/src/makesource.sh b/src/makesource.sh new file mode 100644 index 0000000..32703b1 --- /dev/null +++ b/src/makesource.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +IEMAMBI_H=iem_ambi_sources.h +IEMAMBI_C=iem_ambi_sources.c + +EGREP=egrep +SED=sed +LS=ls + +################################# +## functions + +function head_h() { + echo "/* iem_ambi-setup autogenerated header-file" + echo " * generated by \"$0\"" + echo " * !! DO NOT MANUALLY EDIT !!" + echo " */" + echo + echo "#ifndef IEMAMBI_SOURCES_H__" + echo "#define IEMAMBI_SOURCES_H__" +} + +function foot_h() { + echo "#endif /* IEMAMBI_SOURCES_H__ */" + echo "" +} + +function head_c() { + echo "/* iem_ambi-setup autogenerated setup-file" + echo " * generated by \"$0\"" + echo " * !! DO NOT MANUALLY EDIT !!" + echo " */" + echo + echo "#include \"$IEMAMBI_H\"" + echo + echo "void iem_ambi_sources_setup(void)" + echo "{" +} + +function foot_c() { + echo "}" + echo +} + + +################################## +## body + +head_h > $IEMAMBI_H +head_c > $IEMAMBI_C + +for i in $(${LS} *.c | ${EGREP} -v "iem_bin_ambi.*\.c") +do +## each c-file in iem_ambi needs to have an _setup()-function +## that calls all needed setup-functions +## any non-alpha-numeric-character is replaced by "_" +## e.g. "bla~.c" -> "bla__setup()" + SETUPNAME=$(echo ${i%.c} | ${SED} -e 's/[^[:alnum:]]/_/g')_setup + echo "void ${SETUPNAME}(void); /* $i */" >> $IEMAMBI_H + echo " ${SETUPNAME}(); /* $i */" >> $IEMAMBI_C +done + +foot_h >> $IEMAMBI_H +foot_c >> $IEMAMBI_C + -- cgit v1.2.1