diff --git a/.gitignore b/.gitignore index cad351c0..5b2a2064 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -# Only track the SFS_config_example.m file, not the real configuration -SFS_config.m # omit the directory containing the sample points for a sphere MinimumEnergyPointsOnASphere # Unwanted binary files diff --git a/.zenodo.json b/.zenodo.json new file mode 100644 index 00000000..628f1b8f --- /dev/null +++ b/.zenodo.json @@ -0,0 +1,45 @@ +{ + "description": "

The Sound Field Synthesis Toolbox (SFS) for Matlab/Octave gives you the possibility to play around with sound field synthesis methods like Wave Field Synthesis (WFS) or near-field compensated Higher Order Ambisonics (NFC-HOA). There are functions to simulate monochromatic sound fields for different secondary source (loudspeaker) setups, time snapshots of full band impulses emitted by the secondary source distributions, or even generate Binaural Room Scanning (BRS) stimuli sets in order to simulate WFS with the SoundScape Renderer (SSR).

For more information, see: http://matlab.sfstoolbox.org

", + "access_right": "open", + "license": "mit-license", + "keywords": [ + "WFS", + "NFC-HOA", + "binaural synthesis", + "SSR", + "SOFA", + "SFS" + ], + "upload_type": "software", + "creators": [{ + "name": "Hagen Wierstorf" + }, + { + "name": "Fiete Winter", + "affiliation": "Universität Rostock", + "orcid": "0000-0002-9454-4177" + }, + { + "name": "Till Rettberg", + "affiliation": "Universität Rostock" + }, + { + "name": "Vera Erbes", + "affiliation": "Universität Rostock" + }, + { + "name": "Nara Hahn", + "affiliation": "Universität Rostock" + }, + { + "name": "Frank Schultz", + "affiliation": "Universität Rostock" + }, + { + "name": "Christoph Hold" + }, + { + "name": "Sascha Spors", + "affiliation": "Universität Rostock" + }] +} diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index f142f480..00000000 --- a/AUTHORS +++ /dev/null @@ -1,19 +0,0 @@ -Written by: - - Hagen Wierstorf - Assessment of IP-based Applications - Technische Universität Berlin - - Fiete Winter - Institut für Nachrichtentechnik - Universität Rostock - - Sascha Spors - Institut für Nachrichtentechnik - Universität Rostock - -Scientific supervision: - Sascha Spors - -Contributions by: - Lars-Erik Riechert, Vincent Kuscher, Frank Schultz diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst new file mode 100644 index 00000000..6b2ca102 --- /dev/null +++ b/CONTRIBUTING.rst @@ -0,0 +1,47 @@ +Contributing +------------ + +If you find errors, omissions, inconsistencies or other things that need +improvement, please create an issue or a pull request at +https://github.com/sfstoolbox/sfs-matlab/. +Contributions are always welcome! + +Building the Documentation +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you make changes to the documentation, you can re-create the HTML pages +using Sphinx_. +You can install it and a few other necessary packages with:: + + python3 -m pip install -r doc/requirements.txt --user + +To create the HTML pages, use:: + + sphinx-build -b html -d ./_build/doctrees . ./_build/html-preview/ + +The generated files will be available in the directory +``build/sphinx/html-preview/``. + +.. _Sphinx: http://sphinx-doc.org/ + +Creating a New Release +^^^^^^^^^^^^^^^^^^^^^^ + +New releases are made using the following steps: + +#. Bump version number in ``SFS_version.m`` +#. Update ``NEWS`` +#. Commit those changes as "Release x.y.z" +#. Create an (annotated) tag with ``git tag -a x.y.z`` +#. Check that all author details in ``.zenodo.json`` are correct +#. Push the commit and the tag to Github and `add release notes`_ containing a + link to the documentation with https://sfs-matlab.readthedocs.io/en/x.y.z and + the bullet points from ``NEWS`` +#. Check that the new release was built correctly on RTD_, delete the "stable" + version and select the new release as default version +#. Check that the new release was registered at Zenodo_ and edit the release + notes on Github to include the DOI badge + +.. _add release notes: https://github.com/sfstoolbox/sfs-matlab/tags +.. _RTD: https://readthedocs.org/projects/sfs-matlab/builds/ +.. _Zenodo: https://zenodo.org/search?page=1&size=20&q=SFS%20Toolbox&sort=bestmatch diff --git a/COPYING b/COPYING deleted file mode 100644 index 94a9ed02..00000000 --- a/COPYING +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. 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 -them 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 prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. 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. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey 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; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If 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 convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU 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 that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - 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. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -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. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - 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 -state 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 3 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, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program 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, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU 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 Lesser General -Public License instead of this License. But first, please read -. diff --git a/INSTALL b/INSTALL deleted file mode 100644 index 777fb327..00000000 --- a/INSTALL +++ /dev/null @@ -1,14 +0,0 @@ -Installation Instructions -************************* - -Download the Toolbox and add the main path of the Toolbox to your Matlab/Octave -path. After that copy SFS_config_example.m to SFS_config.m and change it to your -needs. For an easy beginning you can just use the default settings by leaving -everything as it is. -Then start the Toolbox with SFS_start; which will add all needed -subpathes. - -If you are using Octave you will need the following additional packages from -octave-forge (http://octave.sourceforge.net/): -* audio (e.g. for wavwrite) -* signal (e.g. for firls) diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..89323389 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2010-2019 SFS Toolbox Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/NEWS b/NEWS index 031c73dd..e7da0b7b 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,126 @@ -Changes in the Sound Field Synthesis-Toolbox. Recent changes on top. +2.5.0 (18. March 2019) + - Add voronoi interpolation for impulse responses + - Fix phase offset of Linkwitz-Riley Allpass Filters + - Add modal window to monochromatic NFC-HOA driving functions + - Update equation links to https://sfs.rtfd.io/en/3.2/ + +2.4.3 (26. October 2018) + - fix bug where in LWFS-SBL, where inverse Allpass was inverted + +2.4.2 (14. March 2018) + - extend signal_from_spectrum and spectrum_from_signal to N-dim matrices + - remove obsolete *_localwfs functions + - add optional logarithmic spacing for linear secondary sources + +2.4.1 (28. September 2017) + - add monochromatic implementation of LWFS using spatial bandwidth-limitation + - add monochromatic circular expansion functions for ps and pw + - add function for conversion from circular to plane wave expansion + - add freq_response_* and time_response_* for all LWFS methods + - add optional message arg to progress_bar() + - fix missing conf.N in freq_response_nfchoa() + - fix auralize_ir() for local files + +2.4.0 (22. August 2017) + - improve references in SFS_config() + - update structure of configuration for LWFS methods + - fix off-center dummy head positions for HRTFs + - add elevation to head orientation for binaural synthesis + - fix sphbesselh_zeros() for high orders + - fix symmetric ifft for Octave + - add inverse Legendre transform + - fix integral weights for spherical secondary sources + - add 3D ps and pw driving functions for NFC-HOA + - add 'reference_circle' as new default for focused sources in 2.5D + - add max-rE and tukey modal weighting windows + - add time-domain implementation of LWFS using spatial bandwidth-limitation + - add circular expansion functions + - fix incorporation of tapering weights for LWFS + - remove x0 from interpolate_ir() call + - fix interpolate_ir() for special cases + - switch handling of time from samples to seconds + - add freq_response_line_source() + - add freq_response_point_source() + - add time_response_line_source() + +2.3.0 (04. March 2017) + - default 2D WFS focused source is now a line sink + - improve point selection and interpolation of impulse responses + - speed up Parks-McClellan resampling method + - change default value of conf.usebandpass to false + - rename conf.wfs.t0 to conf.t0 + - rename and improve easyffft() to spectrum_from_signal() + - rename and improve easyifft() to signal_from_spectrum() + - correct amplitude values of WFS and NFC-HOA in time domain + - fix default 2.5D WFS driving function in time domain + - add time_response_point_source() + - update amplitude and position of dirac in dummy_irs() + - fix missing secondary source selection in ssr_brs_wfs() + - add amplitude terms to WFS FIR pre-filter + - fix Gauss-Legendre quadrature weights + - add delay_offset as return value to NFC-HOA and ir funtions + - fix handling of delay_offset in WFS time domain driving functions + +2.2.1 (22. August 2016) + - fix delayoffset for FIR fractional delay filter + - add findconvexcone() + - simplify convolution() + - add linear interpolation working in the frequency domain + - fix pm option for delayline() + +2.2.0 (7. July 2016) + - fix impulse response interpolation for three points + - add the ability to apply modal weighting window to NFC-HOA in time domain + - change license to MIT + - update delayline() config settings + - add Lagrange and Thiran filters to delayline() + - replace wavread and warwrite by audioread and savewav + - convolution() excepts now two matrices as input + - allow headphone compensation filter to be a one- or two-channel wav file + - add new online doc at http://matlab.sfstoolbox.org/ + - fix greens_function_mono() for plane wave and 3D + - replace conf.ir.useoriglength by conf.ir.hrirpredelay + - update default WFS driving functions + - add links to equations in online theory at https://sfs.rtfd.io/ + +2.1.0 (10. March 2016) + - make conf struct mandatory + - add new start message + - fix handling of 0 in least squares fractional delays + - fix NFC-HOA order for even loudspeaker numbers to N/2-1 + - add conf.wfs.hpreFIRorder as new config option (was hard coded to 128 + before) + - speed up secondary source selection for WFS + - rename chromajs colormap to yellowred + - fix tapering_window() for non-continuous secondary sources + - remove cubehelix colormap as it is part of Octave + - add conf.wfs.t0 option which is useful, if you have more than one + virtual source + - virtual line sources are now available for monochromatic WFS and NFC-HOA + - allow arbritrary orders for time-domain NFC-HOA simulations + +2.0.0 (26. October 2015) + - add support for SOFA + - add SOFA convention SimpleFreeFieldHRIR + - add SOFA convention MultiSpeakerBRIR + - calculate integration weights (x0(:,7)) of secondary sources based on their + distances to their neighbours + - add rounded-box as new loudspeaker array geometry + - fix bugs in local sound field synthesis time domain implementation + - speedup local sound field synthesis processing by fewer calls to + delayline() + - add heuristic to find a good local wave field synthesis pre-filter + - loudspeaker geometry can now be read from a SOFA file + - now custom grids can be used during sound field simulations + - add 3D plot routine + - change plot_sound_field(P,x,y,z) to plot_sound_field(P,X,Y,Z) + - normalization of sound field now only happens in plot_sound_field(); this + comes with the new config option conf.plot.normalisation + - remove interaural_level_difference() and interaural_time_difference() + - change default config setting conf.ir.usehcomp to false + - lots of small bug fixes 1.2.0 (2. June 2015) - - add PDF documentation "Theory of Sound Field Synthesis" - fix remaining usegnuplot config entry - change default dB color map to chromajs @@ -10,7 +129,6 @@ Changes in the Sound Field Synthesis-Toolbox. Recent changes on top. - remove noise() function, use the one from the LTFAT Toolbox instead 1.1.0 (2. April 2015) - - fix amplitude bug in get_ir() and ir_generic() - remove direct gnuplot plotting - add support for local Wave Field Synthesis @@ -19,7 +137,6 @@ Changes in the Sound Field Synthesis-Toolbox. Recent changes on top. - correct the sign for Wave Field Synthesis driving functions 1.0.1 (4 August 2014) - - rms() works now also with row vectors in order to be compatible with the Auditory Modeling Toolbox - fixed handling of number of secondary sources for a box shaped array @@ -27,7 +144,6 @@ Changes in the Sound Field Synthesis-Toolbox. Recent changes on top. - corrected NFC-HOA driving functions for off-center arrays 1.0.0 (27 March 2014) - - added references for all driving functions - streamlined nested conf settings; e.g. now it is no longer neccessary to set conf.ir.hcompfile if conf.usehcomp == false @@ -42,7 +158,6 @@ Changes in the Sound Field Synthesis-Toolbox. Recent changes on top. - several small fixes 1.0.0-beta2 (5 December 2013) - - rms() now works for arbitrary arrays - speedup of delayline() and HRTF extrapolation - delayline() now works with more than one channel @@ -54,7 +169,6 @@ Changes in the Sound Field Synthesis-Toolbox. Recent changes on top. - several minor fixes 1.0.0-beta (26 August 2013) - - bandpass() can now handle arbritrary frequency limits - sphbesselh_zeros() comes now with precomputed zeros for an order up to 1000 @@ -91,12 +205,10 @@ Changes in the Sound Field Synthesis-Toolbox. Recent changes on top. into xs. For a focused source xs is now [1x6] 0.2.5 (12 July 2013) - - fixed a bug causing the wrong loudspeaker position in the output of generic_wfs() 0.2.4 (4 June 2013) - - added a documentation to the github README - reworked the plotting, now simple saving to png is possible - added a narginchk function for older Matlab versions @@ -104,16 +216,14 @@ Changes in the Sound Field Synthesis-Toolbox. Recent changes on top. - lots of small bugs were fixed 0.2.3 (9 April 2013) - - summed up line, point, ... sources to green_function for mono and imp - introduced global wave_field functions for mono and imp - - fixed binaural simulations for NFCHOA + - fixed binaural simulations for NFC-HOA - removed compatibility for octave versions <3.6 - fixed a critical bug for the HRTF farfield extrapolation, due to the new secondary source selection behavior 0.2.2 (27 November 2012) - - added functions to calculate the sound pressure for monochromatic WFS at a single point in analogy to the point_source function - changed the behavior of secondary_source_selection to returning a new x0 @@ -123,18 +233,17 @@ Changes in the Sound Field Synthesis-Toolbox. Recent changes on top. point always in the direction of the reference point) 0.2.1 (15 June 2012) - - - added NFCHOA 2.5D monochromatic - - added NFCHOA 2.5D binaural simulations + - added NFC-HOA 2.5D monochromatic + - added NFC-HOA 2.5D binaural simulations - added SDM 2.5D monochromatic - - make NFCHOA work under Octave - - fixed direction of plane waves and point sources for NFCHOA time domain + - make NFC-HOA work under Octave + - fixed direction of plane waves and point sources for NFC-HOA time domain simulations - changed syntax for wave_field_* and driving_* functions: - xs,f,src => xs,src,f - xs,L,src => xs,src,L - xs,L,f,src => xs,src,f,L -0.2.0 (25 April 2012) + * xs,f,src => xs,src,f + * xs,L,src => xs,src,L + * xs,L,f,src => xs,src,f,L +0.2.0 (25 April 2012) - first public release (under the GPLv3+ license) diff --git a/README.md b/README.md deleted file mode 100644 index 86caef0d..00000000 --- a/README.md +++ /dev/null @@ -1,590 +0,0 @@ -Sound Field Synthesis Toolbox -============================= - -The Sound Field Synthesis Toolbox (SFS) for Matlab/Octave gives you the -possibility to play around with sound field synthesis methods like Wave Field -Synthesis (WFS) or near-field compensated Higher Order Ambisonics (NFC-HOA). -There are functions to simulate monochromatic sound fields for different secondary -source (loudspeaker) setups, time snapshots of full band impulses emitted by the -secondary source distributions, or even generate Binaural Room Scanning (BRS) -stimuli sets in order to simulate WFS with the SoundScape Renderer (SSR). - -This documentation is all about its usage, if you are interested in the -underlying mathematics you should have a look at its PDF documentation [Theory -of Sound Field -Synthesis](https://github.com/sfstoolbox/sfs-documentation/releases/latest). - -### Table of Contents - -**[Installation](#installation)** -**[Requirements](#requirements)** -**[Usage](#usage)** - [Secondary Sources](#secondary-sources) - [Simulate Monochromatic Sound Fields](#simulate-monochromatic-sound-fields) - [Simulate Time Snapshots of Sound Fields](#simulate-time-snapshots-of-sound-fields) - [Make Binaural Simulations of Your Systems](#make-binaural-simulations-of-your-systems) - [Small helper functions](#small-helper-functions) - [Plotting with Matlab or gnuplot](#plotting-with-matlab-or-gnuplot) -**[Credits and License](#credits-and-license)** - - -Installation ------------- - -Download the Toolbox and add the main path of the Toolbox to your Matlab/Octave -path. After that copy SFS_config_example.m to -SFS_config.m and change it to your needs. For an easy beginning you -can just use the default settings by leaving everything as it is. -Then start the Toolbox with SFS_start which will add all needed -subpathes. - - -Requirements ------------- - -**Matlab** -You need Matlab version 2011b or newer to run the Toolbox. -On older version the Toolbox should also work, but you need to add -[narginchk.m](http://gist.github.com/hagenw/5642886) to the -SFS_helper -directory. - -**Octave** -You need Octave version 3.6 or newer to run the Toolbox. In addition, -you will need the following additional packages from -[octave-forge](http://octave.sourceforge.net/): -* audio (e.g. for wavwrite) -* signal (e.g. for firls) - -After setting up the Toolbox and can made one of the magic following things with it: - -Usage ------ - -### Secondary Sources - -The Toolbox comes with a function which can generate different common shapes of loudspeaker arrays for you. -At the moment linear, circular, box shaped and spherical arrays are included out -of the box. - -Before showing the different geometries, we start with some common settings. First we get a configuration struct -and set the array size/diameter to 3m. - -```Matlab -conf = SFS_config_example; -conf.secondary_sources.size = 3; -``` - -#### Linear Array - -```Matlab -conf = SFS_config_example; -conf.secondary_sources.geometry = 'line'; % or 'linear' -conf.secondary_sources.number = 21; -x0 = secondary_source_positions(conf); -figure; -figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); -draw_loudspeakers(x0,conf); -axis([-2 2 -2 1]); -%print_png('img/secondary_sources_linear.png'); -``` - -![Image](doc/img/secondary_sources_linear.png) - -#### Circular Array - -```Matlab -conf = SFS_config_example; -conf.secondary_sources.geometry = 'circle'; % or 'circular' -conf.secondary_sources.number = 56; -x0 = secondary_source_positions(conf); -figure; -figsize(540,404,'px'); -draw_loudspeakers(x0,conf); -axis([-2 2 -2 2]); -%print_png('img/secondary_sources_circle.png'); -``` - -![Image](doc/img/secondary_sources_circle.png) - -#### Box Shaped Array - -```Matlab -conf = SFS_config_example; -conf.secondary_sources.geometry = 'box'; -conf.secondary_sources.number = 84; -x0 = secondary_source_positions(conf); -figure; -figsize(540,404,'px'); -draw_loudspeakers(x0,conf); -axis([-2 2 -2 2]); -%print_png('img/secondary_sources_box.png'); -``` - -![Image](doc/img/secondary_sources_box.png) - -#### Spherical Array - -For a spherical array you need a grid to place the secondary sources on the -sphere. At the moment we provide grids with the Toolbox, that can be find here: -http://github.com/sfstoolbox/data/tree/master/spherical_grids -You have to specify your desired grid, for example -conf.secondary_sources.grid = 'equally_spaced_points'. The -secondary_source_positions() functions will then automatically -download the desired grid from that web page and stores it under -<$SFS_MAIN_PATH>/data. If the download is not working (which can -happen under Matlab and Windows at the moment) you can alternatively checkout or -download the whole [data repository](http://github.com/sfstoolbox/data) to the -data folder. - -```Matlab -conf = SFS_config_example; -conf.secondary_sources.size = 3; -conf.secondary_sources.geometry = 'sphere'; % or 'spherical' -conf.secondary_sources.grid = 'equally_spaced_points'; -conf.secondary_sources.number = 225; -x0 = secondary_source_positions(conf); -figure; -figsize(540,404,'px'); -draw_loudspeakers(x0,conf); -axis([-2 2 -2 2]); -%print_png('img/secondary_sources_sphere.png'); -``` - -![Image](doc/img/secondary_sources_sphere.png) - -#### Arbitrary Shaped Arrays - -You can create arbitrarily shaped arrays by settings the values of the single -loudspeaker directly in the conf.secondary_sources.x0 matrix, which -has to be empty if you want to use one of the above predefined shapes. The rows -of the matrix contain the single loudspeakers and the six columns are -[x y z nx ny nz w], the position and direction and weight of the -single loudspeakers. The weight w is a factor the driving function -of this particular loudspeaker is multiplied with in a function that calculates -the sound field from the given driving signals and secondary sources. For WFS -w could include the tapering window, a spherical grid weight, and -the r^2 cos(theta) weights for integration on a sphere. - -```Matlab -conf = SFS_config_example; -% create a stadium like shape by combining two half circles with two linear -% arrays -% first getting a full circle with 56 loudspeakers -conf.secondary_sources.geometry = 'circle'; -conf.secondary_sources.number = 56; -conf.secondary_sources.x0 = []; -x0 = secondary_source_positions(conf); -% store the first half cricle and move it up -x01 = x0(2:28,:); -x01(:,2) = x01(:,2) + ones(size(x01,1),1)*0.5; -% store the second half circle and move it down -x03 = x0(30:56,:); -x03(:,2) = x03(:,2) - ones(size(x03,1),1)*0.5; -% create a linear array -conf.secondary_sources.geometry = 'line'; -conf.secondary_sources.number = 7; -conf.secondary_sources.size = 1; -x0 = secondary_source_positions(conf); -% rotate it and move it left -R = rotation_matrix(pi/2); -x02 = [(R*x0(:,1:3)')' (R*x0(:,4:6)')']; -x02(:,1) = x02(:,1) - ones(size(x0,1),1)*1.5; -x02(:,7) = x0(:,7); -% rotate it the other way around and move it right -R = rotation_matrix(-pi/2); -x04 = [(R*x0(:,1:3)')' (R*x0(:,4:6)')']; -x04(:,1) = x04(:,1) + ones(size(x0,1),1)*1.5; -x04(:,7) = x0(:,7); -% combine everything -conf.secondary_sources.x0 = [x01; x02; x03; x04]; -% if we gave the conf.x0 to the secondary_source_positions function it will -% simply return the defined x0 matrix -x0 = secondary_source_positions(conf); -figure; -figsize(540,404,'px'); -draw_loudspeakers(x0,conf); -axis([-2 2 -2.5 2.5]); -%print_png('img/secondary_sources_arbitrary.png'); -``` - -![Image](doc/img/secondary_sources_arbitrary.png) - - -#### Plot Loudspeaker Symbols - -For two dimensional setups you can plot the secondary sources with loudspeaker -symbols, for example the following will replot the last array. - -```Matlab -conf.plot.realloudspeakers = true; -figure; -figsize(540,404,'px'); -draw_loudspeakers(x0,conf); -axis([-2 2 -2.5 2.5]); -%print_png('img/secondary_sources_arbitrary_realloudspeakers.png'); -``` - -![Image](doc/img/secondary_sources_arbitrary_realloudspeakers.png) - - -### Simulate Monochromatic Sound Fields - -With the files in SFS_monochromatic you can simulate a -monochromatic sound field in a specified area for different techniques like WFS -and NFC-HOA. The area can be a 3D cube, a 2D plane, a line or only one point. -This depends on the specification of X,Y,Z. For example -[-2 2],[-2 2],[-2 2] will be a 3D cube; -[-2 2],0,[-2 2] the xz-plane; [-2 2],0,0 a line along -the x-axis; 3,2,1 a single point. - -For all 2.5D functions the configuration conf.xref is important as -it defines the point for which the amplitude is corrected in the sound field. -The default entry is -```Matlab -conf.xref = [0 0 0]; -``` - -#### Wave Field Synthesis - -The following will simulate the field of a virtual plane wave with a frequency -of 800 Hz going into the direction of (0 -1 0) synthesized with 3D WFS. - -```Matlab -conf = SFS_config_example; -conf.dimension = '3D'; -conf.secondary_sources.size = 3; -conf.secondary_sources.number = 225; -conf.secondary_sources.geometry = 'sphere'; -% [P,x,y,z,x0,win] = sound_field_mono_wfs(X,Y,Z,xs,src,f,conf); -sound_field_mono_wfs([-2 2],[-2 2],0,[0 -1 0],'pw',800,conf); -%print_png('img/sound_field_wfs_3d_xy.png'); -sound_field_mono_wfs([-2 2],0,[-2 2],[0 -1 0],'pw',800,conf); -%print_png('img/sound_field_wfs_3d_xz.png'); -sound_field_mono_wfs(0,[-2 2],[-2 2],[0 -1 0],'pw',800,conf); -%print_png('img/sound_field_wfs_3d_yz.png'); -``` - -![Image](doc/img/sound_field_wfs_3d_xy.png) - -![Image](doc/img/sound_field_wfs_3d_xz.png) - -![Image](doc/img/sound_field_wfs_3d_yz.png) - - -You can see that the Toolbox is now projecting all the secondary source positions -into the plane for plotting them. In addition the axis are automatically chosen -and labeled. - -In the next plot we use a two dimensional array, 2.5D WFS and a virtual point source -located at (0 2.5 0) m. The 3D example showed you, that the sound fields are -automatically plotted if we specify now output arguments. If we specify one, we -have to explicitly say if we want also plot the results, by -conf.plot.useplot = true;. - -```Matlab -conf = SFS_config_example; -conf.dimension = '2.5D'; -conf.plot.useplot = 1; -% [P,x,y,z,x0] = sound_field_mono_wfs(X,Y,Z,xs,src,f,conf); -[P,x,y,z,x0] = sound_field_mono_wfs([-2 2],[-2 2],0,[0 2.5 0],'ps',800,conf); -%print_png('img/sound_field_wfs_25d.png'); -``` - -![Image](doc/img/sound_field_wfs_25d.png) - -If you want to plot the whole array and not only the active secondary sources, -you can do this by adding these commands. First we store all sources in an extra -variable x0_all, then we get the active ones x0 and -the corresponding indices of these active ones in x0_all. -Afterwards we set all sources in x0_all to zero, which is inactive -and only the active ones to x0(:,7). - -```Matlab -x0_all = secondary_source_positions(conf); -[x0,idx] = secondary_source_selection(x0_all,[0 2.5 0],'ps'); -x0_all(:,7) = zeros(1,size(x0_all,1)); -x0_all(idx,7) = x0(:,7); -plot_sound_field(P,x,y,z,x0_all,conf); -%print_png('img/sound_field_wfs_25d_with_all_sources.png'); -``` - -![Image](doc/img/sound_field_wfs_25d_with_all_sources.png) - - -#### Near-Field Compensated Higher Order Ambisonics - -In the following we will simulate the field of a virtual plane wave with a frequency -of 800 Hz traveling into the direction (0 -1 0), synthesized with 2.5D NFC-HOA. - -```Matlab -conf = SFS_config_example; -conf.dimension = '2.5D'; -% sound_field_mono_nfchoa(X,Y,Z,xs,src,f,conf); -sound_field_mono_nfchoa([-2 2],[-2 2],0,[0 -1 0],'pw',800,conf); -%print_png('img/sound_field_nfchoa_25d.png'); -``` - -![Image](doc/img/sound_field_nfchoa_25d.png) - - -#### Local Wave Field Synthesis - -In Near-Field Compensated Higher Order Ambisonics aliasing frequency in a small -array inside the listening area can be increased by limiting the used order. A -similar outcome can be achoieved in Wave Field Synthesis by applying so called -local Wave Field Synthesis. In this case the original loudspeaker array is -driven by Wave Field Synthesis to create a virtual loudspeaker array consisting -of focused sources which can then be used to create the desired sound field in a -small area. -The settings are the same as for Wave Field Synthesis, but a new struct -conf.localsfs has to be filled out, which for example provides the -settings for the desired position and form of the local area with higher -aliasing frequency. - -```Matlab -conf = SFS_config_example; -conf.resolution = 1000; -conf.dimension = '2D'; -conf.secondary_sources.geometry = 'box'; -conf.secondary_sources.number = 4*56; -conf.secondary_sources.size = 2; -conf.localsfs.vss.size = 0.4; -conf.localsfs.vss.center = [0 0 0]; -conf.localsfs.vss.geometry = 'circular'; -conf.localsfs.vss.number = 56; -% sound_field_mono_localwfs(X,Y,Z,xs,src,f,conf); -sound_field_mono_localwfs([-1 1],[-1 1],0,[1.0 -1.0 0],'pw',7000,conf); -axis([-1.1 1.1 -1.1 1.1]); -%print_png('img/sound_field_localwfs_2d.png'); -``` - -![Image](doc/img/sound_field_localwfs_2d.png) - - -#### Stereo - -The Toolbox includes not only WFS and NFC-HOA, but also some generic sound field -functions that are doing only the integration of the driving signals of the -single secondary sources to the resulting sound field. With these function you -can for example easily simulate a stereophonic setup. - -```Matlab -conf = SFS_config_example; -x0 = [-1 2 0 0 -1 0 1;1 2 0 0 -1 0 1]; -% [P,x,y,z] = sound_field_mono(X,Y,Z,x0,src,D,f,conf) -sound_field_mono([-2 2],[-1 3],0,x0,'ps',[1 1],800,conf) -%print_png('img/sound_field_stereo.png'); -``` -![Image](doc/img/sound_field_stereo.png) - - -### Simulate Time Snapshots of Sound Fields - -With the files in SFS_time_domain you can simulate snapshots in -time of an impulse originating from your WFS or NFC-HOA system. - -In the following we will create a snapshot in time after 200 samples for a broadband -virtual point source placed at (0 2 0) m for 2.5D NFC-HOA. - -```Matlab -conf = SFS_config_example; -conf.dimension = '2.5D'; -conf.plot.useplot = true; -% sound_field_imp_nfchoa(X,Y,Z,xs,src,t,conf) -[p,x,y,z,x0] = sound_field_imp_nfchoa([-2 2],[-2 2],0,[0 2 0],'ps',200,conf); -%print_png('img/sound_field_imp_nfchoa_25d.png'); -``` - -![Image](doc/img/sound_field_imp_nfchoa_25d.png) - -The output can also be plotted in dB by setting conf.plot.usedb = -true;. In this case the default color map is changed and a color bar -is plotted in the figure. For none dB plots no color bar is shown in the plots. -In these cases the color coding goes always from -1 to 1, with clipping of -larger values. -You could change the color - -```Matlab -conf.plot.usedb = true; -plot_sound_field(p,x,y,z,x0,conf); -%print_png('img/sound_field_imp_nfchoa_25d_dB.png'); -``` - -![Image](doc/img/sound_field_imp_nfchoa_25d_dB.png) - -You could change the color map yourself doing the following before the plot -command. - -```Matlab -conf.plot.colormap = 'jet'; % Matlab rainbow color map -``` - -### Make Binaural Simulations of Your Systems - -If you have a set of head-related transfer functions (HRTFs) you can simulate -the ear signals reaching a listener sitting at a given point in the listening -area for a specified WFS or NFC-HOA system. -You can even download a set of HRTFs, which will just work with the Toolbox at -http://dev.qu.tu-berlin.de/projects/measurements/wiki/2010-11-kemar-anechoic - -In order to easily use different HRIR sets the toolbox incorporates its own -[struct based file -format](http://dev.qu.tu-berlin.de/projects/measurements/wiki/IRs_file_format) -for HRIRs and BRIRs. The toolbox provides conversion functions for three other -free available data sets (CIPIC,MIT,Oldenburg). In the future it will -incorporate the newly advancing [SOFA HRTF file -format](http://sourceforge.net/projects/sofacoustics). - -The files dealing with the binaural simulations are in the folder -SFS_binaural_synthesis. Files dealing with HRTFs are in the folder -SFS_ir. If you want to extrapolate your HRTFs to plane waves you -may also want to have a look in SFS_HRTF_extrapolation. - -For example the following code will load our HRTF data set for a distance of 3m, then -a single impulse response for an angle of 30° is chosen from the set. If the -desired angle of 30° is not available, a linear interpolation between the next -two available angles will be applied. Afterwards a noise signal is created and convolved -with the impulse response by the auralize_ir() function. - -```Matlab -conf = SFS_config_example; -irs = read_irs('QU_KEMAR_anechoic_3m.mat',conf); -ir = get_ir(irs,[rad(30) 0 3],'spherical',conf); -nsig = randn(44100,1); -sig = auralize_ir(ir,nsig,1,conf); -sound(sig,conf.fs); -``` - -To simulate the same source as a virtual point source synthesized by WFS and a -circular array with a diameter of 3 m, you have to do the following. - -```Matlab -conf = SFS_config_example; -conf.secondary_sources.size = 3; -conf.secondary_sources.number = 56; -conf.secondary_sources.geometry = 'circle'; -conf.dimension = '2.5D'; -irs = read_irs('QU_KEMAR_anechoic_3m.mat',conf); -% ir = ir_wfs(X,phi,xs,src,irs,conf); -ir = ir_wfs([0 0 0],pi/2,[0 3 0],'ps',irs,conf); -nsig = randn(44100,1); -sig = auralize_ir(ir,nsig,1,conf); -``` - -Binaural simulations are also a nice way to investigate the frequency response -of your reproduction system. The following code will investigate the influence -of the pre-equalization filter in WFS on the frequency response. -For the red line the pre-filter is used and its upper frequency is set to the -expected aliasing frequency of the system (above these frequency the spectrum -becomes very noise as you can see in the figure). - -```Matlab -conf = SFS_config_example; -conf.ir.usehcomp = 0; -conf.wfs.usehpre = 0; -irs = dummy_irs; -[ir1,x0] = ir_wfs([0 0 0],pi/2,[0 2.5 0],'ps',irs,conf); -conf.wfs.usehpre = 1; -conf.wfs.hprefhigh = aliasing_frequency(x0,conf); -ir2 = ir_wfs([0 0 0],pi/2,[0 2.5 0],'ps',irs,conf); -[a1,p,f] = easyfft(norm_signal(ir1(:,1)),conf); -a2 = easyfft(norm_signal(ir2(:,1)),conf); -figure; -figsize(540,404,'px'); -semilogx(f,20*log10(a1),'-b',f,20*log10(a2),'-r'); -axis([10 20000 -80 -40]); -set(gca,'XTick',[10 100 250 1000 5000 20000]); -legend('w/o pre-filter','w pre-filter'); -xlabel('frequency / Hz'); -ylabel('magnitude / dB'); -%print_png('img/impulse_response_wfs_25d.png'); -``` - -![Image](doc/img/impulse_response_wfs_25d.png) - -The same can be done in the frequency domain, but in this case we are not able -to set a maximum frequency of the pre-equalization filter and the whole -frequency range will be affected. - -```Matlab -freq_response_wfs([0 0 0],[0 2.5 0],'ps',conf); -axis([10 20000 -20 20]); -%print_png('img/impulse_response_wfs_25d_mono.png'); -``` - -![Image](doc/img/impulse_response_wfs_25d_mono.png) - - -#### Using the SoundScape Renderer with the SFS Toolbox - -In addition to binaural synthesis, you may want to apply dynamic binaural -synthesis, which means you track the position of the head of the listener and -switches the used impulse responses regarding the head position. The [SoundScape -Renderer (SSR)](http://spatialaudio.net/ssr/) is able to do this. The SFS Toolbox -provides functions to generate the needed wav files containing the impulse -responses used by the SoundScape Renderer. -All functions regarding the SSR are stored in SFS_ssr. - -```Matlab -conf = SFS_config_example; -brs = ssr_brs_wfs(X,phi,xs,src,irs,conf); -wavwrite(brs,fs,16,'brs_set_for_SSR.wav'); -``` - - -### Small helper functions - -The Toolbox provides you also with a set of useful small functions. -Here the highlights are angle conversion with rad() and -deg(), FFT calculation and plotting easyfft(), -create noise signal noise(), rotation matrix -rotation_matrix(), multi-channel convolution -convolution(), nearest neighbour search -findnearestneighbour(), even or odd checking iseven() -isodd(), spherical bessel functions sphbesselh() -sphbesselj() sphbessely(). - - -### Plotting with Matlab or gnuplot - -The Toolbox provides you with a variety of functions for plotting your simulated -sound fields plot_sound_field() and adding loudspeaker symbols to the -figure draw_loudspeakers. -If you have gnuplot installed, you can use the functions gp_save_matrix.m -and gp_save_loudspeakers.m to save your data in a way that it can -be used with gnuplot. An example use case can be found [at this plot of a plane -wave](https://github.com/hagenw/phd-thesis/tree/master/02_theory_of_sound_field_synthesis/fig2_04) -which includes the Matlab/Octave code to generate the data and the gnuplot -script for plotting it. - - -Credits and License -------------------- - -This is the source distribution of Sound Field Synthesis Toolbox (SFS) licensed -under the GPLv3+. Please consult the file COPYING for more information about -this license. - -Website: http://github.com/sfstoolbox/sfs - -If you have questions, bug reports or feature requests, please use the [Issue -Section on the website](https://github.com/sfstoolbox/sfs/issues) to report them. - -If you use the Toolbox for your publications please cite our AES Convention e-Brief: -H. Wierstorf, S. Spors - Sound Field Synthesis Toolbox. -In the Proceedings of *132nd Convention of the -Audio Engineering Society*, 2012 -[ [pdf](http://audio.qu.tu-berlin.de/wp-content/uploads/publications/2012/wierstorf2012_SFS_toolbox_AES.pdf) ] -[ [bibtex](doc/aes132_paper.bib) ] - -Copyright (c) 2010-2015 -Quality & Usability Lab, together with -Assessment of IP-based Applications -Telekom Innovation Laboratories, TU Berlin -Ernst-Reuter-Platz 7, 10587 Berlin, Germany - -Copyright (c) 2013-2015 -Institut fuer Nachrichtentechnik -Universitaet Rostock -Richard-Wagner-Strasse 31, 18119 Rostock diff --git a/README.rst b/README.rst new file mode 100644 index 00000000..5fc65ce2 --- /dev/null +++ b/README.rst @@ -0,0 +1,143 @@ +Sound Field Synthesis Toolbox for Matlab +======================================== + +The SFS Toolbox for Matlab gives you the possibility to play around with sound +field synthesis methods like wave field synthesis (WFS) or near-field +compensated higher order Ambisonics (NFC-HOA). There are functions to simulate +monochromatic sound fields for different secondary source (loudspeaker) setups, +time snapshots of full band impulses emitted by the secondary source +distributions, or even generate binaural room scanning (BRS) impulse response +sets in order to generate binaural simulations of the synthesized sound fields +with the `SoundScape Renderer`_. + +.. _SoundScape Renderer: http://spatialaudio.net/ssr + +Theory: + https://sfs.readthedocs.io/ + +Documentation: + https://sfs-matlab.readthedocs.io/ + +Source code and issue tracker: + https://github.com/sfstoolbox/sfs-matlab/ + +SFS Toolbox for Python: + https://sfs-python.readthedocs.io/ + +License: + MIT -- see the file ``LICENSE`` for details. + + +Installation +------------ + +`Download the Toolbox`_, go to the main path of the Toolbox and start it with +``SFS_start`` which will add all needed paths to Matlab/Octave. If +you want to remove them again, run ``SFS_stop``. + +.. _Download the Toolbox: + https://github.com/sfstoolbox/sfs-matlab/releases/latest + + +Requirements +------------ + +Matlab: + You need Matlab version R2011b or newer to run the Toolbox. On older + versions the Toolbox should also work, but you need to add `narginchk.m`_ to + the ``SFS_helper`` directory. + +.. _narginchk.m: https://gist.github.com/hagenw/5642886 + +Octave: + You need Octave version 3.6 or newer to run the Toolbox. In addition, + you will need the ``audio`` and ``signal`` packages from + `octave-forge`_. + +.. _octave-forge: https://octave.sourceforge.io/ + +audioread: + If ``audioread()`` is not available in your Matlab or Octave version, + you can replace it by ``wavread()``. It is used in the two functions + ``auralize_ir()`` and ``compensate_headphone()``. + +Impulse responses: + The Toolbox uses the `SOFA`_ file format for handling impulse response data + sets like HRTFs. If you want to use this functionality you also have to + install the `SOFA API for Matlab/Octave`_, which you can add to your paths + by executing ``SOFAstart``. + +Backward compatibility: + Since version 2.0.0 the SFS Toolbox incorporates `SOFA`_ as file format for + HRTFs which replaces the old `irs file format`_ formerly used by the + Toolbox. If you still need this you should download `the latest version with + irs file support`_. + +.. _SOFA: https://sofaconventions.org/ +.. _SOFA API for Matlab/Octave: https://github.com/sofacoustics/API_MO +.. _irs file format: + https://dev.qu.tu-berlin.de/projects/measurements/wiki/IRs_file_format +.. _the latest version with irs file support: + https://github.com/sfstoolbox/sfs-matlab/releases/tag/1.2.0 + + +Getting started +--------------- + +In order to make a simulation of the sound field of a monochromatic point source +with a frequency of 800 Hz placed at (0,2.5,0) m synthesized by WFS run + +.. sourcecode:: matlab + + conf = SFS_config; + conf.plot.normalisation = 'center'; + sound_field_mono_wfs([-2 2],[-2 2],0,[0 2.5 0],'ps',800,conf) + +To make a simulation of the same point source - now producing a broadband +impulse - in the time domain at a time of 5 ms after the first loudspeaker +activity run + +.. sourcecode:: matlab + + conf = SFS_config; + conf.plot.normalisation = 'max'; + sound_field_imp_wfs([-2 2],[-2 2],0,[0 2.5 0],'ps',0.005,conf) + +After that have a look at ``SFS_config.m`` for the default settings of +the Toolbox. Please don't change the settings directly in +``SFS_config.m``, but create an extra function or script for this, that +can look like this: + +.. sourcecode:: matlab + + conf = SFS_config; + conf.fs = 48000; + +For a detailed description of all available features the SFS Toolbox, have a +look at the `online documentation`_. + +.. _online documentation: https://sfs-matlab.readthedocs.io/ + + +Credits and feedback +-------------------- + +If you have questions, bug reports or feature requests, please use the `Issue +Section`_ to report them. + +If you use the SFS Toolbox for your publications please cite our AES Convention +e-Brief and the DOI for the used Toolbox version, you will find at the `official +releases page`_: + +H. Wierstorf, S. Spors - Sound Field Synthesis Toolbox. +In the Proceedings of *132nd Convention of the +Audio Engineering Society*, 2012 +[ `pdf`_ ] +[ `bibtex`_ ] + +Copyright (c) 2010-2019 SFS Toolbox Developers + +.. _Issue Section: https://github.com/sfstoolbox/sfs-matlab/issues +.. _official releases page: https://github.com/sfstoolbox/sfs-matlab/releases +.. _pdf: http://files.sfstoolbox.org/wierstorf_et_al_sfs-toolbox_aes132.pdf +.. _bibtex: http://files.sfstoolbox.org/wierstorf_et_al_sfs-toolbox_aes132.bib diff --git a/SFS_HRTF_extrapolation/extrapolate_farfield_hrtfset.m b/SFS_HRTF_extrapolation/extrapolate_farfield_hrtfset.m index d5d37d94..7491a03d 100644 --- a/SFS_HRTF_extrapolation/extrapolate_farfield_hrtfset.m +++ b/SFS_HRTF_extrapolation/extrapolate_farfield_hrtfset.m @@ -1,96 +1,84 @@ -function irs_pw = extrapolate_farfield_hrtfset(irs,conf) +function sofa_pw = extrapolate_farfield_hrtfset(sofa,conf) %EXTRAPOLATE_FARFIELD_HRTFSET far-field extrapolation of a given HRTF dataset % -% Usage: irs = extrapolate_farfield_hrtfset(irs,[conf]) +% Usage: sofa = extrapolate_farfield_hrtfset(sofa,conf) % % Input parameters: -% irs - IR data set for the virtual secondary sources -% conf - optional configuration struct (see SFS_config) +% sofa - IR data set for the virtual secondary sources +% conf - configuration struct (see SFS_config) % % Output parameters: -% irs - IR data set extra polated to conation plane wave IRs +% sofa - IR data set extra polated to conation plane wave IRs % -% EXTRAPOLATE_FARFIELD_HRTFSET(IRS) generates a far-field extrapolated set of -% impulse responses, using the given irs set. Far-field means that the +% EXTRAPOLATE_FARFIELD_HRTFSET(SOFA,conf) generates a far-field extrapolated +% set of impulse responses, using the given irs set. Far-field means that the % resulting impulse responses are plane waves. The extrapolation is done via % WFS. % -% References: -% S. Spors and J. Ahrens (2011) - "Generation of far-field head-related -% transfer functions using sound field synthesis", In German Annual -% Conference on Acoustics (DAGA). -% % See also: get_ir, driving_function_imp_wfs +% +% References: +% Spors and Ahrens (2011) - "Generation of far-field head-related +% transfer functions using sound field synthesis", 37th German Annual +% Conference on Acoustics (DAGA), pp. 673-674, +% http://pub.dega-akustik.de/DAGA_2011/data/articles/000370.pdf %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 1; +nargmin = 2; nargmax = 2; narginchk(nargmin,nargmax); -check_irs(irs); -if nargineps('single')) && any(theta-theta(1)>eps('single')) % 3D case conf.usetapwin = false; if ~strcmp('3D',dimension) @@ -118,10 +105,11 @@ end if strcmp('2.5D',dimension) % Apply a amplitude correction, due to 2.5D. This will result in a correct - % reproduced ILD in the resulting impulse responses (see, Spors 2011) - amplitude_correction = -1.7 * sin(irs.apparent_azimuth); + % reproduced ILD in the resulting impulse responses, see Spors and + % Ahrens (2011). + amplitude_correction = -1.7 * sin(phi); else - amplitude_correction = zeros(size(irs.apparent_azimuth)); + amplitude_correction = zeros(nls,1); end @@ -132,20 +120,28 @@ conf.wfs.hprefhigh = aliasing_frequency(x0_all,conf); % Initialize new irs set -irs_pw = irs; -irs_pw.description = 'Extrapolated HRTF set containing plane waves'; -irs_pw.left = zeros(N,nls); -irs_pw.right = zeros(N,nls); -irs_pw.distance = Inf; - +sofa_pw = sofa; +sofa_pw.GLOBAL_Comment = 'Extrapolated HRTF set containing plane waves'; +sofa_pw.Data.IR = zeros(nls,2,N); +sofa_pw.SourcePosition = [Inf 0 0]; % Get all HRTFs for the secondary source positions -ir_all = zeros(size(irs.left,1),2,nls); +ir_all = zeros(nls,2,N); +X = SOFAconvertCoordinates(sofa.ListenerPosition, ... + sofa.ListenerPosition_Type, ... + 'cartesian'); +head_orientation = SOFAconvertCoordinates(sofa.ListenerView, ... + sofa.ListenerView_Type, ... + 'spherical'); +head_orientation = rad(head_orientation(1,1:2)); +warning('off','SFS:get_ir'); % Disable warning for short N for ii=1:nls - ir_all(:,:,ii) = get_ir(irs,x0_all(ii,1:3),'cartesian',conf); + ir_all(ii,:,:) = get_ir(sofa,X,head_orientation, ... + x0_all(ii,1:3),'cartesian',conf)'; end +warning('on','SFS:get_ir'); -% Generate a irs set for all given angles +% Generate a impulse response set for all given angles for ii=1:nls % Show progress @@ -157,7 +153,7 @@ % Calculate active virtual speakers [x0,idx] = secondary_source_selection(x0_all,xs,'pw'); - ir = ir_all(:,:,idx); + ir = ir_all(idx,:,:); % Apply tapering window x0 = secondary_source_tapering(x0,conf); @@ -167,16 +163,17 @@ conf.wfs.usehpre = false; [~,delay,weight] = driving_function_imp_wfs(x0,xs,'pw',conf); conf.wfs.usehpre = tmp_usehpre; - % Delay in samples - delay = delay.*fs; % Sum up contributions from individual virtual speakers - irs_pw.left(:,ii) = sum(delayline(squeeze(ir(:,1,:)),delay,weight,conf),2); - irs_pw.right(:,ii) = sum(delayline(squeeze(ir(:,2,:)),delay,weight,conf),2); - irs_pw.left(:,ii) = irs_pw.left(:,ii)/10^(amplitude_correction(ii)/20); - irs_pw.right(:,ii) = irs_pw.right(:,ii)/10^(-amplitude_correction(ii)/20); + for jj=1:size(x0,1) + % Delay and weight HRTFs + sofa_pw.Data.IR(ii,:,:) = squeeze(sofa_pw.Data.IR(ii,:,:)) + ... + delayline(squeeze(ir(jj,:,:))',delay(jj),weight(jj),conf)'; + end + sofa_pw.Data.IR(ii,1,:) = sofa_pw.Data.IR(ii,1,:)/10^(amplitude_correction(ii)/20); + sofa_pw.Data.IR(ii,2,:) = sofa_pw.Data.IR(ii,2,:)/10^(-amplitude_correction(ii)/20); end %% ===== Pre-equalization =============================================== -irs_pw.left = wfs_preequalization(irs_pw.left,conf); -irs_pw.right = wfs_preequalization(irs_pw.right,conf); +sofa_pw.Data.IR(:,1,:) = wfs_preequalization(squeeze(sofa_pw.Data.IR(:,1,:))',conf)'; +sofa_pw.Data.IR(:,2,:) = wfs_preequalization(squeeze(sofa_pw.Data.IR(:,2,:))',conf)'; diff --git a/SFS_analysis/freq_response_line_source.m b/SFS_analysis/freq_response_line_source.m new file mode 100644 index 00000000..46f576db --- /dev/null +++ b/SFS_analysis/freq_response_line_source.m @@ -0,0 +1,97 @@ +function varargout = freq_response_line_source(X,xs,conf) +%FREQ_RESPONSE_LINE_SOURCE frequency response of a line source +% +% Usage: [S,f] = freq_response_line_source(X,xs,conf) +% +% Input parameters: +% X - listener position / m +% xs - position of line source / m +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% S - simulated frequency response +% f - corresponding frequency axis / Hz +% +% FREQ_RESPONSE_LINE_SOURCE(X,xs,conf) simulates the frequency response of a +% line source placed at xs at the given virtual microphone position X. +% The length in samples of the frequency response is given by conf.N. +% +% See also: sound_field_mono_line_source, time_response_line_source + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 3; +nargmax = 3; +narginchk(nargmin,nargmax); +isargposition(X); +isargxs(xs); +isargstruct(conf); + + +%% ===== Configuration ================================================== +N = conf.N; +showprogress = conf.showprogress; +useplot = conf.plot.useplot; + + +%% ===== Computation ==================================================== +% Disable progress bar and plotting for sound_field_imp() +conf.showprogress = false; +conf.plot.useplot = false; +% Get the position of the loudspeaker from line source position. +% NOTE: its directivity [0 -1 0] will be ignored +x0 = [xs 0 -1 0 1]; +% Generate frequencies (10^1-10^4.3) +f = logspace(0,4.3,N)'; +S = zeros(size(f)); +% Get the result for all frequencies +for ii = 1:length(f) + if showprogress, progress_bar(ii,length(f)); end + % Calculate sound field at the listener position + P = sound_field_mono(X(1),X(2),X(3),x0,'ls',1,f(ii),conf); + S(ii) = abs(P); +end + +% Return parameter +if nargout>0, varargout{1}=S; end +if nargout>1, varargout{2}=f; end + + +%% ===== Plotting ======================================================== +if nargout==0 || useplot + figure; + figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); + semilogx(f,db(S)); + set(gca,'XTick',[10 100 250 1000 5000 20000]); + ylabel('amplitude / dB)'); + xlabel('frequency / Hz'); +end diff --git a/SFS_analysis/freq_response_localwfs.m b/SFS_analysis/freq_response_localwfs.m deleted file mode 100644 index 0efe4ac1..00000000 --- a/SFS_analysis/freq_response_localwfs.m +++ /dev/null @@ -1,117 +0,0 @@ -function varargout = freq_response_localwfs(X,xs,src,conf) -%FREQ_RESPONSE_WFS simulates the frequency response for WFS at the given -%listener position -% -% Usage: [S,f] = freq_response_wfs(X,xs,src,[conf]) -% -% Input parameters: -% X - listener position / m -% xs - position of virtual source / m -% src - source type of the virtual source -% 'pw' -plane wave -% 'ps' - point source -% 'fs' - focused source -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% S - simulated frequency response -% f - corresponding frequency axis / Hz -% -% FREQ_RESPONSE_WFS(X,xs,src,conf) simulates the frequency response of the -% sound field at the given position X. The sound field is simulated for the -% given source type (src) using a monochromatic WFS driving function. -% -% See also: sound_field_mono_wfs, sound_field_imp_wfs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargposition(X); -isargxs(xs); -isargchar(src); -if nargin20000,1); -f = f(1:idx); -S = zeros(size(f)); -% Get the result for all frequencies -for ii = 1:length(f) - if showprogress, progress_bar(ii,length(f)); end - [D, x0] = driving_function_mono_localwfs(x0_real,xs,src,f(ii),conf); - % Calculate sound field at the listener position - P = sound_field_mono(X(1),X(2),X(3),x0,greens_function,D,f(ii),conf); - S(ii) = abs(P); -end - -% Return parameter -if nargout>0, varargout{1}=S; end -if nargout>1, varargout{2}=f; end - - -%% ===== Plotting ======================================================== -if nargout==0 || useplot - figure; - figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); - semilogx(f,db(S)); - set(gca,'XTick',[10 100 250 1000 5000 20000]); - ylabel('Amplitude (dB)'); - xlabel('Frequency (Hz)'); -end diff --git a/SFS_analysis/freq_response_localwfs_sbl.m b/SFS_analysis/freq_response_localwfs_sbl.m new file mode 100644 index 00000000..01a423f4 --- /dev/null +++ b/SFS_analysis/freq_response_localwfs_sbl.m @@ -0,0 +1,116 @@ +function varargout = freq_response_localwfs_sbl(X,xs,src,conf) +%FREQ_RESPONSE_LOCALWFS_SBL frequency response for local WFS +% +% Usage: [S,f] = freq_response_loaclwfs_sbl(X,xs,src,conf) +% +% Input parameters: +% X - listener position / m +% xs - position of virtual source / m +% src - source type of the virtual source +% 'pw' -plane wave +% 'ps' - point source +% 'fs' - focused source +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% S - simulated frequency response +% f - corresponding frequency axis / Hz +% +% FREQ_RESPONSE_LOCALWFS_SBL(X,xs,src,conf) simulates the frequency response +% of a source synthesized by local WFS using spatial bandwith limitation +% (SBL) at the given virtual microphone position X. +% The length in samples of the frequency response is given by conf.N. The +% actual calculation is done via sound_field_mono() and a loop over frequency +% f. +% +% See also: sound_field_mono_localwfs, time_response_localwfs + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 4; +nargmax = 4; +narginchk(nargmin,nargmax); +isargposition(X); +isargxs(xs); +isargchar(src); +isargstruct(conf); + + +%% ===== Configuration ================================================== +N = conf.N; +showprogress = conf.showprogress; +useplot = conf.plot.useplot; +% Check type of secondary sources to use +if strcmp('2D',conf.dimension) + greens_function = 'ls'; +else + greens_function = 'ps'; +end + + +%% ===== Computation ==================================================== +% Disable progress bar and plotting for sound_field_imp() +conf.showprogress = false; +conf.plot.useplot = false; +% Get the position of the loudspeakers +x0 = secondary_source_positions(conf); +% Generate frequencies (10^1-10^4.3) +f = logspace(0,4.3,N)'; +S = zeros(size(f)); +% set default value for conf.localwfs_sbl.Npw +if isempty(conf.localwfs_sbl.Npw) + conf.localwfs_sbl.Npw = ... + 2*ceil(2*pi*max(f)/conf.c*conf.secondary_sources.size/2); +end +% Get the result for all frequencies +for ii = 1:length(f) + if showprogress, progress_bar(ii,length(f)); end + D = driving_function_mono_localwfs_sbl(x0,xs,src,f(ii),conf); + % Calculate sound field at the listener position + P = sound_field_mono(X(1),X(2),X(3),x0,greens_function,D,f(ii),conf); + S(ii) = abs(P); +end + +% Return parameter +if nargout>0, varargout{1}=S; end +if nargout>1, varargout{2}=f; end + + +%% ===== Plotting ======================================================== +if nargout==0 || useplot + figure; + figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); + semilogx(f,db(S)); + set(gca,'XTick',[10 100 250 1000 5000 20000]); + ylabel('amplitude / dB'); + xlabel('frequency / Hz'); +end diff --git a/SFS_analysis/freq_response_localwfs_vss.m b/SFS_analysis/freq_response_localwfs_vss.m new file mode 100644 index 00000000..6594ddf9 --- /dev/null +++ b/SFS_analysis/freq_response_localwfs_vss.m @@ -0,0 +1,111 @@ +function varargout = freq_response_localwfs_vss(X,xs,src,conf) +%FREQ_RESPONSE_LOCALWFS_VSS frequency response for local WFS +% +% Usage: [S,f] = freq_response_localwfs_vss(X,xs,src,conf) +% +% Input parameters: +% X - listener position / m +% xs - position of virtual source / m +% src - source type of the virtual source +% 'pw' -plane wave +% 'ps' - point source +% 'fs' - focused source +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% S - simulated frequency response +% f - corresponding frequency axis / Hz +% +% FREQ_RESPONSE_LOCALWFS_VSS(X,xs,src,conf) simulates the frequency response +% of a source synthesized by local WFS using virtual secondary sources (VSS) +% at the given virtual microphone position X. +% The length in samples of the frequency response is given by conf.N. The +% actual calculation is done via sound_field_mono() and a loop over frequency +% f. +% +% See also: sound_field_mono_localwfs_vss, time_response_localwfs_vss + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 4; +nargmax = 4; +narginchk(nargmin,nargmax); +isargposition(X); +isargxs(xs); +isargchar(src); +isargstruct(conf); + + +%% ===== Configuration ================================================== +N = conf.N; +showprogress = conf.showprogress; +useplot = conf.plot.useplot; +% Check type of secondary sources to use +if strcmp('2D',conf.dimension) + greens_function = 'ls'; +else + greens_function = 'ps'; +end + + +%% ===== Computation ==================================================== +% Disable progress bar and plotting for sound_field_imp() +conf.showprogress = false; +conf.plot.useplot = false; +% Get the position of the loudspeakers +x0_real = secondary_source_positions(conf); +% Generate frequencies (10^1-10^4.3) +f = logspace(0,4.3,N)'; +S = zeros(size(f)); +% Get the result for all frequencies +for ii = 1:length(f) + if showprogress, progress_bar(ii,length(f)); end + [D, x0] = driving_function_mono_localwfs_vss(x0_real,xs,src,f(ii),conf); + % Calculate sound field at the listener position + P = sound_field_mono(X(1),X(2),X(3),x0,greens_function,D,f(ii),conf); + S(ii) = abs(P); +end + +% Return parameter +if nargout>0, varargout{1}=S; end +if nargout>1, varargout{2}=f; end + + +%% ===== Plotting ======================================================== +if nargout==0 || useplot + figure; + figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); + semilogx(f,db(S)); + set(gca,'XTick',[10 100 250 1000 5000 20000]); + ylabel('amplitude / dB'); + xlabel('frequency / Hz'); +end diff --git a/SFS_analysis/freq_response_nfchoa.m b/SFS_analysis/freq_response_nfchoa.m index d427c336..d1588b9d 100644 --- a/SFS_analysis/freq_response_nfchoa.m +++ b/SFS_analysis/freq_response_nfchoa.m @@ -1,118 +1,111 @@ -function varargout = freq_response_nfchoa(X,xs,src,conf) -%FREQ_RESPONSE_NFCHOA simulates the frequency response for NFC-HOA at the given -%listener position -% -% Usage: [S,f] = freq_response_nfchoa(X,xs,src,[conf]) -% -% Input parameters: -% X - listener position / m -% xs - position of virtual source / m -% src - source type of the virtual source -% 'pw' -plane wave -% 'ps' - point source -% 'fs' - focused source -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% S - simulated frequency response -% f - corresponding frequency axis / Hz -% -% FREQ_RESPONSE_NFCHOA(X,xs,src,conf) simulates the frequency response of the -% sound field at the given position X. The sound field is simulated for the -% given source type (src) using a monochromatic NFC-HOA driving function. -% -% See also: sound_field_mono_nfchoa, sound_field_imp_nfchoa - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargposition(X); -isargxs(xs); -isargchar(src); -if nargin20000,1); -f = f(1:idx); -S = zeros(size(f)); -% Get the result for all frequencies -for ii = 1:length(f) - if showprogress, progress_bar(ii,length(f)); end - D = driving_function_mono_nfchoa(x0,xs,src,f(ii),conf); - % Calculate sound field at the listener position - P = sound_field_mono(X(1),X(2),X(3),x0,greens_function,D,f(ii),conf); - S(ii) = abs(P); -end - -% Return parameter -if nargout>0, varargout{1}=S; end -if nargout>1, varargout{2}=f; end - - -%% ===== Plotting ======================================================== -if nargout==0 || useplot - figure; - figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); - semilogx(f,db(S)); - set(gca,'XTick',[10 100 250 1000 5000 20000]); - ylabel('Amplitude (dB)'); - xlabel('Frequency (Hz)'); -end +function varargout = freq_response_nfchoa(X,xs,src,conf) +%FREQ_RESPONSE_NFCHOA frequency response for NFC-HOA +% +% Usage: [S,f] = freq_response_nfchoa(X,xs,src,conf) +% +% Input parameters: +% X - listener position / m +% xs - position of virtual source / m +% src - source type of the virtual source +% 'pw' -plane wave +% 'ps' - point source +% 'fs' - focused source +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% S - simulated frequency response +% f - corresponding frequency axis / Hz +% +% FREQ_RESPONSE_NFCHOA(X,xs,src,conf) simulates the frequency response of a +% the source type src placed at xs and synthesized by NFC-HOA at the given +% virtual microphone position X. +% The length in samples of the frequency response is given by conf.N. The +% actual calculation is done via sound_field_mono() and a loop over frequency +% f. +% +% See also: sound_field_mono_nfchoa, time_response_nfchoa + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 4; +nargmax = 4; +narginchk(nargmin,nargmax); +isargposition(X); +isargxs(xs); +isargchar(src); +isargstruct(conf); + + +%% ===== Configuration ================================================== +N = conf.N; +showprogress = conf.showprogress; +useplot = conf.plot.useplot; +% Check type of secondary sources to use +if strcmp('2D',conf.dimension) + greens_function = 'ls'; +else + greens_function = 'ps'; +end + + +%% ===== Computation ==================================================== +% Disable progress bar and plotting for sound_field_imp() +conf.showprogress = false; +conf.plot.useplot = false; +% Get the position of the loudspeakers +x0 = secondary_source_positions(conf); +% Generate frequencies (10^1-10^4.3) +f = logspace(0,4.3,N)'; +S = zeros(size(f)); +% Get the result for all frequencies +for ii = 1:length(f) + if showprogress, progress_bar(ii,length(f)); end + D = driving_function_mono_nfchoa(x0,xs,src,f(ii),conf); + % Calculate sound field at the listener position + P = sound_field_mono(X(1),X(2),X(3),x0,greens_function,D,f(ii),conf); + S(ii) = abs(P); +end + +% Return parameter +if nargout>0, varargout{1}=S; end +if nargout>1, varargout{2}=f; end + + +%% ===== Plotting ======================================================== +if nargout==0 || useplot + figure; + figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); + semilogx(f,db(S)); + set(gca,'XTick',[10 100 250 1000 5000 20000]); + ylabel('amplitude / dB'); + xlabel('frequency / Hz'); +end diff --git a/SFS_analysis/freq_response_point_source.m b/SFS_analysis/freq_response_point_source.m new file mode 100644 index 00000000..6a76b249 --- /dev/null +++ b/SFS_analysis/freq_response_point_source.m @@ -0,0 +1,97 @@ +function varargout = freq_response_point_source(X,xs,conf) +%FREQ_RESPONSE_POINT_SOURCE frequency response of a point +% +% Usage: [S,f] = freq_response_point_source(X,xs,conf) +% +% Input parameters: +% X - listener position / m +% xs - position of point source / m +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% S - simulated frequency response +% f - corresponding frequency axis / Hz +% +% FREQ_RESPONSE_POINT_SOURCE(X,xs,conf) simulates the frequency response of a +% point source placed at xs at the given virtual microphone position X. +% The length in samples of the frequency response is given by conf.N. +% +% See also: sound_field_mono_point_source, time_response_point_source + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 3; +nargmax = 3; +narginchk(nargmin,nargmax); +isargposition(X); +isargxs(xs); +isargstruct(conf); + + +%% ===== Configuration ================================================== +N = conf.N; +showprogress = conf.showprogress; +useplot = conf.plot.useplot; + + +%% ===== Computation ==================================================== +% Disable progress bar and plotting for sound_field_imp() +conf.showprogress = false; +conf.plot.useplot = false; +% Get the position of the loudspeaker from point source position. +% NOTE: its directivity [0 -1 0] will be ignored +x0 = [xs 0 -1 0 1]; +% Generate frequencies (10^1-10^4.3) +f = logspace(0,4.3,N)'; +S = zeros(size(f)); +% Get the result for all frequencies +for ii = 1:length(f) + if showprogress, progress_bar(ii,length(f)); end + % Calculate sound field at the listener position + P = sound_field_mono(X(1),X(2),X(3),x0,'ps',1,f(ii),conf); + S(ii) = abs(P); +end + +% Return parameter +if nargout>0, varargout{1}=S; end +if nargout>1, varargout{2}=f; end + + +%% ===== Plotting ======================================================== +if nargout==0 || useplot + figure; + figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); + semilogx(f,db(S)); + set(gca,'XTick',[10 100 250 1000 5000 20000]); + ylabel('amplitude / dB)'); + xlabel('frequency / Hz'); +end diff --git a/SFS_analysis/freq_response_wfs.m b/SFS_analysis/freq_response_wfs.m index 0c92282b..bd9555d3 100644 --- a/SFS_analysis/freq_response_wfs.m +++ b/SFS_analysis/freq_response_wfs.m @@ -1,119 +1,113 @@ -function varargout = freq_response_wfs(X,xs,src,conf) -%FREQ_RESPONSE_WFS simulates the frequency response for WFS at the given -%listener position -% -% Usage: [S,f] = freq_response_wfs(X,xs,src,[conf]) -% -% Input parameters: -% X - listener position / m -% xs - position of virtual source / m -% src - source type of the virtual source -% 'pw' -plane wave -% 'ps' - point source -% 'fs' - focused source -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% S - simulated frequency response -% f - corresponding frequency axis / Hz -% -% FREQ_RESPONSE_WFS(X,xs,src,conf) simulates the frequency response of the -% sound field at the given position X. The sound field is simulated for the -% given source type (src) using a monochromatic WFS driving function. -% -% See also: sound_field_mono_wfs, sound_field_imp_wfs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargposition(X); -isargxs(xs); -isargchar(src); -if nargin20000,1); -f = f(1:idx); -S = zeros(size(f)); -% Get the result for all frequencies -for ii = 1:length(f) - if showprogress, progress_bar(ii,length(f)); end - D = driving_function_mono_wfs(x0,xs,src,f(ii),conf); - % calculate sound field at the listener position - P = sound_field_mono(X(1),X(2),X(3),x0,greens_function,D,f(ii),conf); - S(ii) = abs(P); -end - -% Return parameter -if nargout>0, varargout{1}=S; end -if nargout>1, varargout{2}=f; end - - -%% ===== Plotting ======================================================== -if nargout==0 || useplot - figure; - figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); - semilogx(f,db(S)); - set(gca,'XTick',[10 100 250 1000 5000 20000]); - ylabel('Amplitude (dB)'); - xlabel('Frequency (Hz)'); -end +function varargout = freq_response_wfs(X,xs,src,conf) +%FREQ_RESPONSE_WFS frequency response for WFS +% +% Usage: [S,f] = freq_response_wfs(X,xs,src,conf) +% +% Input parameters: +% X - listener position / m +% xs - position of virtual source / m +% src - source type of the virtual source +% 'pw' -plane wave +% 'ps' - point source +% 'fs' - focused source +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% S - simulated frequency response +% f - corresponding frequency axis / Hz +% +% FREQ_RESPONSE_WFS(X,xs,src,conf) simulates the frequency response of a the +% source type src placed at xs and synthesized by WFS at the given virtual +% microphone position X. +% The length in samples of the frequency response is given by conf.N. The +% actual calculation is done via sound_field_mono() and a loop over frequency +% f. +% +% See also: sound_field_mono_wfs, time_response_wfs + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 4; +nargmax = 4; +narginchk(nargmin,nargmax); +isargposition(X); +isargxs(xs); +isargchar(src); +isargstruct(conf); + + +%% ===== Configuration ================================================== +N = conf.N; +showprogress = conf.showprogress; +useplot = conf.plot.useplot; +% Check type of secondary sources to use +if strcmp('2D',conf.dimension) + greens_function = 'ls'; +else + greens_function = 'ps'; +end + + +%% ===== Computation ==================================================== +% Disable progress bar and plotting for sound_field_imp() +conf.showprogress = false; +conf.plot.useplot = false; +% Get the position of the loudspeakers +x0 = secondary_source_positions(conf); +x0 = secondary_source_selection(x0,xs,src); +x0 = secondary_source_tapering(x0,conf); +% Generate frequencies (10^1-10^4.3) +f = logspace(0,4.3,N)'; +S = zeros(size(f)); +% Get the result for all frequencies +for ii = 1:length(f) + if showprogress, progress_bar(ii,length(f)); end + D = driving_function_mono_wfs(x0,xs,src,f(ii),conf); + % Calculate sound field at the listener position + P = sound_field_mono(X(1),X(2),X(3),x0,greens_function,D,f(ii),conf); + S(ii) = abs(P); +end + +% Return parameter +if nargout>0, varargout{1}=S; end +if nargout>1, varargout{2}=f; end + + +%% ===== Plotting ======================================================== +if nargout==0 || useplot + figure; + figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); + semilogx(f,db(S)); + set(gca,'XTick',[10 100 250 1000 5000 20000]); + ylabel('amplitude / dB)'); + xlabel('frequency / Hz'); +end diff --git a/SFS_analysis/interaural_level_difference.m b/SFS_analysis/interaural_level_difference.m deleted file mode 100644 index d1dbd110..00000000 --- a/SFS_analysis/interaural_level_difference.m +++ /dev/null @@ -1,67 +0,0 @@ -function ild = interaural_level_difference(insigleft,insigright) -%INTERAURAL_LEVEL_DIFFERENCE Extract the ILD between the two given signals -% -% Usage: ild = interaural_level_difference(insigleft,insigright) -% -% Input parameters: -% insigleft - left ear signal. This can also be a matrix containing -% left signals for different frequency bands -% insigright - the same as insigleft, but for the right ear -% -% Output parameters: -% ild - ILD for the given signals. A single value for two -% given signals or a vector with values for every -% frequency band / dB -% -% INTERAURAL_LEVEL_DIFFERENCE(insigleft,insigright) extractes the ILD -% between the left and right signal(s) by subtracting the dB value of -% the left signal(s) from the dB value of the right signal(s). -% -% See also: interaural_time_difference - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ==================================== -nargmin = 2; -nargmax = 2; -narginchk(nargmin,nargmax); -isargmatrix(insigleft,insigright); -if size(insigright)~=size(insigright) - error('%s: insigleft and insigright have to be the same size!', ... - upper(mfilename)); -end - - -%% ===== Computation ===================================================== -ild = db(rms(insigright(:,:)))-db(rms(insigleft(:,:))); diff --git a/SFS_analysis/interaural_time_difference.m b/SFS_analysis/interaural_time_difference.m deleted file mode 100644 index 8463795a..00000000 --- a/SFS_analysis/interaural_time_difference.m +++ /dev/null @@ -1,204 +0,0 @@ -function [itd,idxleft,idxright] = interaural_time_difference(insigleft,insigright,fs,mode,fit) -%INTERAURAL_TIME_DIFFERENCE Extract the ITD between the two given impulse -%responses -% -% Usage: itd = interaural_time_difference(insigleft,insigright,fs,[mode]) -% -% Input parameters: -% insigleft - left impuls response. This can also be a matrix containing -% left signals for different frequency bands -% insigright - the same as insigleft, but for the right ear -% fs - sampling rate / Hz -% mode - describes which algorith was used: simple is default -% - you should use 'int' too and compare results -% - 'simple' - fast, use only for low frequencies (default) -% - 'hilbert' - use only for hight frequencies -% - 'int' - use if simple and hilbert fail -% - 'int2' - use for signals with high noise -% - 'int3' - use if int fails -% - 'max' - very primitive algorithm, doesn't work well -% fit - seconds the itd from angle i can difer from itd of angle i+1 -% (default is 0.1 ) -% -% Output parameters: -% itd - ITD for the given signals. A single value for two -% given signals or a vector with values for every -% frequency band / ms -% -% INTERAURAL_TIME_DIFFERENCE(insigleft,insigright,fs) extractes the ITD between -% the left and right impulse responses by using an edge detection algorithm to -% identify the first non-zero entry in both impulse responses and then -% calculating the time difference. -% -% References: -% J. Sandvad, D. Hammershøi (1994) - "Binaural Auralization. Comparison of -% FIR and IIR Filter Representation of HIRs", 96th AES Conv. -% A. Lindau, J. Estrella, S. Weinzierl (2010) - "Individualization of -% dynamic binaural synthesis by real time manipulation of the ITD", -% 128th AES Conv. -% -% See also: interaural_level_difference - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters =================================== -nargmin = 3; -nargmax = 5; -narginchk(nargmin,nargmax); -isargmatrix(insigleft,insigright); -isargpositivescalar(fs); -if size(insigleft)~=size(insigright) - error('%s: insigleft and insigright have to be the same size!', ... - upper(mfilename)); -end -if nargin==5 - isargchar(mode); -elseif nargin==4 - isargchar(mode); - fit=0.1; -elseif nargin==3 - mode='simple'; - fit=0.1; -end - - -%% ===== Computation ==================================================== -if strcmp ( mode,'hilbert') - % Extract the envelope of the input signals - insigleft = abs(hilbert(insigleft)); - insigright = abs(hilbert(insigright)); -end - -% See if we have more than one frequency channel in the insig -itd = zeros(1,size(insigleft,2)); -itdold =0; -jminold=0; -for ii = 1:size(insigleft,2) -if strcmp( mode,'hilbert') || strcmp( mode,'simple') - % Treshold after sandvad1994 (5% of maximum in each IR) - % NOTE: I have changed it to 10% - tresholdleft = 0.10 * max(abs(insigleft(:,ii))); - tresholdright = 0.10 * max(abs(insigright(:,ii))); - % Ten fold upsampling (after lindau2010) to have a smoother output - resampleft = resample(insigleft(:,ii),10*fs,fs); - resampright = resample(insigright(:,ii),10*fs,fs); - - idxleft(ii) = find(abs(resampleft) > tresholdleft,1,'first'); - idxright(ii) = find(abs(resampright) > tresholdright,1,'first'); - itd(ii) = (idxleft(ii)-idxright(ii))/(10*fs); - - if 0 %mod(ii,30)==0 - range = 001:8000; - plot(range,resampright(range),range,resampleft(range),idxleft(ii),tresholdleft,'+',idxright(ii),tresholdright,'*'); - grid on; - file = sprintf('results/itd_%s_%i.png',mode,ii); - print(file); - end - -elseif strcmp ( mode,'max') - % Find maximum and use the maximum to calculate the ITD - [maxleft idxleft(ii)] = max(abs(insigleft(:,ii))); - [maxright idxright(ii)] = max(abs(insigright(:,ii))); - itd(ii) = (idxleft(ii)-idxright(ii))/(10*fs); - -elseif strncmp ( mode,'int',3) - %Here we try an other approach / integration of the difference and minimize - difmin=0; - - a=sum(abs(insigleft(:,ii)))/sum(abs(insigright(:,ii))); %here we normalize the both signals - insigright(:,ii)=a*insigright(:,ii); - %the right one should be louder - %Put zeros in the end and beginning - l=(length(insigleft(:,ii))); - stretch = round(fs*0.001); - newleft = zeros(1,l+2*stretch); - newleft(stretch+1:l+stretch) = insigleft(:,ii); - [maxright idxright] = max(abs(insigright(:,ii))); - weight=(idxright*2-1:-1:idxright)-idxright; - - if strcmp(mode,'int2') - weight=log(weight+1); - end - - % Add zeros also to the end and beginning of the right signal, and let the data turn from beginning to end - - for j = 1:2*stretch - newright = zeros(1,l+2*stretch); %create an empty signal of the new lenght - if strcmp(mode,'int3') - newright(j:j-1+l) = insigright(:,ii); - else - newright(j:j-1+idxright) = insigright(1:idxright,ii); %we cut the right(shifting) signal after the maximum - end - - dif = newleft - newright; - - if strcmp(mode,'int') |strcmp(mode,'int2') - dif2 = zeros(1,l+2*stretch); - dif2(j:j-1+idxright) = dif(j:j-1+idxright); %only the errors before we cut the signal are important - %dif2(find(abs(newright)>0.05*maxright)) = dif(find(abs(newright)>0.05*maxright)); %only errors where the right signal is not zero are important - - dif=dif2; - dif(j:j-1+idxright)=weight.*dif(j:j-1+idxright); %here we say which errors are more important than others - end - - %dif = dif.*weight*100; - %dif = dif.^2; - dif=abs(dif); - sumdif = sum(dif); - - - if ((sumdif < difmin) & abs(((-stretch+j)/fs)-itdold)0, varargout{1}=s; end +if nargout>1, varargout{2}=t; end + + +%% ===== Plotting ======================================================== +if nargout==0 || useplot + figure; + figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); + plot(t*1000,s); + ylabel('amplitude'); + xlabel('time / ms'); +end diff --git a/SFS_analysis/time_response_localwfs.m b/SFS_analysis/time_response_localwfs.m deleted file mode 100644 index 8f00d938..00000000 --- a/SFS_analysis/time_response_localwfs.m +++ /dev/null @@ -1,123 +0,0 @@ -function varargout = time_response_localwfs(X,xs,src,conf) -%TIME_RESPONSE_LOCALWFS simulates the time response for LOCAL WFS at the given -%listener position -% -% Usage: [s,t] = time_response_localwfs(X,xs,src,[conf]) -% -% Input parameters: -% X - listener position / m -% xs - position of virtual source / m -% src - source type of the virtual source -% 'pw' -plane wave -% 'ps' - point source -% 'fs' - focused source -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% s - simulated time response -% t - corresponding time axis / s -% -% TIME_RESPONSE_LOCALWFS(X,xs,src,conf) simulates the time response of the -% sound field at the given position X. The sound field is simulated for the -% given source type (src) using the sound_field_imp_localwfs function. -% -% See also: sound_field_imp_localwfs, freq_response_localwfs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargposition(X); -isargxs(xs); -isargchar(src); -if nargin0, varargout{1}=s; end -if nargout>1, varargout{2}=t; end - - -%% ===== Plotting ======================================================== -if nargout==0 || useplot - figure; - figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); - plot(t/fs*1000,db(abs(s))); - ylabel('amplitude / dB'); - xlabel('time / ms'); -end diff --git a/SFS_analysis/time_response_localwfs_sbl.m b/SFS_analysis/time_response_localwfs_sbl.m new file mode 100644 index 00000000..e6d742ad --- /dev/null +++ b/SFS_analysis/time_response_localwfs_sbl.m @@ -0,0 +1,113 @@ +function varargout = time_response_localwfs_sbl(X,xs,src,conf) +%TIME_RESPONSE_LOCALWFS_SBL time response for local WFS +% +% Usage: [s,t] = time_response_localwfs_sbl(X,xs,src,conf) +% +% Input parameters: +% X - listener position / m +% xs - position of virtual source / m +% src - source type of the virtual source +% 'pw' -plane wave +% 'ps' - point source +% 'fs' - focused source +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% s - simulated time response +% t - corresponding time axis / s +% +% TIME_RESPONSE_LOCALWFS_SBL(X,xs,src,conf) simulates the impulse response of +% a source synthesized by local WFS using spatial bandwidth limitation at the +% given virtual microphone position X. +% The length in samples of the impulse response is given by conf.N. The +% actual calculation is done via sound_field_imp() and a loop over time t. A +% similar result can be achieved by using ir_localwfs() in combination with +% dummy_irs(). +% +% See also: ir_localwfs, sound_field_imp, freq_response_localwfs_vss + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 4; +nargmax = 4; +narginchk(nargmin,nargmax); +isargposition(X); +isargxs(xs); +isargchar(src); +isargstruct(conf); + + +%% ===== Configuration ================================================== +fs = conf.fs; +N = conf.N; +showprogress = conf.showprogress; +useplot = conf.plot.useplot; +% Select secondary source type +if strcmp('2D',conf.dimension) + greens_function = 'ls'; +else + greens_function = 'ps'; +end + + +%% ===== Computation ==================================================== +% Disable progress bar and plotting for sound_field_imp() +conf.showprogress = false; +conf.plot.useplot = false; +% Get the position of the loudspeakers +x0 = secondary_source_positions(conf); +x0 = secondary_source_selection(x0,xs,src); +x0 = secondary_source_tapering(x0,conf); +% Generate time axis +t = (0:N-1)'/fs; +s = zeros(1,length(t)); +d = driving_function_imp_localwfs_vss(x0,xs,src,conf); +for ii = 1:length(t) + if showprogress, progress_bar(ii,length(t)); end + % Calculate sound field at the listener position + p = sound_field_imp(X(1),X(2),X(3),x0,greens_function,d,t(ii),conf); + s(ii) = real(p); +end + +% Return parameter +if nargout>0, varargout{1}=s; end +if nargout>1, varargout{2}=t; end + + +%% ===== Plotting ======================================================== +if nargout==0 || useplot + figure; + figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); + plot(t*1000,s); + ylabel('amplitude'); + xlabel('time / ms'); +end diff --git a/SFS_analysis/time_response_localwfs_vss.m b/SFS_analysis/time_response_localwfs_vss.m new file mode 100644 index 00000000..60c55105 --- /dev/null +++ b/SFS_analysis/time_response_localwfs_vss.m @@ -0,0 +1,113 @@ +function varargout = time_response_localwfs_vss(X,xs,src,conf) +%TIME_RESPONSE_LOCALWFS_VSS time response for local WFS +% +% Usage: [s,t] = time_response_localwfs_vss(X,xs,src,conf) +% +% Input parameters: +% X - listener position / m +% xs - position of virtual source / m +% src - source type of the virtual source +% 'pw' -plane wave +% 'ps' - point source +% 'fs' - focused source +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% s - simulated time response +% t - corresponding time axis / s +% +% TIME_RESPONSE_LOCALWFS_VSS(X,xs,src,conf) simulates the impulse response of +% a source synthesized by local WFS using virtual secondary sources (VSS) at +% the given virtual microphone position X. +% The length in samples of the impulse response is given by conf.N. The +% actual calculation is done via sound_field_imp() and a loop over time t. A +% similar result can be achieved by using ir_localwfs() in combination with +% dummy_irs(). +% +% See also: ir_localwfs, sound_field_imp, freq_response_localwfs_vss + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 4; +nargmax = 4; +narginchk(nargmin,nargmax); +isargposition(X); +isargxs(xs); +isargchar(src); +isargstruct(conf); + + +%% ===== Configuration ================================================== +fs = conf.fs; +N = conf.N; +showprogress = conf.showprogress; +useplot = conf.plot.useplot; +% Select secondary source type +if strcmp('2D',conf.dimension) + greens_function = 'ls'; +else + greens_function = 'ps'; +end + + +%% ===== Computation ==================================================== +% Disable progress bar and plotting for sound_field_imp() +conf.showprogress = false; +conf.plot.useplot = false; +% Get the position of the loudspeakers +x0 = secondary_source_positions(conf); +x0 = secondary_source_selection(x0,xs,src); +x0 = secondary_source_tapering(x0,conf); +% Generate time axis +t = (0:N-1)'/fs; +s = zeros(1,length(t)); +d = driving_function_imp_localwfs_vss(x0,xs,src,conf); +for ii = 1:length(t) + if showprogress, progress_bar(ii,length(t)); end + % Calculate sound field at the listener position + p = sound_field_imp(X(1),X(2),X(3),x0,greens_function,d,t(ii),conf); + s(ii) = real(p); +end + +% Return parameter +if nargout>0, varargout{1}=s; end +if nargout>1, varargout{2}=t; end + + +%% ===== Plotting ======================================================== +if nargout==0 || useplot + figure; + figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); + plot(t*1000,s); + ylabel('amplitude'); + xlabel('time / ms'); +end diff --git a/SFS_analysis/time_response_nfchoa.m b/SFS_analysis/time_response_nfchoa.m index e0637aa6..eacf112a 100644 --- a/SFS_analysis/time_response_nfchoa.m +++ b/SFS_analysis/time_response_nfchoa.m @@ -1,113 +1,112 @@ -function varargout = time_response_nfchoa(X,xs,src,conf) -%TIME_RESPONSE_NFCHOA simulates the time response for NFC-HOA at the given -%listener position -% -% Usage: [s,t] = time_response_nfchoa(X,xs,src,[conf]) -% -% Input parameters: -% X - listener position / m -% xs - position of virtual source / m -% src - source type of the virtual source -% 'pw' -plane wave -% 'ps' - point source -% 'fs' - focused source -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% s - simulated time response -% t - corresponding time axis / s -% -% TIME_RESPONSE_NFCHOA(X,xs,src,conf) simulates the time response of the -% sound field at the given position X. The sound field is simulated for the -% given source type (src) using the sound_field_imp function. -% -% See also: sound_field_imp_nfchoa, freq_response_nfchoa, time_response_wfs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargposition(X); -isargxs(xs); -isargchar(src); -if nargin0, varargout{1}=s; end -if nargout>1, varargout{2}=t; end - - -%% ===== Plotting ======================================================== -if nargout==0 || useplot - figure; - figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); - plot(t/fs*1000,db(abs(s))); - ylabel('amplitude / dB'); - xlabel('time / ms'); -end +function varargout = time_response_nfchoa(X,xs,src,conf) +%TIME_RESPONSE_NFCHOA time response for NFC-HOA +% +% Usage: [s,t] = time_response_nfchoa(X,xs,src,conf) +% +% Input parameters: +% X - listener position / m +% xs - position of virtual source / m +% src - source type of the virtual source +% 'pw' -plane wave +% 'ps' - point source +% 'fs' - focused source +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% s - simulated time response +% t - corresponding time axis / s +% +% TIME_RESPONSE_NFCHOA(X,xs,src,conf) simulates the impulse response of a the +% source type src placed at xs and synthesized by NFC-HOA at the given virtual +% microphone position X. +% The length in samples of the impulse response is given by conf.N. The +% actual calculation is done via sound_field_imp() and a loop over time t. A +% similar result can be achieved by using ir_nfchoa() in combination with +% dummy_irs(). +% +% See also: ir_nfchoa, sound_field_imp, freq_response_nfchoa, time_response_wfs + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 4; +nargmax = 4; +narginchk(nargmin,nargmax); +isargposition(X); +isargxs(xs); +isargchar(src); +isargstruct(conf); + + +%% ===== Configuration ================================================== +fs = conf.fs; +N = conf.N; +showprogress = conf.showprogress; +useplot = conf.plot.useplot; +% Select secondary source type +if strcmp('2D',conf.dimension) + greens_function = 'ls'; +else + greens_function = 'ps'; +end + + +%% ===== Computation ==================================================== +% Disable progress bar and plotting for sound_field_imp() +conf.showprogress = false; +conf.plot.useplot = false; +% Get the position of the loudspeakers +x0 = secondary_source_positions(conf); +% Generate time axis +t = (0:N-1)'/fs; +S = zeros(1,length(t)); +% delay is the time offset added by the driving function +[d,~,delay] = driving_function_imp_nfchoa(x0,xs,src,conf); +for ii = 1:length(t) + if showprogress, progress_bar(ii,length(t)); end + % Calculate sound field at the listener position + p = sound_field_imp(X(1),X(2),X(3),x0,greens_function,d,t(ii)+delay,conf); + s(ii) = real(p); +end + +% Return parameter +if nargout>0, varargout{1}=s; end +if nargout>1, varargout{2}=t; end + + +%% ===== Plotting ======================================================== +if nargout==0 || useplot + figure; + figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); + plot(t*1000,s); + ylabel('amplitude'); + xlabel('time / ms'); +end diff --git a/SFS_analysis/time_response_point_source.m b/SFS_analysis/time_response_point_source.m new file mode 100644 index 00000000..fde62108 --- /dev/null +++ b/SFS_analysis/time_response_point_source.m @@ -0,0 +1,99 @@ +function varargout = time_response_point_source(X,xs,conf) +%TIME_RESPONSE_POINT_SOURCE time response of a point source +% +% Usage: [s,t] = time_response_point_source(X,xs,conf) +% +% Input parameters: +% X - listener position / m +% xs - position of point source / m +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% s - simulated time response +% t - corresponding time axis / s +% +% TIME_RESPONSE_POINT_SOURCE(X,xs,conf) simulates the impulse response of a +% point source placed at xs at the given virtual microphone position X. +% The length in samples of the impulse response is given by conf.N. +% The actual calculation is done via sound_field_imp() and a loop over time t. +% A similar result can be achieved by using ir_point_source() in combination +% with dummy_irs(). +% +% See also: ir_point_source, sound_field_imp, freq_response_point_source + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 3; +nargmax = 3; +narginchk(nargmin,nargmax); +isargposition(X); +isargxs(xs); +isargstruct(conf); + + +%% ===== Configuration ================================================== +fs = conf.fs; +N = conf.N; +showprogress = conf.showprogress; +useplot = conf.plot.useplot; + + +%% ===== Computation ==================================================== +% Disable progress bar and plotting for sound_field_imp() +conf.showprogress = false; +conf.plot.useplot = false; +% Get the position of the loudspeaker from point source position. +% NOTE: its directivity [0 -1 0] will be ignored +x0 = [xs 0 -1 0 1]; +% Generate time axis +t = (0:N-1)'/fs; +s = zeros(1,length(t)); +for ii = 1:length(t) + if showprogress, progress_bar(ii,length(t)); end + % Calculate sound field at the listener position + p = sound_field_imp(X(1),X(2),X(3),x0,'ps',dirac_imp(),t(ii),conf); + s(ii) = real(p); +end + +% Return parameter +if nargout>0, varargout{1}=s; end +if nargout>1, varargout{2}=t; end + + +%% ===== Plotting ======================================================== +if nargout==0 || useplot + figure; + figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); + plot(t*1000,s); + ylabel('amplitude'); + xlabel('time / ms'); +end diff --git a/SFS_analysis/time_response_wfs.m b/SFS_analysis/time_response_wfs.m index 081a56a7..c4c1f8b5 100644 --- a/SFS_analysis/time_response_wfs.m +++ b/SFS_analysis/time_response_wfs.m @@ -1,123 +1,114 @@ -function varargout = time_response_wfs(X,xs,src,conf) -%TIME_RESPONSE_WFS simulates the time response for WFS at the given -%listener position -% -% Usage: [s,t] = time_response_wfs(X,xs,src,[conf]) -% -% Input parameters: -% X - listener position / m -% xs - position of virtual source / m -% src - source type of the virtual source -% 'pw' -plane wave -% 'ps' - point source -% 'fs' - focused source -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% s - simulated time response -% t - corresponding time axis / s -% -% TIME_RESPONSE_WFS(X,xs,src,conf) simulates the time response of the -% sound field at the given position X. The sound field is simulated for the -% given source type (src) using the sound_field_imp_wfs function. -% -% See also: sound_field_imp_wfs, freq_response_wfs, time_response_nfchoa - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargposition(X); -isargxs(xs); -isargchar(src); -if nargin0, varargout{1}=s; end -if nargout>1, varargout{2}=t; end - - -%% ===== Plotting ======================================================== -if nargout==0 || useplot - figure; - figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); - plot(t/fs*1000,db(abs(s))); - ylabel('amplitude / dB'); - xlabel('time / ms'); -end +function varargout = time_response_wfs(X,xs,src,conf) +%TIME_RESPONSE_WFS time response for WFS +% +% Usage: [s,t] = time_response_wfs(X,xs,src,conf) +% +% Input parameters: +% X - listener position / m +% xs - position of virtual source / m +% src - source type of the virtual source +% 'pw' -plane wave +% 'ps' - point source +% 'fs' - focused source +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% s - simulated time response +% t - corresponding time axis / s +% +% TIME_RESPONSE_WFS(X,xs,src,conf) simulates the impulse response of a the +% source type src placed at xs and synthesized by WFS at the given virtual +% microphone position X. +% The length in samples of the impulse response is given by conf.N. The +% actual calculation is done via sound_field_imp() and a loop over time t. A +% similar result can be achieved by using ir_wfs() in combination with +% dummy_irs(). +% +% See also: ir_wfs, sound_field_imp, freq_response_wfs, time_response_nfchoa + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 4; +nargmax = 4; +narginchk(nargmin,nargmax); +isargposition(X); +isargxs(xs); +isargchar(src); +isargstruct(conf); + + +%% ===== Configuration ================================================== +fs = conf.fs; +N = conf.N; +showprogress = conf.showprogress; +useplot = conf.plot.useplot; +% Select secondary source type +if strcmp('2D',conf.dimension) + greens_function = 'ls'; +else + greens_function = 'ps'; +end + + +%% ===== Computation ==================================================== +% Disable progress bar and plotting for sound_field_imp() +conf.showprogress = false; +conf.plot.useplot = false; +% Get the position of the loudspeakers +x0 = secondary_source_positions(conf); +x0 = secondary_source_selection(x0,xs,src); +x0 = secondary_source_tapering(x0,conf); +% Generate time axis +t = (0:N-1)'/fs; +s = zeros(1,length(t)); +% delay is the time offset added by the driving function +[d,~,~,delay] = driving_function_imp_wfs(x0,xs,src,conf); +for ii = 1:length(t) + if showprogress, progress_bar(ii,length(t)); end + % calculate sound field at the listener position + p = sound_field_imp(X(1),X(2),X(3),x0,greens_function,d,t(ii)+delay,conf); + s(ii) = real(p); +end + +% Return parameter +if nargout>0, varargout{1}=s; end +if nargout>1, varargout{2}=t; end + + +%% ===== Plotting ======================================================== +if nargout==0 || useplot + figure; + figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); + plot(t*1000,s); + ylabel('amplitude'); + xlabel('time / ms'); +end diff --git a/SFS_analysis/wave_fronts_wfs.m b/SFS_analysis/wave_fronts_wfs.m index 2c0fab68..f73158ab 100644 --- a/SFS_analysis/wave_fronts_wfs.m +++ b/SFS_analysis/wave_fronts_wfs.m @@ -1,206 +1,195 @@ -function varargout = wave_fronts_wfs(X,phi,xs,src,gnuplot,conf) -%WAVE_FRONTS_WFS returns direction, amplitude and time of the single wave -% fronts for WFS -% -% Usage: [alpha,a,t] = wave_fronts_wfs(X,phi,xs,src,[gnuplot],[conf]) -% -% Input parameters: -% X,phi - listener position and direction / m, rad -% xs - virtual source position / m -% src - used source model: -% 'pw' - plane wave -% 'ps' - point source -% 'fs' - focused source -% gnuplot - boolean indicator if the data should be stored in to output -% files, called direction_nls*.txt for later plotting with -% gnuplot, default: false -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% alpha - angle of incident for every echo / rad -% a - amplitudes of the echos -% t - time of the wave fronts / s -% -% WAVE_FRONTS_WFS(X,phi,xs,src) calculates the direction of the single wave -% fronts (due to aliasing artifacts) arriving from the loudspeakers for a -% WFS array at the given listener position X for the given virtual source -% xs. -% -% Refrences: -% H. Wierstorf, A. Raake, M. Geier, S. Spors (2013) - Perception of Focused -% Sources in Wave Field Synthesis, J. Audio Eng. Soc. 61.1, p. 5-16 -% -% See also: ir_wfs, driving_function_imp_wfs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ==================================== -nargmin = 4; -nargmax = 6; -narginchk(nargmin,nargmax); -isargposition(X); -isargxs(xs), -isargscalar(phi); -if nargin==nargmax-1 - if isstruct(gnuplot) - conf = gnuplot; - gnuplot = false; - else - conf = SFS_config; - end -elseif nargin==nargmax-2 - conf = SFS_config; - gnuplot = false; -end -isargstruct(conf); - - -%% ===== Configuration =================================================== -c = conf.c; -useplot = conf.plot.useplot; - - -%% ===== Variables ======================================================= -phi = correct_azimuth(phi); -% Loudspeaker positions -x0 = secondary_source_positions(conf); -x0 = secondary_source_selection(x0,xs,src); -x0 = secondary_source_tapering(x0,conf); -% Number of loudspeaker -nls = size(x0,1); - -%% ===== Calculate direction of the echos =============================== - -% Geometry -% x0(ii,:) X0 -% x-axis <-^--^--^--^--^--^--^--^--^-|-^--^--^--^--^--^--^--^--^-- -% | | -% | | | -% | | | -% x | | -% xs | | -% O | -% X | -% v -% y-axis -% - -% Get time delay and weighting factor for a single echo -[~,delay,a] = driving_function_imp_wfs(x0,xs,src,conf); -% Time, in which pre-echos occur: -% time_from_secondary_source_to_listener + delay -t = vector_norm(bsxfun(@minus,X,x0(:,1:3)),2)./c + delay -norm(X-xs(:,1:3))/c; -% Set start to t=0 -t = t-min(t); -% Direction of the wave fronts / rad -% angle between listener and secondary source (-pi < alpha <= pi, -% without phi) -% NOTE: phi is the orientation of the listener (see first graph) -[alpha_tmp,~,~] = cart2sph(x0(:,1)-X(1),x0(:,2)-X(2),x0(:,3)-X(3)); -alpha = alpha_tmp - phi; - -% Return values -if nargout>0, varargout{1}=alpha; end -if nargout>1, varargout{2}=a; end -if nargout>2, varargout{3}=t; end - - -%% ===== Plotting ======================================================= -if (nargout==0 || useplot) - % Plot the amplitude (dB) over time - figure; plot(t,20*log10(a)+100,'xb'); - xlabel('t / s'); - ylabel('Amplitude / dB'); -end - - -%% ===== Generate data structures for plotting with gnuplot ============= -if gnuplot - - v = zeros(nls,3); - vdB = zeros(nls,3); - for ii = 1:nls - % === Direction and amplitude in vector notation === - % Rotation matrix (see: http://en.wikipedia.org/wiki/Rotation_matrix) - % RM = [cos(alpha) -sin(alpha); ... - % sin(alpha) cos(alpha)]; - RM = rotation_matrix(alpha(ii),3,'counterclockwise'); - % Vector notation of angle and amplitude (in x,y coordinates) - v(ii,:) = a(ii) .* (RM * [0 1 0]'); - % \____ ____/ - % \/ - % unit vector in direction - % of the given loudspeaker - % In dB notation - vdB(ii,:) = (20*log10(a(ii))+100) .* (RM * [0 1 0]'); - end - - % name of the data file to store the result - outfile = sprintf('direction_nls%i_xs%.1f_ys%.1f_X%.1f_Y%.1f.txt', ... - nls,xs(1),xs(2),X(1),X(2)); - outfiledB = sprintf('direction_nls%i_xs%.f1_ys%.1f_X%.1f_Y%.1f_dB.txt',... - nls,xs(1),xs(2),X(1),X(2)); - - - % == Amplitude and direction of the direct sound from the virtual source == - % Calculate amplitude for the virtual source (which arrives per - % definition at t = 0 - A = sum(a); - % Calculate the direction of the virtual source pulse (rad) - [alpha_ds,~,~] = cart2sph(xs(1)-X(1),xs(2)-X(2),xs(3)-X(3)); - alpha_ds = alpha_ds - phi; - RM_ds = rotation_matrix(alpha_ds,3,'counterclockwise'); - X_ds = A .* (RM_ds * [0 1 0]'); - X_dsdB = (20*log10(A)+100) .* (RM_ds * [0 1 0]'); - - % Position of the listener - Xn = X(1).*ones(nls,1); - % Open file for storing results - fid = fopen(outfile,'w'); - fiddB = fopen(outfiledB,'w'); - % Angle and amplitude in vector notation - % Generate matrix for gnuplot plot - gnuM = [Xn t v]; - % Directions weighted by the amplitude of the echos - gnudB = [Xn t vdB]; - % Store data - fprintf(fid,'#X\tt\tx\ty\tz\n'); - fprintf(fiddB,'#X\tt\tx\ty\tA\n'); - fprintf(fid,'%f\t%f\t%f\t%f\t%f\n',gnuM); - fprintf(fiddB,'%f\t%f\t%f\t%f\t%f\t%f\n',[gnudB (20*log10(a)+100)]); - fprintf(fid,'\n\n%f\t0\t%f\t%f\t%f',X(1),X_ds(1),X_ds(2),A); - fprintf(fiddB,'\n\n%f\t0\t%f\t%f\t%f',X(1),X_dsdB(1),X_dsdB(2),20*log10(A)+100); - fclose(fid); - fclose(fiddB); -end +function varargout = wave_fronts_wfs(X,phi,xs,src,gnuplot,conf) +%WAVE_FRONTS_WFS direction, amplitude and time of WFS wave fronts +% +% Usage: [alpha,a,t] = wave_fronts_wfs(X,phi,xs,src,[gnuplot],conf) +% +% Input parameters: +% X,phi - listener position and direction / m, rad +% xs - virtual source position / m +% src - used source model: +% 'pw' - plane wave +% 'ps' - point source +% 'fs' - focused source +% gnuplot - boolean indicator if the data should be stored in to output +% files, called direction_nls*.txt for later plotting with +% gnuplot, default: false +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% alpha - angle of incident for every echo / rad +% a - amplitudes of the echos +% t - time of the wave fronts / s +% +% WAVE_FRONTS_WFS(X,phi,xs,src,conf) calculates the direction of the single +% wave fronts (due to aliasing artifacts) arriving from the loudspeakers for a +% WFS array at the given listener position X for the given virtual source +% xs. +% +% Refrences: +% H. Wierstorf, A. Raake, M. Geier, S. Spors (2013) - Perception of Focused +% Sources in Wave Field Synthesis, J. Audio Eng. Soc. 61.1, p. 5-16 +% +% See also: ir_wfs, driving_function_imp_wfs + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ==================================== +nargmin = 5; +nargmax = 6; +narginchk(nargmin,nargmax); +isargposition(X); +isargxs(xs), +isargscalar(phi); +if nargin0, varargout{1}=alpha; end +if nargout>1, varargout{2}=a; end +if nargout>2, varargout{3}=t; end + + +%% ===== Plotting ======================================================= +if (nargout==0 || useplot) + % Plot the amplitude (dB) over time + figure; plot(t,20*log10(a)+100,'xb'); + xlabel('t / s'); + ylabel('Amplitude / dB'); +end + + +%% ===== Generate data structures for plotting with gnuplot ============= +if gnuplot + + v = zeros(nls,3); + vdB = zeros(nls,3); + for ii = 1:nls + % === Direction and amplitude in vector notation === + % Rotation matrix (see: https://en.wikipedia.org/wiki/Rotation_matrix) + % RM = [cos(alpha) -sin(alpha); ... + % sin(alpha) cos(alpha)]; + RM = rotation_matrix(alpha(ii),3,'counterclockwise'); + % Vector notation of angle and amplitude (in x,y coordinates) + v(ii,:) = a(ii) .* (RM * [0 1 0]'); + % \____ ____/ + % \/ + % unit vector in direction + % of the given loudspeaker + % In dB notation + vdB(ii,:) = (20*log10(a(ii))+100) .* (RM * [0 1 0]'); + end + + % name of the data file to store the result + outfile = sprintf('direction_nls%i_xs%.1f_ys%.1f_X%.1f_Y%.1f.txt', ... + nls,xs(1),xs(2),X(1),X(2)); + outfiledB = sprintf('direction_nls%i_xs%.f1_ys%.1f_X%.1f_Y%.1f_dB.txt',... + nls,xs(1),xs(2),X(1),X(2)); + + + % == Amplitude and direction of the direct sound from the virtual source == + % Calculate amplitude for the virtual source (which arrives per + % definition at t = 0 + A = sum(a); + % Calculate the direction of the virtual source pulse (rad) + [alpha_ds,~,~] = cart2sph(xs(1)-X(1),xs(2)-X(2),xs(3)-X(3)); + alpha_ds = alpha_ds - phi; + RM_ds = rotation_matrix(alpha_ds,3,'counterclockwise'); + X_ds = A .* (RM_ds * [0 1 0]'); + X_dsdB = (20*log10(A)+100) .* (RM_ds * [0 1 0]'); + + % Position of the listener + Xn = X(1).*ones(nls,1); + % Open file for storing results + fid = fopen(outfile,'w'); + fiddB = fopen(outfiledB,'w'); + % Angle and amplitude in vector notation + % Generate matrix for gnuplot plot + gnuM = [Xn t v]; + % Directions weighted by the amplitude of the echos + gnudB = [Xn t vdB]; + % Store data + fprintf(fid,'#X\tt\tx\ty\tz\n'); + fprintf(fiddB,'#X\tt\tx\ty\tA\n'); + fprintf(fid,'%f\t%f\t%f\t%f\t%f\n',gnuM); + fprintf(fiddB,'%f\t%f\t%f\t%f\t%f\t%f\n',[gnudB (20*log10(a)+100)]); + fprintf(fid,'\n\n%f\t0\t%f\t%f\t%f',X(1),X_ds(1),X_ds(2),A); + fprintf(fiddB,'\n\n%f\t0\t%f\t%f\t%f',X(1),X_dsdB(1),X_dsdB(2),20*log10(A)+100); + fclose(fid); + fclose(fiddB); +end diff --git a/SFS_binaural_synthesis/auralize_ir.m b/SFS_binaural_synthesis/auralize_ir.m index e29c6fda..fc0d4c29 100644 --- a/SFS_binaural_synthesis/auralize_ir.m +++ b/SFS_binaural_synthesis/auralize_ir.m @@ -1,132 +1,102 @@ -function outsig = auralize_ir(ir,content,usenorm,conf) -%AURALIZE_IR auralizes an impulse response with an audio file/signal -% -% Usage: outsig = auralize_ir(ir,[[[content],normalize],conf]) -% -% Input parameters: -% ir - impulse response (IR). Also an binaural room scanning -% (BRS) matrix can be auralized, then only the two first -% channels will be used. -% content - content file or signal vector to be used for auralisation -% (mono, if it contains more than one channel, only the -% first will be used). -% Also predefined content can be used by applying the -% one of the following strings: -% 'speech', 'noise', 'pinknoise', 'cello', 'castanets'. -% Then these contents will be used to auralise the IR. -% The corresponding content files are specified in -% SFS_config. -% normalize - normalize the signal (1 or 0), default: 1 -% conf - optional configuration struct (see SFS_config) -% -% AURALIZE_IR(ir,content,normalize) convolves the first two channels of the -% given IR with the given content and returns the resulting outsig. If -% instead of an explicite content file or vector only a string containig -% 'speech', 'noise', 'pinknoise', 'cello' or 'castanets' is given, the -% corresponding content file as specified in conf is used. -% -% See also: auralize_ir_file, ir_wfs, ir_generic, ir_point_source - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters and configuration ================= -nargmin = 2; -nargmax = 4; -narginchk(nargmin,nargmax); -isargmatrix(ir); - -if nargin<3 - usenorm = 1; - conf = SFS_config; -elseif nargin2 - warning('Your impulse response has more than two channels.'); -end -% Convolve the impulse responses with the content signal -outsig = convolution(ir,content); -% Scale output -if(usenorm) - outsig = norm_signal(outsig); -end +function outsig = auralize_ir(ir,content,usenorm,conf) +%AURALIZE_IR auralizes an impulse response with an audio file/signal +% +% Usage: outsig = auralize_ir(ir,content,[normalize],conf) +% +% Input parameters: +% ir - impulse response (IR). Also an binaural room scanning +% (BRS) matrix can be auralized, then only the two first +% channels will be used. +% content - content file or signal vector to be used for auralisation +% (mono, if it contains more than one channel, only the +% first will be used). +% normalize - normalize the signal (1 or 0), default: 1 +% conf - configuration struct (see SFS_config) +% +% AURALIZE_IR(ir,content,normalize,conf) convolves the first two channels of +% the given IR with the given content and returns the resulting outsig. The +% content can be specified in the form of an explicite content file or vector. +% +% See also: ir_wfs, ir_generic, ir_point_source + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters and configuration ================= +nargmin = 3; +nargmax = 4; +narginchk(nargmin,nargmax); +isargmatrix(ir); +if nargin2 + warning('Your impulse response has more than two channels.'); +end +% Convolve the impulse responses with the content signal +outsig = convolution(ir,content); +% Scale output +if(usenorm) + outsig = norm_signal(outsig); +end diff --git a/SFS_binaural_synthesis/compensate_headphone.m b/SFS_binaural_synthesis/compensate_headphone.m index e6c41783..98c7cd83 100644 --- a/SFS_binaural_synthesis/compensate_headphone.m +++ b/SFS_binaural_synthesis/compensate_headphone.m @@ -1,82 +1,77 @@ -function ir = compensate_headphone(ir,conf) -%COMPENSATE_HEADPHONE applies a headphone compensation to the IR -% -% Usage: ir = compensate_headphone(ir,[conf]) -% -% Input parameters: -% ir - Impulse response to which the compensation should be applied -% conf - optional configuration struct (see SFS_config) -% -% Output: -% ir - Impulse response which is compensated for the given headphone -% -% COMPENSATE_HEADPHONE(ir,conf) applies a headphone compensation to the -% given impulse response. Which headphone compensation it should use is -% mentioned in the conf struct. -% The compensation is only applied, if the conf.ir.usehcomp value is not false. -% -% See also: ir_wfs, ir_point_source, ir_generic - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 2; -narginchk(nargmin,nargmax); -isargmatrix(ir); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 5; -nargmax = 6; -narginchk(nargmin,nargmax); -isargposition(X); -isargscalar(phi); -isargsecondarysource(x0); -isargmatrix(d); -check_irs(irs); -if nargin==nargmax-1 - conf = SFS_config; -end - - -%% ===== Configuration ================================================== -N = conf.N; % target length of BRS impulse responses - - -%% ===== Variables ====================================================== -phi = correct_azimuth(phi); - - -%% ===== BRIR =========================================================== -% Initial values -ir_generic = zeros(N,2); - -% Create a BRIR for every single loudspeaker -warning('off','SFS:irs_intpol'); -for ii=1:size(x0,1) - - % Direction of the source from the listener - x_direction = x0(ii,1:3)-X; - % Change to spherical coordinates - [alpha,theta,r] = cart2sph(x_direction(1),x_direction(2),x_direction(3)); - - % Incoporate head orientation and ensure -pi <= alpha < pi - alpha = correct_azimuth(alpha-phi); - - % === IR interpolation === - % Get the desired IR. - % If needed interpolate the given IR set - ir = get_ir(irs,[alpha,theta,r],conf); - - % === Sum up virtual loudspeakers/HRIRs and add loudspeaker time delay === - % Also applying the weights of the secondary sources including integration - % weights or tapering windows etc. - ir_generic = ir_generic + fix_length(convolution(ir,d(:,ii)),N).*x0(ii,7); - -end -warning('on','SFS:irs_intpol'); - - -%% ===== Headphone compensation ========================================= -ir = compensate_headphone(ir_generic,conf); +function ir = ir_generic(X,head_orientation,x0,d,sofa,conf) +%IR_GENERIC impulse response of secondary sources including driving signals +% +% Usage: ir = ir_generic(X,head_orientation,x0,d,sofa,conf) +% +% Input parameters: +% X - listener position / m +% head_orientation - orientation of the listener with [phi theta] / +% (rad, rad) +% x0 - secondary sources [n x 7] / m +% d - driving signals [m x n] +% sofa - impulse response data set for the secondary sources +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% ir - impulse response for the desired driving functions +% (nx2 matrix) +% +% IR_GENERIC(X,head_orientation,x0,d,sofa,conf) calculates a binaural room +% impulse response using the provided sofa database for the sound travelling +% from the secondary sources to the listener position. In addition, the given +% driving signals d are incorporated. +% +% See also: ir_wfs, ir_nfchoa, ir_point_source, auralize_ir + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 6; +nargmax = 6; +narginchk(nargmin,nargmax); +isargposition(X); +isargvector(head_orientation); +isargsecondarysource(x0); +isargmatrix(d); +isargstruct(conf); +if size(x0,1)~=size(d,2) + error(['%s: The number of secondary sources (%i) and driving ', ... + 'signals (%i) does not correspond.'], ... + upper(mfilename),size(x0,1),size(d,2)); +end + +%% ===== Configuration ================================================== +N = conf.N; % target length of BRS impulse responses + + +%% ===== BRIR =========================================================== +% Initial values +ir_generic = zeros(N,2); + +% Create a BRIR for every single loudspeaker +for ii=1:size(x0,1) + + % === Get the desired impulse response. + % If needed interpolate the given impulse response set and weight, delay the + % impulse for the correct distance + ir = get_ir(sofa,X,head_orientation,x0(ii,1:3),'cartesian',conf); + + % === Sum up virtual loudspeakers/HRIRs and add loudspeaker time delay === + % Also applying the weights of the secondary sources including integration + % weights or tapering windows etc. + ir_generic = ir_generic + fix_length(convolution(ir,d(:,ii)),N).*x0(ii,7); + +end + + +%% ===== Headphone compensation ========================================= +ir = compensate_headphone(ir_generic,conf); diff --git a/SFS_binaural_synthesis/ir_localwfs.m b/SFS_binaural_synthesis/ir_localwfs.m index 1f9c11ad..3f95d3b0 100644 --- a/SFS_binaural_synthesis/ir_localwfs.m +++ b/SFS_binaural_synthesis/ir_localwfs.m @@ -1,83 +1,76 @@ -function [ir,x0] = ir_localwfs(X,phi,xs,src,irs,conf) -%IR_LOCALWFS generates a binaural simulation of local WFS -% -% Usage: [ir,x0] = ir_localwfs(X,phi,xs,src,irs,[conf]) -% -% Input parameters: -% X - listener position / m -% phi - listener direction [head orientation] / rad -% 0 means the head is oriented towards the x-axis. -% xs - virtual source position / m -% src - source type: 'pw' -plane wave -% 'ps' - point source -% irs - IR data set for the secondary sources -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% ir - impulse response for the desired WFS array (nx2 matrix) -% x0 - secondary sources / m -% -% IR_LOCALWFS(X,phi,xs,src,irs,conf) calculates a binaural room impulse -% response for a virtual source at xs for a virtual LOCAL WFS array and a -% listener located at X. -% -% See also: ssr_brs_wfs, ir_point_source, auralize_ir - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 5; -nargmax = 6; -narginchk(nargmin,nargmax); -if nargin Y0 => focused source] / m -% src - source type: 'pw' -plane wave -% 'ps' - point source -% irs - IR data set for the secondary sources -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% ir - impulse response for the desired HOA synthesis (nx2 matrix) -% x0 - secondary sources -% -% IR_NFCHOA(X,phi,xs,src,L,irs,conf) calculates a binaural room impulse -% response for a virtual source at xs for a virtual NFCHOA array and a -% listener located at X. -% -% See also: ssr_brs_nfchoa, ir_nfchoa, ir_point_source, auralize_ir - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 5; -nargmax = 6; -narginchk(nargmin,nargmax); -if nargin==nargmax-1 - conf = SFS_config; -end -if conf.debug - isargposition(X); - isargxs(xs); - isargscalar(phi); - isargpositivescalar(L); - isargchar(src); - check_irs(irs); -end - - -%% ===== Variables ====================================================== -% Loudspeaker positions -x0 = secondary_source_positions(conf); - - -%% ===== BRIR =========================================================== -% Calculate driving function -d = driving_function_imp_nfchoa(x0,xs,src,conf); -% Generate the impulse response for NFCHOA -ir = ir_generic(X,phi,x0,d,irs,conf); +function [ir,x0,delay] = ir_nfchoa(X,head_orientation,xs,src,sofa,conf) +%IR_NFCHOA binaural simulation of NFCHOA +% +% Usage: [ir,x0,delay] = ir_nfchoa(X,head_orientation,xs,src,sofa,conf) +% +% Input parameters: +% X - listener position / m +% head_orientation - orientation of the listener with [phi theta] / +% (rad, rad) +% xs - virtual source position / m +% src - source type: 'pw' -plane wave +% 'ps' - point source +% sofa - impulse response data set for the secondary sources +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% ir - impulse response for the desired HOA synthesis +% (nx2 matrix) +% x0 - secondary sources +% delay - delay added by driving function / s +% +% IR_NFCHOA(X,head_orientation,xs,src,L,sofa,conf) calculates a binaural room +% impulse response for a virtual source at xs for a virtual NFCHOA array and +% a listener located at X. +% +% See also: ssr_brs_nfchoa, ir_nfchoa, ir_point_source, auralize_ir + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 6; +nargmax = 6; +narginchk(nargmin,nargmax); +if conf.debug + isargposition(X); + isargxs(xs); + isargvector(head_orientation); + isargpositivescalar(L); + isargchar(src); + isargstruct(config); +end + + +%% ===== Variables ====================================================== +% Loudspeaker positions +x0 = secondary_source_positions(conf); + + +%% ===== BRIR =========================================================== +% Calculate driving function +[d,~,delay] = driving_function_imp_nfchoa(x0,xs,src,conf); +% Generate the impulse response for NFCHOA +ir = ir_generic(X,head_orientation,x0,d,sofa,conf); diff --git a/SFS_binaural_synthesis/ir_point_source.m b/SFS_binaural_synthesis/ir_point_source.m index 1b3b4c02..ac9a295a 100644 --- a/SFS_binaural_synthesis/ir_point_source.m +++ b/SFS_binaural_synthesis/ir_point_source.m @@ -1,72 +1,65 @@ -function ir = ir_point_source(X,phi,xs,irs,conf) -%IR_POINT_SOURCE generates a binaural simulation of a point source -% -% Usage: ir = ir_point_source(X,phi,xs,irs,[conf]) -% -% Input parameters: -% X - listener position / m -% phi - listener direction [head orientation] / rad -% xs - source position / m -% irs - IR data set for the second sources -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% ir - Impulse response (nx2 matrix) -% -% IR_POINT_SOURCE(X,phi,xs,irs,conf) calculates a impulse response for a -% single loudspeaker at position xs and a listener located at X, looking -% into direction phi. Whereby at phi = 0 the listener is looking in the -% direction of the x-axis. -% -% See also: ssr_brs_point_source, get_ir, ir_wfs, auralize_ir - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ==================================== -nargmin = 4; -nargmax = 5; -narginchk(nargmin,nargmax); -isargposition(X); -isargxs(xs); -isargscalar(phi); -check_irs(irs); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 5; -nargmax = 6; -narginchk(nargmin,nargmax); -if nargin= 1 +% This should be in the order of (1/stepsize of fractional delays) +conf.delayline.resamplingfactor = 100; % / 1 +% Order of Parks-McClellan resample filter (only for 'pm') +% This results in a filter length of resamplingfactor*resamplingorder +conf.delayline.resamplingorder = 64; +% Order of delayline filter (only for Lagrange, Least-Squares & Thiran) +conf.delayline.filterorder = 0; % / 1 +% Number of parallel filters in Farrow structure +% (only for 'farrow'); +conf.delayline.filternumber = 1; % / 1 + + +%% ===== Sound Field Synthesis (SFS) ===================================== +% Common sound field synthesis settings +% +% === Dimensionality === +% Dimensionality of the secondary sources and the sound field synthesis driving +% functions: +% '2D' - line sources as secondary sources, arranged in a circle, line, ... +% '2.5D' - point sources as secondary sources, arranged in a circle, line, ... +% '3D' - point sources as secondary sources, arranged in a sphere, plane, ... +conf.dimension = '2.5D'; % string +% +% === Driving functions === +% Implementation of driving functions. For the default ones use 'default'. These +% functions are described at https://sfs.readthedocs.io/. For possible other +% flags have a look into the driving functions as they can be quite specific. +% Most users can safely use the 'default' flag here. +conf.driving_functions = 'default'; % string +% +% === Impulse responses === +% Length of impulse responses used in the time domain driving functions +% and for the creation of the binaural simulations. +% Don't worry, SFS checks for you if conf.N is large enough. +conf.N = 2048; % samples +% +% === 2.5D === +% The amplitude will be correct at the point xref for 2.5D +% synthesis. +conf.xref = [0 0 0]; % / m +% +% === Tapering === +% The truncation of the loudspeaker array leads to diffraction of the +% synthesized sound field. It has been shown that the truncation can be +% described by cylindrical waves originating from the edges of the array, see +% Sect. 8.3.2 in Born, Wolf (1999) for the general principle and Sect. 3.2 in +% Wierstorf (2014) for how it relates to WFS. Therefore a good method to reduce +% artifacts due to the diffraction edge waves is to fade out the amplitude of +% the driving function at the edges of the array. This method is called tapering +% and implemented using a Hann window in the SFS Toolbox. +conf.usetapwin = true; % boolean +% Size of the tapering window +conf.tapwinlen = 0.3; % / percent of array length, 0..1 +% +% === Time Domain Implementation === +% Adjust the starting time in time domain driving functions. +% This can be set to +% 'system' - the first secondary source will be active at t=0 +% 'source' - the virtual source will be active at t=0 +% Setting it to 'system' is most convenient when simulating single sources as +% you will always see activity in the sound field for t>0. Setting it to +% 'source' helps you to simulate different sources as you can time align them +% easily. Note, that for virtual sources outside of the array this can mean you +% will see no activity inside the listening area until the time has passed, that +% the virtual source needs from its position until the nearest secondary source. +% Also note, using 'source' for systems with unbounded listening areas -- e.g. +% linear arrays -- focussed virtual sources may not be placed arbitrarily +% far from the secondary sources. +conf.t0 = 'system'; % string +% Bandpass filter applied in sound_field_imp() +conf.usebandpass = false; % boolean +conf.bandpassflow = 10; % / Hz +conf.bandpassfhigh = 20000; % / Hz +% +% === Modal Weighting === +% Additional weighting of the modal coefficients by window function used +% for Near-Field Compensated Higher Order Ambisonics (NFC-HOA) and Local Sound +% Field Synthesis using Spatial Bandwidth Limitation (LSFS-SBL). +% +% Window type. Available windows are: +% 'rect' - all coefficients are weighted by 1.0 +% 'max-rE' - 2D max-rE weighting +% 'kaiser', 'kaiser-bessel' - Kaiser aka. Kaiser-Bessel window +% 'tukey' - modified Tukey (tapered cosine) window +conf.modal_window = 'rect'; % string +% Scalar parameter for window, if applicable. Effect for distinct window: +% 'rect' - no effect +% 'max-rE' - no effect +% 'kaiser' - [0,inf]. trade-off between main-lobe width and side-lobe levels. +% 0.0 results in the rectangular window and the smallest main-lobe +% width. infinity results in a dirac impulse. +% 'tukey' - [0,1]. width of cosine tapering relative to the modal order. +% 0.0 results in the rectangular window, 1.0 results in a modified +% Hann-window +conf.modal_window_parameter = 0.0; % float + + + +%% ===== Sound Field Simulations ========================================= +% Simulations of monochromatic or time domain sound field +% +% xyz-resolution for sound field simulations, this value is applied along every +% desired dimension, except if only one point is desired +conf.resolution = 300; % / samples +% Phase of omega of sound field (change this value to create monochromatic sound +% fields with different phases, for example this can be useful to create a movie) +conf.phase = 0; % / rad + + +% ===== Secondary Sources ================================================ +% Settings of the used loudspeaker array +% +% Number of secondary sources +conf.secondary_sources.number = 64; % integer +% Diameter/Length of secondary source array +conf.secondary_sources.size = 3; % / m +% Center of array, X0 +conf.secondary_sources.center = [0 0 0]; % / m +% Array geometry +% Possible values are: 'line', 'box', 'rounded-box', 'circle', 'sphere', 'custom' +conf.secondary_sources.geometry = 'circle'; % string +% Exclusive for 'rounded-box' array geometry. Defines the bending radius for +% the corners of the smoothed box +conf.secondary_sources.corner_radius = 0.0; % / m +% Vector containing custom secondary source positions and directions. +% This is used if geometry = 'custom' is specified. +% conf.secondary_sources.x0 = [x0; y0; z0; nx0; ny0; nz0; weight]; +% Or it could also be a SOFA struct or file name, in this case the positions are +% extracted from the provided SOFA file. +conf.secondary_sources.x0 = []; % / m +% For spherical arrays, available grids are: +% 'equally_spaced_points' - Sphere with equal distance between grid points +% 'gauss' - Gauss grid +% 'fabian' - grid of 3D HRTF measurement, available at +% https://doi.org/10.14279/depositonce-5718 +% +% Note, that 'equally_spaced_points' and 'fabian' are precomputed grids that +% will be automatically downloaded and cached on your disk. All available number +% of secondary sources for those grids can be seen at: +% https://github.com/sfstoolbox/data/tree/master/spherical_grids +% An exception are Gauss grids, which are available via 'gauss' and will be +% calculated on the fly allowing very high number of secondary sources. +conf.secondary_sources.grid = 'equally_spaced_points'; % string +% Grid for linear arrays: Allows for logarithmically spaced arrays. It defines +% the ratio of the spacing of the loudspeakers at the extremities of the array +% and the spacing of the loudspeakers at the center of the array. 1.0 for +% equi-distant sampling. +conf.secondary_sources.logspread = 1.0; % float + + +%% ===== Wave Field Synthesis (WFS) ====================================== +% Settings for WFS, see Spors et al. (2008) for an introduction +% +% === Pre-Equalization === +% WFS can be implemented very efficiently using a delay-line with different +% amplitudes and convolving the whole signal once with the so called +% pre-equalization filter, see Spors and Ahrens (2010a). +% Use WFS preequalization-filter +conf.wfs.usehpre = true; % boolean +% FIR or IIR pre-equalization filter +% NOTE: only FIR is working under octave at the moment +conf.wfs.hpretype = 'FIR'; % 'FIR' or 'IIR' +% Lower frequency limit of preequalization filter +% If we have a finite length (<10m) of the secondary source distribution we +% will have a 3dB increase at the very low frequencies and the pre-equalization +% filter should only start above those frequencies, see Sect. 7.2 in Spors and +% Ahrens (2010b). +conf.wfs.hpreflow = 50; % / Hz +% Upper frequency limit of preequalization filter +% If we have aliasing in our system we only want to use +% the pre-equalization filter until the aliasing frequency, because of the +% energy the aliasing is adding to the spectrum above this frequency, see +% Sect. 6.3 in Spors and Ahrens (2010a). +conf.wfs.hprefhigh = 1200; % / Hz +% IIR bandwidth for the Lagrange interpolation region +conf.wfs.hpreBandwidth_in_Oct = 2; % / octaves +% desired IIR filter order +conf.wfs.hpreIIRorder = 4; % integer +% desired FIR filter order, results in N+1 taps +conf.wfs.hpreFIRorder = 128; % even integer + + +%% ===== Spectral Division Method (SDM) ================================== +% Settings for SDM, see Ahrens and Spors (2010) for an introduction +% +% Use the evanescent part of the driving function for SDM +conf.sdm.withev = true; % boolean + + +%% ===== Near-Field Compensated Higher Order Ambisonics (NFC-HOA) ======== +% Settings for NFC-HOA, see Ahrens (2012) for an introduction +% +% Highest order used with NFC-HOA. If this is set to [], band-limited NFC-HOA is +% used and the order is set by nfchoa_order() which returns the highest order +% for which no aliasing occurs. +conf.nfchoa.order = []; % integer + + +%% ===== Local Wave Field Synthesis (LWFS) =============================== +% Settings for Local WFS +% +% === Local Wave Field Synthesis using Virtual Secondary Sources (LWFS-VSS) +% See Spors and Ahrens (2010b) for an introduction. +% +% Method the virtual secondary sources should be driven +conf.localwfs_vss.method = 'wfs'; % 'wfs' or 'nfchoa' +% WFS settings for virtual secondary sources +conf.localwfs_vss.wfs = conf.wfs; +% Tapering of virtual secondary sources (only applied for WFS) +conf.localwfs_vss.usetapwin = false; % boolean +conf.localwfs_vss.tapwinlen = 0.5; % 0..1 +% NFC-HOA settings for virtual secondary sources +conf.localwfs_vss.nfchoa = conf.nfchoa; +% Virtual secondary sources (see also: conf.secondary_sources) +conf.localwfs_vss.size = 0.4; % / m +conf.localwfs_vss.center = [0, 0, 0]; % / m +conf.localwfs_vss.geometry = 'circular'; % string +conf.localwfs_vss.number = 56; % integer +conf.localwfs_vss.grid = 'equally_spaced_points'; % string +% Driving function for virtual secondary sources +conf.localwfs_vss.driving_functions = 'default'; % string +% Linear VSS distribution: rotate the distribution orthogonal to the progation +% direction of the desired sound source. +% Circular VSS distribution: truncate the distribution to a circular arc +% which satisfies the secondary source selection criterions (source normal +% aligns with propagation directions of desired sound source). +conf.localwfs_vss.consider_target_field = true; % boolean +% VSS distribution is further truncated if parts of it cannot be correctly +% reproduced, because they lie outside the area which is surrounded by the real +% loudspeakers (secondary sources) +conf.localwfs_vss.consider_secondary_sources = true; % boolean +% +% === Local Wave Field Synthesis using Spatial Bandwidth Limitation (LWFS-SBL) +% See Hahn et al. (2016) for an introduction. +% The centre of the local synthesis region is set by conf.xref +% +% Maximum modal order aka. spatial bandwidth of desired sound field. If left +% empty, the value is set by nfchoa_order(), which may suboptimal depending on +% the geometry, e.g. number of secondary sources and shape of the secondary +% source distribution. +conf.localwfs_sbl.order = []; % integer +% Due to stability issues for the time-domain implementation of synthesis +% of a point source, conventional WFS has to be used for the low frequencies. +% fc defines the crossover frequency between the WFS and LWFS-SBL. If left +% empty, this frequency is estimated by aliasing_frequency(). +conf.localwfs_sbl.fc = []; % float +% The spatially bandwidth-limited sound field is converted into plane wave +% decomposition which is then synthesised using conventional WFS for each +% individual plane wave. Npw defines the number of plane waves with their +% directions distributed equi-angularly on the unit circle. If left empty, +% it is estimated based on the sampling frequency and size of the secondary +% source distribution. +conf.localwfs_sbl.Npw = []; % integer + + +%% ===== Binaural reproduction =========================================== +% Settings regarding all the stuff with impulse responses from the SFS_ir and +% SFS_binaural_synthesis folders +% +% Use interpolation to get the desired HRTF or BRIR for binaural simulation. +% If this is disabled, the HRTF/BRIR returned by a nearest neighbour search is +% used instead. +conf.ir.useinterpolation = true; % boolean +% You can choose the way the points for interpolation are selected. Depending on +% the geometry of the measured HRTF/BRIR data set and the interpolation method, +% a different number of HRTFs are selected for interpolation. See validation +% script test_interpolation_point_selection.m for examples. Available methods: +% 'nearestneighbour' - Interpolation between nearest neighbours. This only +% works for interpolation points on a circle in the +% horizontal plane. +% 'delaunay' - Interpolation between surrounding points according to +% Delaunay triangulation. This only works for +% interpolation points on a sphere. +% 'voronoi' - For spherical Voronoi interpolation, all coordinates +% are projected on the unit sphere. Voronoi regions +% (including their area) on the sphere are calculated +% for all measured positions included in the HRTF/BRIR +% data set. The query position is added to the point +% cloud and the regions are calculated, again. +% The weights result from the area "stolen" by the query +% position from each of the other coordinates +conf.ir.interpolationpointselection = 'nearestneighbour'; +% You can choose between the following interpolation methods: +% 'simple' - Interpolation in the time domain performed samplewise. This +% does not heed the times of arrival of the impulse responses. +% 'freqdomain' - Interpolation in the frequency domain performed separately +% for magnitude and phase. +% This method cannot work properly if there is too much noise in +% the phase information at low frequencies which is often the +% case for measured HRTFs. Low frequencies can be corrected +% according to theory, see e.g. the corrected KEMAR HRTFs published +% at https://github.com/spatialaudio/lf-corrected-kemar-hrtfs. +% The implementation of this method suffers from circular shifting, +% see test_interpolation_methods.m in the validation folder. For +% typical HRIRs with leading and trailing zeros, the error is +% negligible. +% 'timedomain' - Interpolation in the time domain with cross-correlation for +% estimation of time of arrival (TOA) differences. +conf.ir.interpolationmethod = 'simple'; +% +% If you have HRIRs in the form of the SimpleFreeFieldHRIR SOFA convention, zeros +% are padded at the beginning of every impulse response corresponding to their +% measurement distance. If you know that your measured HRIRs already have a +% given pre-delay, add the pre-delay here and accordingly less zero padding will +% be applied. In this case you can lose samples from the beginning of the +% impulse response. If you are not sure, choose a value of 0. +conf.ir.hrirpredelay = 0; % / samples +% +% === Headphone compensation === +% Headphone compensation +conf.ir.usehcomp = false; % boolean +% Headphone compensation file for left and right ear. +conf.ir.hcompfile = 'data/headphone_compensation/QU_KEMAR_AKGK601_hcomp.wav'; % string +% +% === SoundScape Renderer === +% To use a dynamic binaural simulation together with the SoundScape Renderer +% (SSR) and a headtracker, brs sets can be created. If these sets should be +% used in BRS mode of the SSR, the angles have to be: +% conf.ir.brsangles = 0:1:359; +% If the brs set should be used as IRs for the SSR, the angles have to be: +% conf.ir.brsangles = 360:-1:1; +conf.ir.brsangles = 0:1:359; % / degree + + +%% ===== Plotting ======================================================== +% Plot the results (sound fields etc.) directly +conf.plot.useplot = false; % boolean +% Normalize the sound field for plotting +conf.plot.usenormalisation = true; % boolean +% Normalisation method. Available methods are: +% 'auto' - 'center' if center of sound field > 0.3, otherwise 'max' +% 'center' - center of sound field == 1 +% 'max' - max of sound field == 1 +conf.plot.normalisation = 'auto'; % string +% Plot mode (uses the GraphDefaults function). Available modes are: +% 'monitor' - displays the plot on the monitor +% 'paper' - eps output in conf.plot.outfile +% 'png' - png output in conf.plot.outfile +conf.plot.mode = 'monitor'; % string +% Plot amplitudes in dB (e.g. sound field plots) +conf.plot.usedb = false; % boolean +% caxis settings (leave blank, if you would use the default values of the given +% plot function) +conf.plot.caxis = []; % [min max] +% Default colormap to use +% The Toolbox comes with two own color maps, if you set 'default' or 'moreland' +% you will get a blue/red-colormap after +% http://www.kennethmoreland.com/color-advice/ +% If you set 'gray' or 'grey' you will get a colormap ranging from white to +% black. In addition you can add every other map you can specify in +% Matlab/Octave. For example to get the Matlab default colormap set 'parula'. +conf.plot.colormap = 'default'; % string +% Plot loudspeakers in the sound field plots +conf.plot.loudspeakers = true; % boolean +% Use real loudspeakers symbols (otherwise crosses are used) +conf.plot.realloudspeakers = false; % boolean +% Size of the loudspeaker +conf.plot.lssize = 0.16; % m +% Size of the plot +conf.plot.size_unit = 'px'; % 'px','cm','inches' +conf.plot.size = [540 404]; % [xsize ysize] +% Resolution of plot in dpi +conf.plot.resolution = 150; % integer +% Additional plot command +conf.plot.cmd = ''; % string +% output of plot (file or screen) +conf.plot.usefile = false; % boolean +% File name, if this is provided with as *.png or *.eps file, the figure is +% plotted to the regarding file +conf.plot.file = ''; % string + + +%% ===== References ====================================================== +% +% Ahrens (2012) - "Analytic Methods of Sound Field Synthesis", Springer, +% https://doi.org/10.1007/978-3-642-25743-8 +% +% Ahrens and Spors (2010) - "Sound Field Reproduction Using Planar and Linear +% Arrays of Loudspeakers", Transactions on Audio, Speech, and Language +% Processing, vol. 18, no. 8, pp. 2038-2050, +% https://doi.org/10.1109/TASL.2010.2041106 +% +% Born and Wolf (1999) - "Principles of Optics", Cambridge University Press, +% 7th edition, ISBN 9780521642224 +% +% Hahn, Winter, Spors (2016) - "Local Wave Field Synthesis by Spatial +% Band-limitation in the Circular/Spherical Harmonics Domain", 140th +% Convention of the Audio Engineering Society, Paper 9596, +% http://www.aes.org/e-lib/browse.cfm?elib=18294 +% +% Spors and Ahrens (2010a) - "Analysis and Improvement of Pre-Equalization in +% 2.5-Dimensional Wave Field Synthesis", 128th Convention of the Audio +% Engineering Society, Paper 8121, +% http://www.aes.org/e-lib/browse.cfm?elib=15418 +% +% Spors and Ahrens (2010b) - "Local Sound Field Synthesis by Virtual Secondary +% Sources", 40th Conference of the Audio Engineering Society, Paper 6-3, +% http://www.aes.org/e-lib/browse.cfm?elib=15561 +% +% Spors, Rabenstein, Ahrens (2008) - "The Theory of Wave Field Synthesis +% Revisited," 124th Convention of the Audio Engineering Society, Paper 7358, +% http://www.aes.org/e-lib/browse.cfm?elib=14488 +% +% Wierstorf (2014) - "Perceptual Assessment of Sound Field Synthesis", +% TU Berlin, https://doi.org/10.14279/depositonce-4310 +% +% Winter and Spors (2016) - "On fractional delay interpolation for local wave +% field synthesis", 24th European Signal Processing Conference (EUSIPCO), +% pp. 2415-2419, https://doi.org/10.1109/EUSIPCO.2016.7760682 diff --git a/SFS_config_example.m b/SFS_config_example.m deleted file mode 100644 index 1c9bd482..00000000 --- a/SFS_config_example.m +++ /dev/null @@ -1,364 +0,0 @@ -function conf = SFS_config() -%SFS_CONFIG Configuration file for the SoundFieldSynthesis functions -% -% Usage: conf = SFS_config -% -% Output parameters: -% conf - struct containing all configuration variables -% -% SFS_CONFIG() creates the struct conf containing the default -% configuration values. If you want to create other entries, please set -% them in your script (e.g. conf.fs = 48000) and pass the conf struct to -% the desired function as last input (e.g. tapering_window(x0,conf)). -% -% So edit this function only, if the default values have changed! -% -% see also: SFS_start - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 0; -nargmax = 0; -narginchk(nargmin,nargmax); - - -%% ===== Configuration default values =================================== - -% ===== Table of Content ======================== -% -% - Misc -% - Audio -% - Simulations -% - Secondary Sources -% - Binaural Reproduction -% * Headphone compensation -% * HRIR/BRIR -% * Auralization -% - WFS -% * Pre-equalization -% * Tapering -% * Virtual Sources -% - SDM -% - HOA -% - Plotting -% * Gnuplot -% - - -%% ===== Misc ============================================================ -conf.tmpdir = '/tmp/sfs'; % string -% Debugging level. We are supporting 3 levels: -% 0 - normal mode -% 1 - debug modus, showing interim results and plots -conf.debug = 0; % 0 or 1 -% Show a progress bar in the loops (for example sound_field_mono). This can be -% useful if you are using secondary sources with >1000 loudspeakers -conf.showprogress = false; % boolean - - -%% ===== Audio =========================================================== -% Audio and signal processing settings -% -% Samplingrate -conf.fs = 44100; % / Hz -% Speed of sound -conf.c = 343; % / m/s -% use fractional delays for delay lines -conf.usefracdelay = false; % boolean -conf.fracdelay_method = 'resample'; % string -% Bandpass filter applied in sound_field_imp() -conf.usebandpass = true; % boolean -conf.bandpassflow = 10; % / Hz -conf.bandpassfhigh = 20000; % / Hz - - -%% ===== Sound Field Synthesis (SFS) ===================================== -% Common sound field synthesis settings -% -% === Dimensionality === -% Dimensionality of the secondary sources and the sound field synthesis driving -% functions: -% '2D' - line sources as secondary sources, arranged in a circle, line, ... -% '2.5D' - point sources as secondary sources, arranged in a circle, line, ... -% '3D' - point sources as secondary sources, arranged in a sphere, plane, ... -conf.dimension = '2.5D'; % string -% -% === Driving functions === -% Implementation of driving functions. For the default ones use 'default'. These -% functions are described in the PDF documentation, in the doc folder of the -% SFS-Toolbox. For possible other flags have a look into the driving functions. -% Most users can safely use the 'default' flag here. -conf.driving_functions = 'default'; % string -% -% === Impulse responses === -% Length of impulse responses used in the time domain driving functions -% and for the creation of the binaural simulations. -% Don't worry, SFS checks for you if conf.N is large enough) -conf.N = 2048; % samples -% -% === 2.5D === -% The amplitude will be correct at the point xref for 2.5D -% synthesis. -% This point is also used to scale the sound field to 1 at this point. -conf.xref = [0 0 0]; % / m -% -% === Tapering === -% The truncation of the loudspeaker array leads to diffraction of the -% synthesized sound field. It has been shown that the truncation can be discribed -% by cylindrical waves originating from the edges of the array -% [Young,Sommerfeld,Rubinovitch]. Therefore a good method to reduce artifacts -% due to the diffraction edge waves is to fade out the amplitude of the driving -% function at the edges of the array. This method is called tapering and -% implemented using a Hanning window. -% Use tapering window -conf.usetapwin = true; % boolean -% Size of the tapering window -conf.tapwinlen = 0.3; % / percent of array length, 0..1 - - -%% ===== Sound Field Simulations ========================================= -% Simulations of monochromatic or time domain sound field -% -% xyz-resolution for sound field simulations, this value is applied along every -% desired dimension, expect if only one point is desired -conf.resolution = 300; % / samples -% Phase of omega of sound field (change this value to create monochromatic sound -% fields with different phases, for example this can be useful to create a movie) -conf.phase = 0; % / rad -% normalize the simulated sound field? -conf.usenormalisation = true; % boolean - - -% ===== Secondary Sources ================================================ -% Settings of the used loudspeaker array -% -% Number of secondary sources -conf.secondary_sources.number = 64; % integer -% Diameter/Length of secondary source array -conf.secondary_sources.size = 3; % / m -% Center of array, X0 -conf.secondary_sources.center = [0 0 0]; % / m -% Array geometry -% Possible values are: 'line', 'box', 'circle', 'sphere' -conf.secondary_sources.geometry = 'circle'; % string -% Vector containing custom secondary source positions and directions. -% conf.secondary_sources.x0 = [x0; y0; z0; nx0; ny0; nz0; weight]; -conf.secondary_sources.x0 = []; % / m -% Grid for the spherical array. Note, that you have to download and install the -% spherical grids from an additiona source. For available grids see: -% http://github.com/sfstoolbox/data/tree/master/spherical_grids -% An exception are Gauss grids, which are available via 'gauss' and will be -% calculated on the fly allowing very high number of secondary sources. -conf.secondary_sources.grid = 'equally_spaced_points'; % string - - -%% ===== Wave Field Synthesis (WFS) ====================================== -% Settings for WFS, see Spors et al. (2008) for an introduction -% -% === Pre-Equalization === -% WFS can be implemented very efficiently using a delay-line with different -% amplitudes and convolving the whole signal once with the so called -% pre-equalization filter [References]. If we have aliasing in our system we -% only want to use the pre-equalization filter until the aliasing frequency, -% because of the energy the aliasing is adding to the spectrum above this -% frequency (which means the frequency response over the aliasing frequency is -% allready "correct") [Reference] -% Use WFS preequalization-filter -conf.wfs.usehpre = true; % boolean -% FIR or IIR pre-equalization filter -% NOTE: only FIR is working under octave at the moment -conf.wfs.hpretype = 'FIR'; % 'FIR' or 'IIR' -% Lower frequency limit of preequalization filter (~ frequency when -% subwoofer is active) -conf.wfs.hpreflow = 50; % / Hz -% Upper frequency limit of preequalization filter (~ aliasing frequency of -% system) -conf.wfs.hprefhigh = 1200; % / Hz -% IIR bandwidth for the Lagrange interpolation region -conf.wfs.hpreBandwidth_in_Oct = 2; % / octaves -% desired IIR filter order -conf.wfs.hpreIIRorder = 4; % integer - - -%% ===== Spectral Division Method (SDM) ================================== -% Settings for SDM, see Ahrens, Spors (2010) for an introduction -% -% Use the evanescent part of the driving function for SDM -conf.sdm.withev = true; % boolean - - -%% ===== Near-Field Compensated Higher Order Ambisonics (NFC-HOA) ======== -% Settings for NFCF-HOA, see Ahrens (2012) fro an introduction -% -% normally the order of NFC-HOA is set by the nfchoa_order() function which -% returns the highest order for which no aliasing occurs. If you wish to use -% another order you can set it manually here, otherwise leave it blank -conf.nfchoa.order = []; % integer - - -%% ===== Local Sound Field Synthesis ===================================== -% Settings for Local SFS, see Spors, Ahrens (2010) for an introduction -% -% Method the virtual secondary sources should be driven -conf.localsfs.method = 'wfs'; % 'wfs' or 'nfchoa' -conf.localsfs.usetapwin = false; % boolean -conf.localsfs.tapwinlen = 0.5; % 0..1 -% WFS settings -conf.localsfs.wfs = conf.wfs; -% Virtual secondary sources (vss) -conf.localsfs.vss.size = 0.4; -conf.localsfs.vss.center = [0, 0, 0]; -conf.localsfs.vss.geometry = 'circular'; -conf.localsfs.vss.number = 56; -conf.localsfs.vss.grid = 'equally_spaced_points'; -% -% linear vss distribution: rotate the distribution orthogonal to the progation -% direction of the desired sound source -% circular vss distribution: truncate the distribution to a circular arc -% which satisfies the secondary source selection criterions ( source normal -% aligns with propagation directions of desired sound source ) -conf.localsfs.vss.consider_target_field = true; -% -% vss distribution is further truncated if parts of it cannot be correctly -% reproduced, because they lie outside the area which is surrounded by the real -% loudspeakers (secondary sources) -conf.localsfs.vss.consider_secondary_sources = true; - - -%% ===== Binaural reproduction =========================================== -% Settings regarding all the stuff with impulse responses from the SFS_ir and -% SFS_binaural_synthesis folders -% -% Directory containing HRTF data bases, you want to use. Note, that also all -% subdirectories will be added to the path. This is not done automatically, but -% by calling addirspath; -% If you have more than one path, seperate them by : -conf.ir.path = '~/git/sfs/data/HRTFs:~/svn/ir_databases:~/svn/measurements'; % string -% -% If we load an HRTF data set we are most likely interested to modify its -% existing length, to enable a delaying of the impulse responses without -% problems. If these value is set to "false", zeros are padded at the -% beginning of all HRTFs corresponding to the maximum distance of the whole -% set. In addition the overall length of the impulse responses is set to -% conf.N. This is applied directly if you load a HRTF set with read_irs(). -% Only set this to true if you really know what you are doing. -conf.ir.useoriglength = false; % boolean -% -% Use interpolation to get the desired HRTF for binaural simulation. If this is -% disabled the HRTF returned by a nearest neighbour search is used instead. -% Depending on the geometry of the measured HRTF data set, the interpolation -% will be done between the two or three nearest HRTFs. -conf.ir.useinterpolation = true; % boolean -% -% === Headphone compensation === -% Headphone compensation -conf.ir.usehcomp = true; % boolean -% Headphone compensation file for left and right ear. -conf.ir.hcompfile = 'data/headphone_compensation/QU_KEMAR_AKGK601_hcomp.wav'; % string -% -% === Auralisation === -% These files are used for the auralization of impulse responses by the -% auralize_ir() function. -% NOTE: you have to provide them by yourself! -conf.ir.speechfile = ''; % string -conf.ir.cellofile = ''; % string -conf.ir.castanetsfile = ''; % string -conf.ir.noisefile = ''; % string -conf.ir.pinknoisefile = ''; % string -% -% === SoundScape Renderer === -% To use a dynamic binaural simulation together with the SoundScape Renderer -% (SSR) and a headtracker, brs sets can be created. If these sets should be -% used in BRS mode of the SSR, the angles have to be: -% conf.ir.brsangles = 0:1:359; -% If the brs set should be used as IRs for the SSR, the angles have to be: -% conf.ir.brsangles = 360:-1:1; -conf.ir.brsangles = 0:1:359; % / degree - - -%% ===== Plotting ======================================================== -% Plot the results (sound fields etc.) directly -conf.plot.useplot = false; % boolean -% Plot mode (uses the GraphDefaults function). Avaiable modes are: -% 'monitor' - displays the plot on the monitor -% 'paper' - eps output in conf.plot.outfile -% 'png' - png output in conf.plot.outfile -conf.plot.mode = 'monitor'; % string -% Plot amplitudes in dB (e.g. sound field plots) -conf.plot.usedb = false; % boolean -% caxis settings (leave blank, if you would use the default values of the given -% plot function) -conf.plot.caxis = []; % [min max] -% Default colormap to use -% The Toolbox comes with two own color maps, if you set 'default' or 'moreland' -% you will get a blue/red-colormap after -% http://www.sandia.gov/~kmorel/documents/ColorMaps/ -% If you set 'gray' or 'grey' you will get a colormap ranging from white to -% black. In addition you can add every other map you can specify in -% Matlab/Octave. For example to get the Matlab default colormap ser 'jet'. -conf.plot.colormap = 'default'; % string -% Plot loudspeakers in the sound field plots -conf.plot.loudspeakers = true; % boolean -% Use real loudspeakers symbols (otherwise crosses are used) -conf.plot.realloudspeakers = false; % boolean -% Size of the loudspeaker -conf.plot.lssize = 0.16; % m -% Size of the plot -conf.plot.size_unit = 'px'; % 'px','cm','inches' -conf.plot.size = [540 404]; % [xsize ysize] -% Resolution of plot in dpi -conf.plot.resolution = 150; % integer -% Additional plot command -conf.plot.cmd = ''; % string -% output of plot (file or screen) -conf.plot.usefile = false; % boolean -% File name, if this is provided with as *.png or *.eps file, the figure is -% plotted to the regarding file -conf.plot.file = ''; % string - - -%% ===== References ====================================================== -% -% Spors, Rabenstein, Ahrens - The Theory of Wave Field Synthesis Revisited, 124 -% AES Convention, Paper 7358, 2008. http://bit.ly/ZCvyQ6 -% -% Ahrens, Spors - Sound Field Reproduction Using Planar and Linear Arrays of -% Loudspeakers, Transactions on Audio, Speech, and Language Processing, p. -% 2038-50, 2010. http://bit.ly/10dpA9r -% -% Spors, Ahrens - Local Sound Field Synthesis by Virtual Secondary Sources, 40 -% AES Conference, Paper 6-3, 2010. http://bit.ly/1t3842v -% -% Ahrens - Analytic Methods of Sound Field Synthesis. Springer, 2012. diff --git a/SFS_general/aliasing_frequency.m b/SFS_general/aliasing_frequency.m index 27a3007c..b51fbd91 100644 --- a/SFS_general/aliasing_frequency.m +++ b/SFS_general/aliasing_frequency.m @@ -1,14 +1,13 @@ function [fal,dx0] = aliasing_frequency(x0,conf) -%ALIASING_FREQUENCY returns the aliasing frequency for the given secondary -%sources +%ALIASING_FREQUENCY aliasing frequency for the given secondary sources % -% Usage: [fal,dx0] = aliasing_frequency([x0],[conf]) +% Usage: [fal,dx0] = aliasing_frequency([x0],conf) % -% Input options: +% Input parameters: % x0 - secondary sources / m -% conf - optional configuration struct (see SFS_config) +% conf - configuration struct (see SFS_config) % -% Output options: +% Output parameters: % fal - aliasing frequency / Hz % dx0 - mean distance between secondary sources / m % @@ -20,62 +19,58 @@ % For a calculation that includes the dependency on the listener position have % a look at Start (1997). % -% References: -% S. Spors and J. Ahrens (2009) - "Spatial sampling artifacts of wave field -% synthesis for the reproduction of virtual point sources", 126th AES Conv. -% E. Start (1997) - "Direct Sound Enhancement by Wave Field Synthesis", -% TU Delft. -% % See also: sound_field_mono_wfs, secondary_source_positions, % secondary_source_distance +% +% References: +% Spors and Ahrens (2009) - "Spatial sampling artifacts of wave field +% synthesis for the reproduction of virtual point sources", 126th +% Convention of the Audio Engineering Society, Paper 7744, +% http://www.aes.org/e-lib/browse.cfm?elib=14940 +% +% Start (1997) - "Direct Sound Enhancement by Wave Field Synthesis", +% PhD thesis, TU Delft, +% http://resolver.tudelft.nl/uuid:c80d5b58-67d3-4d84-9e73-390cd30bde0d %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ==================================== -nargmin = 0; +nargmin = 1; nargmax = 2; narginchk(nargmin,nargmax); -if nargin==nargmax-1 - if isstruct(x0) - conf = x0; - x0 = []; - else - conf = SFS_config; - end -elseif nargin==nargmax-2 - conf = SFS_config; +if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input parameters ======================================= -nargmin = 3; -nargmax = 3; -narginchk(nargmin,nargmax); -isargpositivescalar(n) -isargscalar(m) -isargnumeric(arg) -if n. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters =================================== -isargvector(varargin{:}); - - -%% ===== Computation ===================================================== -for ii = 1:nargin - vec = row_vector(varargin{ii}); - if size(vec,2)<2 - varargout{ii} = [vec vec]; - else - varargout{ii} = vec; - end -end diff --git a/SFS_general/bandpass.m b/SFS_general/bandpass.m index fa5c8631..28850e9e 100644 --- a/SFS_general/bandpass.m +++ b/SFS_general/bandpass.m @@ -1,83 +1,73 @@ -function sig = bandpass(sig,flow,fhigh,conf) -%BANDPASS filters a signal by a bandpass -% -% Usage: sig = bandpass(sig,flow,fhigh,[conf]) -% -% Input parameters: -% sig - input signal (matrix) -% flow - start frequency of bandpass -% fhigh - stop frequency of bandpass -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% sig - filtered signal -% -% BANDPASS(sig,flow,fhigh) filters the given signal with a bandpass filter -% with cutoff frequencies of flow and fhigh. -% -% See also: sound_field_imp_wfs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargmatrix(sig); -isargpositivescalar(flow,fhigh); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input parameters ======================================= -nargmin = 1; -nargmax = 2; -narginchk(nargmin,nargmax); -isargmatrix(sos); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ==================================== -nargmin = 2; -nargmax = 2; -narginchk(nargmin,nargmax); -isargmatrix(P); -isargscalar(t); - - -%% ===== Computation ===================================================== -if length(P)==1, return; end -% -if max(abs(P(:)))==0 || all(isnan(P(:))) - warning('SFS:check_sound_field',... - ['The activity in the simulated sound field is zero. ',... - 'Maybe you should use another time frame t than %i. '],t); -end diff --git a/SFS_general/cm2in.m b/SFS_general/cm2in.m index 4c09d456..176ac10e 100644 --- a/SFS_general/cm2in.m +++ b/SFS_general/cm2in.m @@ -3,46 +3,41 @@ % % Usage: y = cm2in(x) % -% Input options: +% Input parameters: % x - input / cm % -% Output options: +% Output parameters: % y - output / inches % -% CM2IN(x) returns the given value x in inches. -% % See also: cm2px, px2in, px2cm, in2cm, in2px %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_general/cm2px.m b/SFS_general/cm2px.m index f71fa079..53d2a07f 100644 --- a/SFS_general/cm2px.m +++ b/SFS_general/cm2px.m @@ -3,46 +3,41 @@ % % Usage: y = cm2px(x) % -% Input options: +% Input parameters: % x - input / cm % -% Output options: +% Output parameters: % y - output / px % -% CM2PX(x) returns the given value x in pixels. -% % See also: cm2in, px2in, px2cm, in2cm, in2px %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_general/column_vector.m b/SFS_general/column_vector.m index 46de2a92..59ac584f 100644 --- a/SFS_general/column_vector.m +++ b/SFS_general/column_vector.m @@ -1,61 +1,55 @@ -function varargout = column_vector(varargin) -%COLUMN_VECTOR makes a column vector from the given vector -% -% Usage: [x1,x2,...] = column_vector(x1,x2,...) -% -% Input parameters: -% x1,x2,... - one or more vectors -% -% Output parameters: -% x1,x2,... - input vectors as column vectors -% -% COLUMN_VECTOR(x1,x2,...) returns the given vectors x1,x2,... as column -% vectors. -% -% See also: row_vector - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters =================================== -isargvector(varargin{:}); - - -%% ===== Computation ===================================================== -for ii = 1:nargin - if size(varargin{ii},2)>size(varargin{ii},1) - varargout{ii} = varargin{ii}'; - else - varargout{ii} = varargin{ii}; - end -end +function varargout = column_vector(varargin) +%COLUMN_VECTOR returns the given vectors as column vectors +% +% Usage: [x1,x2,...] = column_vector(x1,x2,...) +% +% Input parameters: +% x1,x2,... - one or more vectors +% +% Output parameters: +% x1,x2,... - input vectors as column vectors +% +% See also: row_vector + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters =================================== +isargvector(varargin{:}); + + +%% ===== Computation ===================================================== +for ii = 1:nargin + if size(varargin{ii},2)>size(varargin{ii},1) + varargout{ii} = varargin{ii}'; + else + varargout{ii} = varargin{ii}; + end +end diff --git a/SFS_general/convolution.m b/SFS_general/convolution.m index 5fb3ceeb..df9b47f1 100644 --- a/SFS_general/convolution.m +++ b/SFS_general/convolution.m @@ -1,84 +1,75 @@ -function z = convolution(x,y) -%CONVOLUTION convolves the signals x and y -% -% Usage: z = convolution(x,y) -% -% Input parameters: -% x - matrix/vector with signals as columns -% y - matrix/vector with signals as columns, note that only one of -% the signals can be a matrix -% -% Output parameters: -% z - convolved signal -% -% CONVOLUTION(x,y) convolves the signals given with x and y. One of the input -% signals can be a matrix containing the signals as column vectors, the other -% one has to be a column vector. The convolution is done in the frequency -% domain and it is checked if we have only real signals to speed up the -% calculation. The length of z is length(x)+length(y)-1. -% -% See also: fft_real, ifft_real, fft, ifft - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input parameters ======================================= -nargmin = 2; -nargmax = 2; -narginchk(nargmin,nargmax); -isargmatrix(x,y); -% Check if only one of the inputs is a matrix -if all(size(x)>1) && all(size(y)>1) - error('%s: Only one of the inputs can be multi-dimensional.', ... - upper(mfilename)); -end -% Ensure column vectors -if ~all(size(x)>1), x=column_vector(x); end -if ~all(size(y)>1), y=column_vector(y); end - - -%% ===== Computation ===================================================== -% If one of the input signals is a matrix repmat the vector of the other signal -if all(size(x)>1) - y = repmat(y,1,size(x,2)); -elseif all(size(y)>1) - x = repmat(x,1,size(y,2)); -end -% Length of output signal -N = size(x,1)+size(y,1)-1; -% Convolve the signals in frequency domain -if isreal(x) && isreal(y) - z = ifft_real(fft_real(fix_length(x,N)).*fft_real(fix_length(y,N)),N); -else - z = ifft(fft(fix_length(x,N)).*fft(fix_length(y,N))); -end +function z = convolution(x,y) +%CONVOLUTION convolves the signals x and y +% +% Usage: z = convolution(x,y) +% +% Input parameters: +% x - matrix/vector with signals as columns +% y - matrix/vector with signals as columns +% +% Output parameters: +% z - convolved signal +% +% CONVOLUTION(x,y) convolves the signals given with x and y. If both input +% signals are matrices, they must contain the same number of signals (columns). +% The convolution is done in the frequency domain and it is checked if we have +% only real signals to speed up the calculation. The length of z is +% length(x)+length(y)-1. +% +% See also: fft, ifft + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking input parameters ======================================= +nargmin = 2; +nargmax = 2; +narginchk(nargmin,nargmax); +isargmatrix(x,y); +% Ensure column vectors +if ~all(size(x)>1), x=x(:); end +if ~all(size(y)>1), y=y(:); end +% If the inputs are two matrices, check if the number of signals is the same +if size(x,2)>1 && size(y,2)>1 && size(x,2)~=size(y,2) + error(['%s: Two input matrices must have the same number of signals '... + '(columns).'],upper(mfilename)); +end + +%% ===== Computation ===================================================== +% Length of output signal +N = size(x,1)+size(y,1)-1; +% FFT + multiplication +Z = bsxfun(@times,fft(x,N,1),fft(y,N,1)); % automatically adjusts sizes +% IFFT +if isreal(x) && isreal(y) + z = real(ifft(Z,[],1)); +else + z = ifft(Z,[],1); +end diff --git a/SFS_general/correct_azimuth.m b/SFS_general/correct_azimuth.m index dcf23ef2..6b5c8c23 100644 --- a/SFS_general/correct_azimuth.m +++ b/SFS_general/correct_azimuth.m @@ -1,61 +1,55 @@ -function phi = correct_azimuth(phi) -%CORRECT_AZIMUTH ensures correct values for azimuth angles -% -% Usage: phi = correct_azimuth(phi) -% -% Input parameters: -% phi - azimuth / rad. Can be a single value or a matrix. -% -% Output paramteres: -% phi - angle between -pi and +pi-eps / rad -% -% CORRECT_AZIMUTH(phi) returns a value for azimuth phi between -% -pi and +pi-eps. -% -% See also: correct_elevation, read_irs, get_ir - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 1; -narginchk(nargmin,nargmax); - - -%% ===== Computation ==================================================== -% Ensure -2pi <= phi <= 2pi -phi = rem(phi,2*pi); -% Ensure -pi <= phi < pi -phi(phi<-pi) = phi(phi<-pi) + 2*pi; -phi(phi>=pi) = phi(phi>=pi) - 2*pi; +function phi = correct_azimuth(phi) +%CORRECT_AZIMUTH ensures azimuth angle between -pi and +pi-eps +% +% Usage: phi = correct_azimuth(phi) +% +% Input parameters: +% phi - azimuth / rad. Can be a single value or a matrix. +% +% Output paramteres: +% phi - angle between -pi and +pi-eps / rad +% +% See also: correct_elevation, get_ir + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Computation ==================================================== +% Ensure -2pi <= phi <= 2pi +phi = rem(phi,2*pi); +% Ensure -pi <= phi < pi +phi(phi<-pi) = phi(phi<-pi) + 2*pi; +phi(phi>=pi) = phi(phi>=pi) - 2*pi; diff --git a/SFS_general/correct_elevation.m b/SFS_general/correct_elevation.m index a1d7412c..73c668c2 100644 --- a/SFS_general/correct_elevation.m +++ b/SFS_general/correct_elevation.m @@ -1,61 +1,55 @@ -function delta = correct_elevation(delta) -%CORRECT_ELEVATION ensures correct values for elevation angles -% -% Usage: delta = correct_elevation(delta) -% -% Input parameters: -% delta - elevation / rad. Can be a single value or a matrix. -% -% Output paramteres: -% delta - angle between -pi/2 and +pi/2 / rad -% -% CORRECT_ELEVATION(delta) returns a value for elevation delta between -% -pi/2 and pi/2. -% -% See also: correct_azimuth, read_irs, get_ir - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 1; -narginchk(nargmin,nargmax); - - -%% ===== Computation ==================================================== -% Ensure -pi <= delta <= pi -delta = correct_azimuth(delta); -% Ensure -pi/2 <= delta <= pi/2 -delta(delta<-pi/2) = -delta(delta<-pi/2) - pi; -delta(delta>pi/2) = -delta(delta>pi/2) + pi; +function delta = correct_elevation(delta) +%CORRECT_ELEVATION ensures elevation angle between -pi/2 and pi/2 +% +% Usage: delta = correct_elevation(delta) +% +% Input parameters: +% delta - elevation / rad. Can be a single value or a matrix. +% +% Output paramteres: +% delta - angle between -pi/2 and +pi/2 / rad +% +% See also: correct_azimuth, get_ir + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Computation ==================================================== +% Ensure -pi <= delta <= pi +delta = correct_azimuth(delta); +% Ensure -pi/2 <= delta <= pi/2 +delta(delta<-pi/2) = -delta(delta<-pi/2) - pi; +delta(delta>pi/2) = -delta(delta>pi/2) + pi; diff --git a/SFS_general/deg.m b/SFS_general/deg.m index 4c948d35..87f830ba 100644 --- a/SFS_general/deg.m +++ b/SFS_general/deg.m @@ -1,48 +1,43 @@ function phi = deg(phi) -%DEG returns the given angle in deg +%DEG angle in deg % % Usage: phi = deg(phi) % -% Input options: +% Input parameters: % phi - angle / rad, can be a scalar or matrix (rad) % -% Output options: +% Output parameters: % phi - angle / degree % -% DEG(phi) returns the given angles phi in degree. -% % See also: rad %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_general/delayline.m b/SFS_general/delayline.m index b3918552..bc464408 100644 --- a/SFS_general/delayline.m +++ b/SFS_general/delayline.m @@ -1,121 +1,243 @@ -function sig = delayline(sig,dt,weight,conf) -%DELAYLINE implements a (fractional) delay line with weights -% -% Usage: sig = delayline(sig,dt,weight,[conf]) -% -% Input parameter: -% sig - input signal (vector) -% dt - delay / samples -% weight - amplitude weighting factor -% conf - mandatory configuration struct (see SFS_config) -% -% Output parameter: -% sig - delayed signal -% -% DELAYLINE(sig,dt,weight,conf) implementes a delayline, that delays the given -% signal by dt samples and applies a amplitude weighting factor. -% The delay is implemented as integer delays or a fractional delay -% filter, see SFS_config. -% -% See also: get_ir, driving_function_imp_wfs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Configuration ================================================== -usefracdelay = conf.usefracdelay; - - -%% ===== Computation ===================================================== -samples = size(sig,1); -channels = size(sig,2); -if channels>1 && length(dt)==1, dt=repmat(dt,[1 channels]); end -if channels>1 && length(weight)==1, weight=repmat(weight,[1 channels]); end - - -if usefracdelay - - % Additional configuration - fracdelay_method = conf.fracdelay_method; - rfactor = 100; % resample factor (1/stepsize of fractional delays) - Lls = 30; % length of least-squares factional delay filter - - % Defining a temporary conf struct for recursive calling of delayline - conf2.usefracdelay = false; - conf2.fracdelay_method = ''; - - switch fracdelay_method - case 'resample' - sig2 = resample(sig,rfactor,1); - sig2 = delayline(sig2,rfactor.*dt,weight,conf2); - sig = resample(sig2,1,rfactor); - - case 'least_squares' - idt = floor(dt); - sig = delayline(sig,idt,weight,conf2); - if abs(dt-idt)>0 - for ii=1:channels - h = general_least_squares(Lls,dt(ii)-idt(ii),0.90); - tmp = convolution(sig(:,ii),h); - sig(:,ii) = tmp(Lls/2:end-Lls/2); - end - end - - case 'interp1' - idt = floor(dt); - sig = delayline(sig,idt,weight,conf2); - t = (1:samples)'; - for ii=1:channels - sig(:,ii) = interp1(t,sig(:,ii),-(dt(ii)-idt(ii))+t,'spline'); - end - - otherwise - disp('Delayline: Unknown fractional delay method'); - end - -else - % From here on integer delays are considered - idt = round(dt); - - % Handling of too long delay values (returns vector of zeros) - idt(abs(idt)>samples) = samples; - - % Handle positive or negative delays - for ii=1:channels - if idt(ii)>=0 - sig(:,ii) = [zeros(idt(ii),1); weight(ii)*sig(1:end-idt(ii),ii)]; - else - sig(:,ii) = [weight(ii)*sig(-idt(ii)+1:end,ii); zeros(-idt(ii),1)]; - end - end -end +function [sig,delay_offset] = delayline(sig,dt,weight,conf) +%DELAYLINE (fractional) delay line with weights +% +% Usage: [sig,delay_offset] = delayline(sig,dt,weight,conf) +% +% Input parameter: +% sig - input signal (vector), can be in the form of [N C], or +% [M C N], where +% N ... samples +% C ... channels (most probably 2) +% M ... number of measurements +% If the input is [M C N], the length of dt and weight has to be +% 1 or M*C. In the last case the first M entries in dt are +% applied to the first channel and so on. +% dt - delay / s +% weight - amplitude weighting factor +% conf - configuration struct (see SFS_config). +% +% Output parameter: +% sig - delayed signal +% delay_offset - additional delay / s +% This is added by the fractional delayline filters to +% all channels. For integer delays this is 0. +% +% DELAYLINE(sig,dt,weight,conf) implementes a delayline, that delays the given +% signal by dt samples and applies an amplitude weighting factor. The delay is +% implemented as integer delay or fractional delay filter, see delayline +% section in SFS_config for possible settings. As default setting an integer +% delayline is used. +% +% See also: get_ir, driving_function_imp_wfs + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Configuration =================================================== +% Check for old configuration +if isfield(conf, 'usefracdelay') + error(['%s: conf.usefracdelay is deprecated, please use conf.delayline', ... + ' instead. See SFS_config for details.'],upper(mfilename)); +end +fs = conf.fs; +delay = conf.delayline; + + +%% ===== Preparation ===================================================== +% --- Reshape signals --- +% Check if the signal is an impulse response given in SOFA conventions [M C N], +% or in usual [N C] convention, where +% M ... number of measurements +% C ... number of channels +% N ... number of samples +if ndims(sig)==3 + [M,C,samples] = size(sig); + channels = M * C; + % Reshape [M C N] => [N C*M], this will be redone at the end of the function + sig = reshape(sig,[channels,samples])'; + reshaped = true; +else + % Assume standard format [N C] + [samples,channels] = size(sig); + reshaped = false; +end + + +%% ===== Resampling ====================================================== +% The resampling is applied independently from the actual fractional/integer +% delay handling performed in the next step. The resampling is redone at the end +% of the file. +% If resampling is used together with the integer delay filter, this is already +% a usage of fractional delay due to the upsampling. +% +switch delay.resampling +case 'none' + rfactor = 1.0; + delay_offset = 0; +case 'matlab' + rfactor = delay.resamplingfactor; + delay_offset = 0; + sig = resample(sig,rfactor,1); +case 'pm' + % === Parks-McClellan linear phase FIR filter === + rfactor = delay.resamplingfactor; + rfilt = pm_filter(rfactor*delay.resamplingorder, 0.9/rfactor, ... + 1/rfactor); + delay_offset = delay.resamplingorder*rfactor/2; + + sig = reshape(sig,1,channels*samples); + sig = [sig; zeros(rfactor-1,channels*samples)]; + sig = reshape(sig,rfactor*samples,channels); + + sig = convolution(rfactor*rfilt, sig); +otherwise + error('%s: "%s": unknown resampling method',upper(mfilename), ... + delay.resampling); +end + + +%% ===== Expansion of signals, delays or weights ========================= +% --- Expand channels +if channels==1 + channels = max(length(dt),length(weight)); + sig = repmat(sig,[1 channels]); +end + +% --- Expand dt and weight --- +% If only single valued time delay and weight is given, create vectors +if channels>1 && length(dt)==1, dt=repmat(dt,[1 channels]); end +if channels>1 && length(weight)==1, weight=repmat(weight,[1 channels]); end + + +%% ===== Conversion to integer delay ===================================== +dt = dt.*rfactor.*fs; % resampled delay / samples +samples = rfactor.*samples; % length of resampled signals +switch delay.filter +case 'integer' + % === Integer delays === + idt = round(dt); % round to nearest integer delay + delay_offset = delay_offset + 0; +case 'zoh' + % === Zero-order hold === + idt = ceil(dt); % round to next larger integer delay + delay_offset = delay_offset + 0; +case 'lagrange' + % === Lagrange polynomial interpolator === + if iseven(delay.filterorder) + idt = round(dt); % round delay for even order + else + idt = floor(dt); % floor delay for odd order + end + fdt = dt - idt; % fractional part of delays + b = lagrange_filter(delay.filterorder,fdt); + a = ones(1,channels); + delay_offset = delay_offset + floor(delay.filterorder/2); +case 'thiran' + % === Thiran's allpass filter for maximally flat group delay === + idt = round(dt); % integer part of delays + fdt = dt - idt; % fractional part of delays + [b,a] = thiran_filter(delay.filterorder,fdt); + delay_offset = delay_offset + delay.filterorder; +case 'least_squares' + % ==== Least squares interpolation filter === + idt = floor(dt); % integer part of delays + fdt = dt - idt; % fractional part of delays + b = zeros(delay.filterorder+1,channels); + for ii=1:channels + b(:,ii) = general_least_squares(delay.filterorder+1,fdt(ii),0.90); + end + a = ones(1,channels); + delay_offset = delay_offset + floor(delay.filterorder/2); +case 'farrow' + % === Farrow-structure === + % Based on the assumption, that each coefficient h(n) of the fractional + % delay filter can be expressed as a polynomial in d (frac. delay), i.e. + % __ + % \ NPol + % h_d(n) ~= > c_m(n) d^m + % /__m=0 + % + % For some Filter design methods, e.g. Lagrange Interpolators, this is + % perfectly possible. For other, a uniform grid of test delays d_q is + % used to fit the polynomials to the desired coefficient(n) find a set + % polynomial which approximates each coefficient of the desired filter. + % This structure allows to perform the convolution independently from + % the delay and reuse the results of the filter for different delays. + % __ + % \ NPol + % y(n) = h_d(n) * x(n) ~= > ( c_m(n)*x(n) ) d^m + % /__m=0 + % + % The above representation shows that the convolution of the input + % signal x can be performed by first convolving c_m and x and + % incorporating the delay d afterwards. + % + % number of parallel filters, i.e. order of polynomial + 1 + % Nfilter = delay.filternumber; + to_be_implemented(mfilename); +otherwise + error('%s: \"%s\" is an unknown delayline filter', ... + upper(mfilename),delay.filter); +end +% Apply filter if needed +if exist('a','var') && exist('b','var') + for ii=1:channels + sig(:,ii) = filter(b(:,ii),a(:,ii),sig(:,ii)); + end +end + + +%% ===== Integer delayline =============================================== +% Handling of too long delay values (returns vector of zeros) +idt(abs(idt)>samples) = samples; +% Handle positive or negative delays +for ii=1:channels + if idt(ii)>=0 + sig(:,ii) = [zeros(idt(ii),1); weight(ii)*sig(1:end-idt(ii),ii)]; + else + sig(:,ii) = [weight(ii)*sig(-idt(ii)+1:end,ii); zeros(-idt(ii),1)]; + end +end + + +%% ===== Postprocessing ================================================== +% --- Downsampling --- +if rfactor~=1 + sig = sig(1:rfactor:samples,:); + delay_offset = delay_offset ./ rfactor; +end +% --- Undo reshape --- +% [N M*C] => [M C N] +if reshaped + % C might have changed due to replication of single-channel input + sig = reshape(sig',M,[],size(sig,1)); +end +% --- delay_offset in seconds --- +delay_offset = delay_offset / fs; diff --git a/SFS_general/direction_vector.m b/SFS_general/direction_vector.m index 0b7b9a88..cd438a44 100644 --- a/SFS_general/direction_vector.m +++ b/SFS_general/direction_vector.m @@ -1,66 +1,61 @@ -function n = direction_vector(x1,x2) -%DIRECTION_VECTOR returns a unit vector pointing from x1 to x2 -% -% Usage: n = direction_vector(x1,x2) -% -% Input parameters: -% x1 - starting point -% x2 - ending point -% -% Output parameters: -% n - unit vector pointing in the direction from x1 to x2 -% -% DIRECTION_VECTOR(x1,x2) calculates the unit vector pointing from the -% n-dimensional point x1 to the n-dimensional point x2. The vectors x1 -% and x2 can each be stored in a matrix containing m different direction -% vectors. -% -% See also: secondary_source_positions - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters =================================== -nargmin = 2; -nargmax = 2; -narginchk(nargmin,nargmax); -if size(x1)~=size(x2) - error('%s: x1 and x2 had to have the same size.',upper(mfilename)); -end - - -%% ==== Main ============================================================= -n = zeros(size(x1)); -for ii=1:size(x1,1) - n(ii,:) = (x2(ii,:)-x1(ii,:)) / norm(x2(ii,:)-x1(ii,:)); -end +function directions = direction_vector(x1,x2) +%DIRECTION_VECTOR unit vector(s) pointing from x1 to x2 +% +% Usage: n = direction_vector(x1,x2) +% +% Input parameters: +% x1 - starting point(s) [1xn] or [mxn] +% x2 - ending point(s) [1xn] or [mxn] +% +% Output parameters: +% n - unit vector(s) pointing in the direction(s) from x1 to x2 +% +% See also: secondary_source_positions + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters =================================== +nargmin = 2; +nargmax = 2; +narginchk(nargmin,nargmax); +if size(x1,2)~=size(x2,2) + error('%s: x1 and x2 need to have the same dimension.',upper(mfilename)); +end +if size(x1,1)~=size(x2,1) && ~(size(x1,1)==1 | size(x2,1)==1) + error(['%s: x1 and x2 need to have the same size, or one needs to ', ... + 'be a vector.'],upper(mfilename)); +end + + +%% ==== Main ============================================================= +% Calculate direction vectors +directions = bsxfun(@minus, x2, x1); % automatically adjusts matrix sizes +directions = bsxfun(@rdivide, directions, sqrt(sum(abs(directions).^2,2))); diff --git a/SFS_general/download_file.m b/SFS_general/download_file.m index 86ae907b..1ed278ae 100644 --- a/SFS_general/download_file.m +++ b/SFS_general/download_file.m @@ -1,81 +1,78 @@ -function success = download_file(url,outfile) -%DOWNLOAD_FILE downloads a file to your computer -% -% Usage: success = download_file(url,outfile) -% -% Input parameters: -% url - url to download -% outfile - path to store the file -% -% Output parameters: -% success - 0 or 1 -% -% DOWNLOAD_FILE(url,file) downloads the given url and stores it at outfile. -% If outfile contains directories that do not exist yet, they will be created. -% -% See also: get_spherical_grid - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input parameters ======================================= -nargmin = 2; -nargmax = 2; -narginchk(nargmin,nargmax); -isargchar(url,outfile) - - -%% ===== Main ============================================================ -% Download if file is not present -if ~exist(outfile,'file') - % Replace '\' with '/' - outfile = strrep(outfile,'\','/'); - % Create dir - % NOTE: newer versions of Matlab can do the following with the strsplit - % function - %dirs = strsplit(outfile,'/'); - dirs = regexp(outfile,'/','split'); - dir_path = []; - for ii=1:length(dirs)-1 - if ii==1 && iswindows - dir_path = [dir_path dirs{ii}]; - else - dir_path = [dir_path '/' dirs{ii}]; - end - [~,~] = mkdir(dir_path); - end - warning('Downloading file %s',url); - [~,success] = urlwrite(url,outfile); -else - error('%s: file exist.',upper(mfilename)); -end +function success = download_file(url,outfile) +%DOWNLOAD_FILE downloads a file to your computer +% +% Usage: success = download_file(url,outfile) +% +% Input parameters: +% url - url to download +% outfile - path to store the file +% +% Output parameters: +% success - 0 or 1 +% +% DOWNLOAD_FILE(url,file) downloads the given url and stores it at outfile. +% If outfile contains directories that do not exist yet, they will be created. +% +% See also: get_spherical_grid + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking input parameters ======================================= +nargmin = 2; +nargmax = 2; +narginchk(nargmin,nargmax); +isargchar(url,outfile) + + +%% ===== Main ============================================================ +% Download if file is not present +if ~exist(outfile,'file') + % Replace '\' with '/' + outfile = strrep(outfile,'\','/'); + % Create dir + % NOTE: newer versions of Matlab can do the following with the strsplit + % function + %dirs = strsplit(outfile,'/'); + dirs = regexp(outfile,'/','split'); + dir_path = ''; + for ii=1:length(dirs)-1 + if ii==1 && iswindows + dir_path = [dir_path dirs{ii}]; + else + dir_path = [dir_path '/' dirs{ii}]; + end + [~,~] = mkdir(dir_path); + end + warning('Downloading file %s',url); + [~,success] = urlwrite(url,outfile); +else + error('%s: file exist.',upper(mfilename)); +end diff --git a/SFS_general/easyfft.m b/SFS_general/easyfft.m deleted file mode 100644 index 97044dae..00000000 --- a/SFS_general/easyfft.m +++ /dev/null @@ -1,101 +0,0 @@ -function varargout = easyfft(sig,conf) -%EASYFFT calculates the FFT of a signal and returns the corresponding frequency -% axis -% -% Usage: [amplitude,phase,f] = easyfft(sig,[conf]) -% -% Input parameters: -% sig - one channel audio waveform -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% amplitude - amplitude spectrum of the input signal -% phase - phase spectrum of the input signal / rad -% f - corresponding frequency axis for the amplitude -% spectrum (=> plot(f,amplitude) / Hz -% -% EASYFFT(sig) calculates the amplitude and phase of the sig spectrum by using -% the fast Fourier transformation. In addition to the amplitude and phase, the -% corresponding frequency axis for a plot is returned. -% -% See also: easyifft, fft - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Check input arguments =========================================== -nargmin = 1; -nargmax = 2; -narginchk(nargmin,nargmax); -sig = column_vector(sig); -if nargin complex output) -compspec = fft(sig); - -% Length of the signal => number of points of fft -samples = length(sig); - -% Get amplitude and phase spectra (and use only the first half of the -%>spectrum (Nyquist)) -amplitude = abs(compspec(1:ceil(samples/2))); -phase = angle(compspec(1:ceil(samples/2))); - -% Scale the amplitude (factor two, because we have cut off one half and -%>divide by number of samples) -amplitude = 2*amplitude / samples; - -% Calculate corresponding frequency axis -f = fs*(0:ceil(samples/2)-1)'/samples; - -% Return values -if nargout>0, varargout{1}=amplitude; end -if nargout>1, varargout{2}=phase; end -if nargout>2, varargout{3}=f; end - - -%% ===== Plotting ======================================================== -if nargout==0 || useplot - figure; semilogx(f,20*log10(abs(amplitude))); -end diff --git a/SFS_general/easyifft.m b/SFS_general/easyifft.m deleted file mode 100644 index a591e6c4..00000000 --- a/SFS_general/easyifft.m +++ /dev/null @@ -1,75 +0,0 @@ -function outsig = easyifft(amplitude,phase) -%EASYIFFT calculates the inverse FFT -% -% Usage: outsig = easyifft(amplitude,phase) -% -% Input parameters: -% amplitude - the amplitude spectrum -% phase - the phase spectrum / rad -% -% Output parameters: -% outsig - a one channel signal -% -% EASYIFFT(amplitude,phase) generates the corresponding waveform from the -% amplitude and phase spectra using ifft. -% -% See also: easyfft, ifft - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input arguments ======================================== -nargmin = 2; -nargmax = 2; -narginchk(nargmin,nargmax); -[amplitude,phase] = column_vector(amplitude,phase); - - -%% ===== Regenerating wave form from spectrum ============================ -% Length of the signal to generate -samples = 2 * (length(amplitude)-1); - -% Rescaling (see easyfft) -amplitude = amplitude/2 * samples; - -% Mirror the amplitude spectrum -amplitude = [ amplitude; amplitude(end-1:-1:2) ]; - -% Mirror the phase spectrum and build the inverse (why?) -phase = [ phase; -1*phase(end-1:-1:2) ]; - -% Convert to complex spectrum -compspec = amplitude .* exp(1i*phase); - -% Build the inverse fft and use only the real part -outsig = real( ifft(compspec) ); diff --git a/SFS_general/fft_real.m b/SFS_general/fft_real.m deleted file mode 100644 index 7e088282..00000000 --- a/SFS_general/fft_real.m +++ /dev/null @@ -1,63 +0,0 @@ -function y = fft_real(x) -%FFT_REAL computes an fft for real value signals -% -% Usage: y = fft_real(x) -% -% Input parameters: -% x - matrix with signals as columns -% -% Output parameters: -% y - matrix with signals as columns -% -% FFT_REAL(x) computes the fft of the real signals in x. The signals have -% to be the columns of x. -% -% See also: ifft_real, convolution - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ==================================== -nargmin = 1; -nargmax = 1; -narginchk(nargmin,nargmax); -isargmatrix(x); - - -%% ===== Computation ===================================================== -N = size(x,1); -N2=floor(N/2)+1; - -% Force IFFT along dimension 1 -y = fft(x,N,1); -y = y(1:N2,:); diff --git a/SFS_general/findcols.m b/SFS_general/findcols.m index 1895059b..082e7331 100644 --- a/SFS_general/findcols.m +++ b/SFS_general/findcols.m @@ -1,5 +1,5 @@ function k = findcols(A,b) -%FINDCOLS finds indices of a given column within a matrix. +%FINDCOLS finds a column within a matrix. % % Usage: idx = findcols(A,b) % @@ -17,35 +17,32 @@ % See also: find, findrows %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** % AUTHOR: Peter John Acklam diff --git a/SFS_general/findconvexcone.m b/SFS_general/findconvexcone.m new file mode 100644 index 00000000..67d7fa80 --- /dev/null +++ b/SFS_general/findconvexcone.m @@ -0,0 +1,166 @@ +function [idx,weights] = findconvexcone(x0,xs) +%FINDCONVEXCONE selects up to 3 points from x0 with xs in their conic span +% +% Usage: [idx,weights] = findconvexcone(x0,xs) +% +% Input parameters: +% x0 - point cloud on a sphere around the origin / m [nx3] +% xs - desired direction as point in R^3 / m [1x3] +% +% Output parameters: +% idx - row indices of N points in x0 [Nx1] +% where N is 1,2 or 3 +% weights - weights [Nx1] +% +% FINDCONVEXCONE(x0,xs) returns 1,2 or 3 row indices into x0 and non-negative +% weights w1, ..., w3 such that w1*x1 + w2*x2 + w3*x3 with +% [x1; x2; x3] == x0(idx,:) composes the point inside the triangle spanned +% by x1, x2, x3. +% +% x1...x3 are selected from the convex hull in R3. +% Various precautions are taken to make this well-behaved in most cases. +% +% (If all x0 and xs have unit norm this is VBAP.) +% +% See also: findnearestneighbour, test_interpolation_point_idx + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ==================================== +nargmin = 2; +nargmax = 2; +narginchk(nargmin,nargmax); + + +%% ===== Prepare Grid (see local functions below) ======================== +% Normalise x0 and xs to lie on unit sphere as only direction is relevant +xs = xs./norm(xs,2); +radii = vector_norm(x0,2); +if abs(max(radii) - min(radii)) >1e-3 + warning('%s: Grid is apparently not a sphere.', upper(mfilename)) +end +x0 = x0./repmat(radii,[1,size(x0,2)]); + +% Rotate to principal axes to enable 2D arrays +[x0, xs] = rotate_to_principal_axes(x0, xs); + +% Calculate dummy points to enable "partial" arrays +dummy_points = augment_bounding_box(x0); +if ~isempty(dummy_points) + dummy_indices = (1:size(dummy_points,1)) + size(x0,1); + x0 = [x0; dummy_points]; +end + + +%% ===== Computation ===================================================== +% Delaunay triangulation of convex hull +simplices = convhulln(x0); + +% Find x0 with smallest angle to xs +[~,most_aligned_point] = ... + max(vector_product(x0,repmat(xs,size(x0,1),1),2)); + +% The simplices at "most aligned point" are the most likely candidates, +% put them at the beginning of the list +mask = logical(sum(simplices==most_aligned_point,2)); +simplices = [simplices(mask,:); simplices(~mask,:) ]; + +% One of these simplices contains xs +for n = 1:size(simplices,1); + A = x0(simplices(n,:),:); + weights = xs/A; + weights(abs(weights)<1e-10) = 0; + if all(weights >= 0) % non-negative weights == convex combination + idx = simplices(n,:); + break; + end +end +assert(all(weights >= 0), '%s: Negative weights. Shall never happen.', ... + upper(mfilename)) + +if ~isempty(dummy_points) + % Remove possible dummies from selected points + dummy_mask = (dummy_indices == idx); + if any(dummy_mask) + idx(dummy_mask) = []; + if ~weights(dummy_mask)==0 + warning('%s: Requested point lies outside grid.', upper(mfilename)) + end + weights(dummy_mask) = []; + end +end + +% Normalise weights +weights = weights/sum(weights); + +[weights,order] = sort(weights.','descend'); +idx = idx(order).'; +end + +% ========================================================================= + +function [x0, xs] = rotate_to_principal_axes(x0, xs, gamma) +%ROTATE_TO_PRINCIPAL_AXES rotates x0 and xs to x0's principal axes. +% If the ratio of second-to-smallest singular values is < gamma, +% the third dimension is discarded. +% +% Input parameters: +% x0 - point cloud in R^3 +% xs - point in R^3 +% gamma - scalar in 0 < gamma << 1 +% +% Output parameters: +% x0 - point cloud in R^3 or R^2 +% xs - point in R^3 or R^2 +if nargin < 3 + gamma = 0.1; % inverse of aspect ratio of principal axes +end + +[~,S,V] = svd(x0); +x0 = x0*V; +xs = xs*V; +S = diag(S); +if S(end)/S(end-1) < gamma + x0(:,3) = []; + xs(3) = []; + warning('SFS:findconvexcone','%s: Grid is apparently two-dimensional. ', ... + upper(mfilename)); +end +end + +% ========================================================================= + +function dummy_points = augment_bounding_box(x0) +%AUGMENT_BOUNDING_BOX yields dummy points such that the origin is +% contained in the cartesian bounding box of x0. +dummy_points = -diag(sign(max(x0)) + sign(min(x0))); +dummy_points(~any(dummy_points,2),:) = []; +end diff --git a/SFS_general/findnearestneighbour.m b/SFS_general/findnearestneighbour.m index e3ade9f4..a72c9d1b 100644 --- a/SFS_general/findnearestneighbour.m +++ b/SFS_general/findnearestneighbour.m @@ -1,53 +1,50 @@ -function [C,idx] = findnearestneighbour(A,b,number_of_neighbours) -%FINDNEARESTNEIGHBOUR finds the n nearest neighbours +function [idx,weights] = findnearestneighbour(A,b,N) +%FINDNEARESTNEIGHBOUR finds the N nearest neighbours % -% Usage: [C,idx] = findnearestneighbour(A,b,[number_of_neighbours]); +% Usage: [idx,weights] = findnearestneighbour(A,b,N) % % Input parameters: -% A - matrix -% b - colum to search for in A -% number_of_neighbours - number of nearest neighbours to find +% A - points in R^3 / m [nx3] +% b - desired point in R^3 / m [1x3] +% N - number of nearest neighbours to find % -% output parameters: -% C - found neighbour columns -% idx - indices of found columns in matrix +% Output parameters: +% idx - row indices of N points in A [Nx1] +% weights - weights [1x1] or [2x1] % -% FINDNEARESTNEIGHBOUR(A,b,number_of_neighbours) returns a number_of_neighbours -% column vectors with the nearest neighbour points from the matrix A to the -% point b. In addition to the values, the indices are also returned. +% FINDNEARESTNEIGHBOUR(A,b,N) returns N indices idx for the nearest neighbour +% points from A to point b. For N<=2, weights for linear interpolation are also +% returned. % -% See also: find, findrows +% See also: find, findrows, get_ir %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** @@ -56,22 +53,36 @@ nargmax = 3; narginchk(nargmin,nargmax); if nargin==nargmax-1 - number_of_neighbours = 1; + N = 1; end -% Ensure column vector -if size(b,2)>1 - b=b'; +if nargout==2 && N>=3 + error(['%s: calculation of weights for 3 or more nearest neighbours ', ... + 'is not implemented.'],upper(mfilename)); end -if number_of_neighbours>size(A,2) - error(['%s: your number of neighbours is larger than the available ', ... - 'points.'],upper(mfilename)); +% Ensure row vector +if size(b,1)>1 + b=b.'; end %% ===== Computation ===================================================== % Calculate distance between points -distance = vector_norm(bsxfun(@minus,A,b),1); +distance = vector_norm(bsxfun(@minus,A.',b.'),1); % Sort the distances in order to find the n lowest once [~,idx] = sort(distance); -idx = idx(1:number_of_neighbours); -C = A(:,idx); +idx = idx(1:min(N,length(idx))).'; + +% Determine weights for linear 1D interpolation over angle +cos_alpha = sum(bsxfun(@times,A(idx,:).',b.'))./vector_norm(A(idx,:),2).'/norm(b); +% Ensure range -1...1 +cos_alpha = min(cos_alpha,1); +cos_alpha = max(cos_alpha,-1); +angles = acos(cos_alpha); +if angles == 0 + weights = 1; +else + angles = fliplr(angles); + weights = angles.'/sum(angles); +end +assert(all(weights >= 0), '%s: Negative weights. Shall never happen.', ... + upper(mfilename)) diff --git a/SFS_general/findrows.m b/SFS_general/findrows.m index 0147e7d6..8e7067c5 100644 --- a/SFS_general/findrows.m +++ b/SFS_general/findrows.m @@ -1,5 +1,5 @@ function k = findrows(A,b) -%FINDROWS finds indices of a given row within a matrix. +%FINDROWS finds a row vector within a matrix. % % Usage: idx = findrows(A,b) % @@ -17,35 +17,32 @@ % See also: find, findcols %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** % AUTHOR: Peter John Acklam diff --git a/SFS_general/findvoronoi.m b/SFS_general/findvoronoi.m new file mode 100644 index 00000000..41307f8e --- /dev/null +++ b/SFS_general/findvoronoi.m @@ -0,0 +1,456 @@ +function [idx,weights] = findvoronoi(x0,xs) +%FINDVORONOI finds the corresponding voronoi regions to the points x0 +%surrounding the desired point xs. The weights are derived from the Voronoi +%region surface area differences with and without xs. +% +% Usage: [idx,weights] = findvoronoi(x0,xs) +% +% Input parameters: +% x0 - point cloud on a sphere around the origin / m [nx3] +% xs - desired point in R^3 / m [1x3] +% +% Output parameters: +% idx - row indices of N points in x0 [Nx1] +% weights - weights [Nx1] +% +% +% See also: findnearestneighbour, findconvexcone, +% test_interpolation_point_selection + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ==================================== +nargmin = 2; +nargmax = 2; +narginchk(nargmin,nargmax); + + +%% ===== Prepare Grid ==================================================== +% Normalise x0 and xs to lie on unit sphere +xs = xs./norm(xs,2); +radii = vector_norm(x0,2); +if abs(max(radii) - min(radii)) >1e-3 + warning('%s: Grid is apparently not a sphere.', upper(mfilename)) +end +x0 = x0./repmat(radii,[1,size(x0,2)]); + +% Center of the Sphere +center = [0 0 0]; + +% Check dimensionality and rotate to principal axes +[x0,xs,dim,eq_idx] = check_dimensionality(x0,xs); + +% In 1D case (xs is colinear with or equals one x0) no interpolation is needed +if dim==1 + idx = eq_idx; + weights = ones(size(idx,1),1) / size(idx,1); + return +end + +% In 2D case linear interpolation using neighboring x0 is sufficient +if dim==2 + [idx, weights] = findnearestneighbour(x0,xs,2); + return +end + +% In 2.5D case order x0 with respect to azimuth angle +if dim == 2.5 + [~,idx_sorted,az] = sort_azimuth(x0); +end + +%% ===== Computation ===================================================== + +% Delaunay triangulation of convex hull with xs (new) +simplices_new = convhulln([x0; xs]); + +% Extract all neighbors of x0 sharing a triangle with xs, denoted as x0_s +xs_idx = size([x0;xs], 1); +[row, ~] = find(simplices_new == xs_idx); +xs_tri = simplices_new(row, :); +idx = unique(xs_tri(xs_tri ~= xs_idx)); + +% Extract all triangles from the simplices with at least one x0_s as a vertex +simplices_new_s = []; +for n = 1:size(idx) + [row, ~] = find(simplices_new == idx(n)); + simplices_new_s = cat(1,simplices_new_s,simplices_new(row,:)); +end +simplices_new_s = unique(simplices_new_s,'rows'); + +% Compute new spherical voronoi_regions for each x0_s +[regions_new_s, vertices_new_s] = calc_voronoi_regions([x0;xs],center, ... + simplices_new_s); + +% Prepare new regions for calculation of the surface area +% Sorting the regions +[regions_new_s] = sort_voronoi_vertices_of_regions(simplices_new_s, ... + regions_new_s); + +% Special 2.5D case handling: skip computation of old voronoi regions +if dim ~= 2.5 + % Delaunay triangulation of convex hull without xs (old) + simplices_old = convhulln(x0); + + % Extract all triangles from the simplices with at least one x0_s as vertex + simplices_old_s = []; + for n = 1:size(idx) + [row_old, ~] = find(simplices_old == idx(n)); + simplices_old_s = cat(1,simplices_old_s,simplices_old(row_old,:)); + end + simplices_old_s = unique(simplices_old_s,'rows'); + + % Compute old spherical voronoi_regions for each x0_s + [regions_old_s, vertices_old_s] = calc_voronoi_regions([x0;xs],center, ... + simplices_old_s); + + % Prepare old regions for calculation of the surface area + % Sorting the regions + [regions_old_s] = sort_voronoi_vertices_of_regions(simplices_old_s, ... + regions_old_s); + +end + +% Surface area calculation +[area_new, area_old] = deal(zeros(size(idx,1),1)); +for ii=1:size(idx,1) + area_new(ii) = calc_surface_area( ... + vertices_new_s(regions_new_s{idx(ii)},:),1); + % Special 2.5D case handling: alternative calculation of old area + if dim ~= 2.5 + area_old(ii) = calc_surface_area( ... + vertices_old_s(regions_old_s{idx(ii)},:),1); + else + % Old area calculation based on area of spherical lune + az_diff = zeros(size(idx,1),1); + m = [size(idx,1) 1:size(idx,1) 1]; + for n = 1:size(idx,1) + az_diff(n) = (az(m(n+2)) - az(m(n))) / 2; + if az_diff(n)<0 + az_diff(n) = (az(m(n+2)) - az(m(n)) + 360) / 2; + end + end + area_old(:) = pi/90 * az_diff(:); + area_old = area_old(circshift(idx_sorted,2)); + end +end + +% Calculate weights +weights = (area_old - area_new) ./ sum(area_old - area_new); + +[weights,order] = sort(weights,'descend'); +idx = idx(order); +end + + +%% ===== Functions ======================================================= + +function [regions,vertices] = calc_voronoi_regions(x0,center,simplices) +%CALC_VORONOI_REGIONS calculates the Voronoi vertices and regions of the given +%points x0. In case specific simplices are provided as input argument, only +%those will be included in the calculation. +% +% Input parameters: +% x0 - point cloud on the surface of a unit sphere in R^3 [nx3] +% center - center of the sphere in R^3 [1x3] +% simplices - pre-calculated simplices, each consisting of +% 3 indices of the points given in x0 [Nx3] +% +% Output parameters: +% regions - cell array consisting of the indices of the vertices +% to belong to the region of each point of x0 [nx3] +% vertices - Voronoi vertices in R^3 [Mx3] +% +% Code based on scipy.spatial._spherical_voronoi.SphericalVoronoi + +if nargin < 3 + simplices = convhulln(x0); % in case simplices are not provided as input arg +end + +% Tetrahedrons from Delaunay triangulation with shape [4x3x2n-4]. +% Add center of sphere to each of the simplices +tri = x0(simplices.', 1:end); +tetrahedrons = []; +n = 1:3:size(tri,1); +for m=n + tetrahedrons = cat(3,tetrahedrons,cat(1,tri(m:m+2,:),center)); +end + +% Calculate surface normal of each triangle via cross product of triangle edges +N = bsxfun(@cross,tri(n+1,:)-tri(n,:),tri(n+2,:)-tri(n,:)); +N = N./repmat(vector_norm(N,2),[1,size(N,2)]); +% Determine direction of projection into correct hemisphere +project_dir = sign(vector_product(direction_vector(tri(n,:),center),N(:,:),2)); + +% Calculate circumcenters of tetrahedrons +% Special handling in case of coplanarity of a triangle and center of the sphere +if ~any(find(~project_dir)) + % Normal handling + circumcenters = calc_circumcenters(tetrahedrons); +else + % Special handling + % Circumcenters lie directly on the center and are projected manually + circumcenters = zeros(size(n,2),3); + for ii = 1:size(n,2) + if project_dir(ii)==0 + circumcenters(ii,:) = N(ii,:); + project_dir(ii) = -1; + else + circumcenters(ii,:) = calc_circumcenters(tetrahedrons(:,:,ii)); + end + end +end + +% Project circumcenters of the tetrahedrons to the surface of the unit +% sphere and thereby get the voronoi vertices with shape [2n-4x3] +% Consider the surface normal direction of each triangle for projection into +% into correct hemisphere +circumcenters = bsxfun(@times, circumcenters, project_dir); +vertices = bsxfun(@rdivide,circumcenters,vector_norm(circumcenters,2)); + +% Calculate regions from triangulation. +% simplex_indices have shape [1x2n-4] +simplex_indices = 1:1:size(simplices,1); +% tri_indices have shape [1x6n-12] +tri_indices = sort( repmat(simplex_indices, 1,3) ); +% point_indices have shape [1x6n-12] +point_indices = reshape(simplices.',1, []); +% array_associations have shape [6n-12x2] +array_associations = cat(1, point_indices, tri_indices).'; +array_associations = sortrows(array_associations); +array_associations = cast(array_associations,'int32'); + +% Group by generator indices to produce unsorted regions in a cell array +regions = accumarray(array_associations(:,1),array_associations(:,2),[], ... + @(x){x.'},{}); +end + +% ========================================================================= + +function [circumcenters] = calc_circumcenters(tetrahedrons) +%CALC_CIRCUMCENTERS calculates the circumcenters of the circumspheres of +%tetrahedrons. +% +% Input parameters: +% tetrahedrons - tetrahedrons defined by 4 points in R^3 [4x2xN] +% +% Output parameters: +% circumcenters - circumcenters in R^3 [Nx3] +% +% Code based on scipy.spatial._spherical_voronoi.calc_circumcenters +% An implementation based on http://mathworld.wolfram.com/Circumsphere.html + +num = size(tetrahedrons,3); +a = cat(2, tetrahedrons, ones(4,1,num)); + +sums = sum(tetrahedrons.^2, 2); +d = cat(2, sums, a); + +[dx1, dy1, dz1] = deal(d); +dx1(:, 2, :) = []; +dy1(:, 3, :) = []; +dz1(:, 4, :) = []; + +% Calculating det in 3D array; inefficient +[dx, dy, dz, ad] = deal(zeros(1,num)); +for ii=1:num + dx(ii) = det(dx1(:,:,ii)); + dy(ii) = -det(dy1(:,:,ii)); + dz(ii) = det(dz1(:,:,ii)); + ad(ii) = det(a(:,:,ii)); +end + +nominator = cat(1, dx, dy, dz); +denominator = 2.*ad; + +circumcenters = bsxfun(@rdivide, nominator, denominator).'; +end + +% ========================================================================= + +function [regions_sorted] = sort_voronoi_vertices_of_regions(simplices,regions) +%SORT_VORONOI_VERTICES_OF_REGIONS sorts the indices of the Voronoi vertices for +%each region such that the resulting points are in a clockwise or +%counterclockwise order around the generator point. +% +% Input parameters: +% simplices - array of shape (Nx3) consisting of N points on +% the surface of a unit sphere in R^3 +% regions - center of the sphere in R^3 [1x3] +% +% Output parameters: +% regions - cell array consisting of the indices of the vertices to +% belong to the region of each point of x0 [Nx3] +% +% Code based on scipy.spatial._spherical_voronoi.SphericalVoronoi + +ARRAY_FILLER = -2; +sorted_vertices = zeros(1, max(cellfun('length', regions)), 'int32'); +regions_sorted = cell(size(regions,1),1); + +for n=1:size(regions,1) + remaining_count = 1; + remaining = regions{n}; + remaining_size = size(remaining,2); + sorted_vertices(:) = ARRAY_FILLER; + + % In case the region (cell) is empty + if remaining_size<1 + regions_sorted{n} = 0; + else + current_simplex = remaining(1); + for ii=1:3 + k = simplices(current_simplex,ii); + if k ~= n + current_vertex = k; + break + end + end + sorted_vertices(remaining_count) = current_simplex; + remaining_count = remaining_count+1; + + % remaining_filter() + for l=1:size(remaining,2) + if remaining(l) == current_simplex + remaining(l) = ARRAY_FILLER; + end + end + + while remaining_size >= remaining_count + cs_identified = 0; + for ii=1:remaining_size + if remaining(ii) == ARRAY_FILLER + continue + end + s = remaining(ii); + for jj=1:3 + if current_vertex == simplices(s, jj) + current_simplex = remaining(ii); + cs_identified = cs_identified +1; + break + end + end + if cs_identified > 0 + break + end + end + + for ii=1:3 + s = simplices(current_simplex, ii); + if s~=n && s~=current_vertex + current_vertex = s; + break + end + end + sorted_vertices(remaining_count) = current_simplex; + remaining_count = remaining_count +1; + % remaining_filter() + for l=1:size(remaining,2) + if remaining(l) == current_simplex + remaining(l) = ARRAY_FILLER; + end + end + end + regions_sorted{n} = sorted_vertices(sorted_vertices > ARRAY_FILLER); + end +end +end + +% ========================================================================= + +function [surface_area] = calc_surface_area(vertices,radius) +%CALC_SURFACE_AREA calculates the surface area of a polygon on the surface of a +%sphere. The input vertices need to be sorted around their generator point. +% +% Input parameters: +% vertices - sorted vertices [Nx3] +% radius - radius of the sphere +% +% Output parameters: +% surface_area - calculated surface area of the given polygon +% +% Implementation based on: http://mathworld.wolfram.com/LHuiliersTheorem.html +% Code based on: voronoi_utility.py from https://doi.org/10.5281/zenodo.13688 + +n = size(vertices, 1); +root_point = vertices(1,:); +surface_area = 0; + +b_point = vertices(2,:); +root_b_dist = calc_haversine_dist(root_point, b_point); +for ii=2:(n-1) + a_point = b_point; + b_point = vertices(ii+1,:); + root_a_dist = root_b_dist; + root_b_dist = calc_haversine_dist(root_point, b_point); + a_b_dist = calc_haversine_dist(a_point, b_point); + s = (root_a_dist + root_b_dist + a_b_dist) ./ 2; + surface_area = surface_area + 4.* atan( sqrt( ... + tan(0.5 .* s) .* ... + tan(0.5 .* (s-root_a_dist)) .* ... + tan(0.5 .* (s-root_b_dist)) .* ... + tan(0.5 .* (s-a_b_dist)) )); +end +% Avoid complex numbers, which occur possibly due to rounding errors +surface_area = real(surface_area * radius^2); +end + +% ========================================================================= + +function [sph_dist] = calc_haversine_dist(x1,x2) +%CALC_HAVERSINE_DISTANCE calculates the distance between two points on the +% surface of a unit sphere based on the Haversine formula provided here: +% https://en.wikipedia.org/wiki/Haversine_formula +% +% Code based on: voronoi_utility.py from https://doi.org/10.5281/zenodo.13688 + +[az1, el1, ~] = cart2sph(x1(:,1), x1(:,2), x1(:,3)); +[az2, el2, ~] = cart2sph(x2(:,1), x2(:,2), x2(:,3)); + +el1 = -(el1-pi/2); +el2 = -(el2-pi/2); + +% long/lat is not the same as spherical coordinates - phi differs by pi/4 +sph_dist = 2 * asin( sqrt(( (1 - cos(el2 - el1))./2) ... + + sin(el1) .* sin(el2) .* ((1-cos(az2 - az1))./2)) ); +end + +% ========================================================================= + +function [x0,idx,az] = sort_azimuth( x0 ) +%SORT_AZIMUTH sorts x0 based on azimuth angle + +% Compute azimuth +az = atan2d(x0(:,2), x0(:,1)); +% Sort azimuth +[az, idx] = sort(az); +% Reorder +x0 = [x0(idx,1) x0(idx,2) x0(idx,3)]; +end diff --git a/SFS_general/fix_length.m b/SFS_general/fix_length.m index a860fb38..3c8e44b9 100644 --- a/SFS_general/fix_length.m +++ b/SFS_general/fix_length.m @@ -1,68 +1,65 @@ -function sig = fix_length(sig,N) -%FIX_LENGTH pads zeros or removes entries from the signal according to length N -% -% Usage: sig = fix_length(sig,N) -% -% Input parameters: -% sig - input signal (matrix with sigs as columns) -% N - number of samples size(sig,1) should be -% -% Output paramteres: -% sig - corrected sig -% -% FIX_LENGTH(sig,N) pads zeros or removes the end of the given signal in -% order to have a sig with a size(sig,1)==N. -% -% see also: fix_irs_length, convolution - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 2; -nargmax = 2; -narginchk(nargmin,nargmax); - - -%% ===== Fix IR ========================================================== -% Length of IR -samples = size(sig,1); -channels = size(sig,2); - -if samples. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_general/general_least_squares.m b/SFS_general/general_least_squares.m index 3bcea6b8..56772502 100644 --- a/SFS_general/general_least_squares.m +++ b/SFS_general/general_least_squares.m @@ -1,88 +1,86 @@ -function h = general_least_squares(samples,fractional_delay,passband_edge) -%GENERAL_LEAST_SQUARES fractional delay approximation using the general least -%squares method -% -% Usage: h = general_least_squares(samples,fractional_delay,passband_edge) -% -% Input parameters: -% samples - filter length (filter order N = samples-1) -% fractional_delay - fractional delay (0 < x <= 1) -% passband_edge - passband edge of approximation (in [0 1]) -% -% Output parameters: -% h - filter coefficient vector h(1)...h(samples) -% -% GENERAL_LEAST_SQUARES(samples,fractional_delay,passband_edge) calculates the -% filter coefficients needed for the least squares fractional delay method -% which is used in delayline() if conf.usefracdelay == true and -% conf.fracdelay_method == 'least_squares'. -% -% See also: delayline - -% This code is based on hgls2() from Timo Laakso - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -% Disabled for time constrains -%nargmin = 3; -%nargmax = 3; -%narginchk(nargmin,nargmax); - - -%% ===== Computation ===================================================== -N = samples-1; % filter order -M = N/2; % middle value -if (M-round(M))==0 - D = fractional_delay + M; % integer part closest to middle -else - D = fractional_delay + M-0.5; -end - -cT = zeros(N+1,1); -p1 = cT; -cT(1)=passband_edge; -if round(D)==D - p1(1) = passband_edge; -else - p1(1) = ( sin(D*passband_edge*pi) )/(D*pi); -end -for k=1:N % compute the elements of the Toeplitz matrix (vector) - k1 = k+1; - kD = k-D; - cT(k1) = ( sin(k*passband_edge*pi) )/(k*pi); - p1(k1) = ( sin(kD*passband_edge*pi) )/(kD*pi); -end -P = toeplitz(cT); -h = P\p1; +function h = general_least_squares(samples,fractional_delay,passband_edge) +%GENERAL_LEAST_SQUARES fractional delay approximation using the general least +%squares method +% +% Usage: h = general_least_squares(samples,fractional_delay,passband_edge) +% +% Input parameters: +% samples - filter length (filter order N = samples-1) +% fractional_delay - fractional delay (0 < x <= 1) +% passband_edge - passband edge of approximation (in [0 1]) +% +% Output parameters: +% h - filter coefficient vector h(1)...h(samples) +% +% GENERAL_LEAST_SQUARES(samples,fractional_delay,passband_edge) calculates the +% filter coefficients needed for the least squares fractional delay method +% which is used in delayline() if conf.usefracdelay == true and +% conf.fracdelay_method == 'least_squares'. +% +% See also: delayline + +% This code is based on hgls2() from Timo Laakso + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +% Disabled for time constrains +%nargmin = 3; +%nargmax = 3; +%narginchk(nargmin,nargmax); + + +%% ===== Computation ===================================================== +N = samples-1; % filter order +M = N/2; % middle value +if (M-round(M))==0 + D = fractional_delay + M; % integer part closest to middle +else + D = fractional_delay + M-0.5; +end + +cT = zeros(N+1,1); +p1 = cT; +cT(1)=passband_edge; +if round(D)==D + p1(1) = passband_edge; +else + % matlab's sinc(x) equals sin(pi*x)./(pi*x) + p1(1) = passband_edge * sinc(D*passband_edge); +end +for k=1:N % compute the elements of the Toeplitz matrix (vector) + k1 = k+1; + kD = k-D; + cT(k1) = passband_edge * sinc(k*passband_edge); + p1(k1) = passband_edge * sinc(kD*passband_edge); +end +P = toeplitz(cT); +h = P\p1; diff --git a/SFS_general/get_shelve_lagrange.m b/SFS_general/get_shelve_lagrange.m index 6a845fbe..13a4f6d8 100644 --- a/SFS_general/get_shelve_lagrange.m +++ b/SFS_general/get_shelve_lagrange.m @@ -1,20 +1,27 @@ function H = get_shelve_lagrange(f,H,FlagSub,fSub,FlagAliasing,fAliasing,Bandwidth_in_Oct) -%GET_SHELVE_LAGRANGE does an Lagrange interpolation towards shelving filter +%GET_SHELVE_LAGRANGE Lagrange interpolation towards shelving filter % % Usage: H = get_shelve_lagrange(f,H,FlagSub,fSub,FlagAliasing, ... % fAliasing,Bandwidth_in_Oct) % % Input parameters: -% f - -% H - -% FlagSub - -% fSub - -% FlagAliasing - -% fAliasing - -% Bandwidth_in_Oct - +% f - frequency vector in Hz, typical 0 to half +% sampling frequency, equidistant sampling is +% assumed (i.e. DFT frequencies) but not required +% H - complex spectrum (mag/phase) at specified frequencies +% with meaningful slope, typically used for +3dB/oct. +% FlagSub - use low-shelf part, 0 or 1 +% fSub - cut-frequency in Hz for low-shelf, +% check e.g. fLow=100Hz in [Fig2, Sch13] +% FlagAliasing - use high-sehlf part, 0 or 1 +% fAliasing - cut-frequency in Hz for high-shelf, +% check e.g. fAliasing=2kHz in [Fig2, Sch13] +% Bandwidth_in_Oct - interpolation bandwidth, i.e. shelf knee range +% in octaves, allowed: 0.5, 1, 2, 3, 4 % % Output parameters: -% H - +% H - return complex spectrum at specified frequencies +% after low-/ and high-shelf interpolation - % % GET_SHELVE_LAGRANGE(f,H,FlagSub,fSub,FlagAliasing,fAliasing,Bandwidth_in_Oct) % does an Lagrange interplation to get a shelving filter. This function is used @@ -26,44 +33,41 @@ % 3dB/oct. slope, other driving functions may have other slopes and % different interpolation offsets may be required % -% References: -% F. Schultz, V. Erbes, S. Spors, S. Weinzierl (2013) - "Derivation -% of IIR prefilters for soundfield synthesis using linear secondary -% source distributions", In: Proc. of the International Conference -% on Acoustics AIA-DAGA, p.2372-2375 -% % See also: wfs_iir_prefilter +% +% References: +% Schultz, Erbes, Spors, Weinzierl (2013) - "Derivation of IIR prefilters +% for soundfield synthesis using linear secondary source distributions", +% International Conference on Acoustics (AIA-DAGA), p.2372-2375, +% http://pub.dega-akustik.de/AIA_DAGA_2013/data/articles/000604.pdf %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * % Revision: 07/02/2013 frank.schultz@uni-rostock.de initial development * %***************************************************************************** Hphase = unwrap(angle(H)); %save original phase diff --git a/SFS_general/get_spherical_grid.m b/SFS_general/get_spherical_grid.m index e337e8f3..31b8c3bc 100644 --- a/SFS_general/get_spherical_grid.m +++ b/SFS_general/get_spherical_grid.m @@ -1,142 +1,139 @@ -function [points,weights] = get_spherical_grid(number,conf) -%GET_SPHERICAL_GRID returns grid points and weights -% -% Usage: [points,weights] = get_spherical_grid(number,[conf]) -% -% Input parameters: -% number - number of grid points -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% points - grid points -% weights - integration weights for the grid points -% -% GET_SPHERICAL_GRID(number) returns the points and weights for a grid on a -% sphere. The type of grid is specified by conf.secondary_sources.grid. -% For available grids, have a look at http://github.com/sfstoolbox/data. -% It expects the grid files at SFS_basepath/data/spherical_grids. If the -% desired file is not available on the hard disk, the function tries to -% download it directly from github. -% For conf.secondary_sources.grid='gauss' the grid positions are calculated -% after Ahrens (2012), p. 121 -% -% References: -% J. Ahrens (2012) - "Analytic Methods of Sound Field Synthesis", Springer. -% -% See also: secondary_source_positions, -% weights_for_points_on_a_sphere_rectangle - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input parameters ======================================= -nargmin = 1; -nargmax = 2; -narginchk(nargmin,nargmax); -isargpositivescalar(number); -if nargin. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_general/ifft_real.m b/SFS_general/ifft_real.m deleted file mode 100644 index a997bbc2..00000000 --- a/SFS_general/ifft_real.m +++ /dev/null @@ -1,69 +0,0 @@ -function y = ifft_real(x,N) -%IFFT_REAL computes an ifft for real value signals -% -% Usage: y = ifft_real(x,samples) -% -% Input parameters: -% x - matrix x with signals as columns -% samples - desired length of the output signals -% -% Output parameters: -% y - matrix y with signals as columns -% -% IFFT_REAL(x,samples) computes the ifft of the real signals in x. The signals -% have to be the columns of x. -% -% See also: fft_real, convolution - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ==================================== -nargmin = 2; -nargmax = 2; -narginchk(nargmin,nargmax); -isargmatrix(x); -isargpositivescalar(N); - - -%% ===== Computation ===================================================== -% Force IFFT along dimension 1 -if rem(N,2)==0 - y = [x; flipud(conj(x(2:end-1,:)))]; -else - y = [x; flipud(conj(x(2:end,:)))]; -end; - -y = real(ifft(y,N,1)); - - diff --git a/SFS_general/in2cm.m b/SFS_general/in2cm.m index 5c753efc..6d3bdf95 100644 --- a/SFS_general/in2cm.m +++ b/SFS_general/in2cm.m @@ -3,46 +3,41 @@ % % Usage: y = in2cm(x) % -% Input options: +% Input parameters: % x - input / inches % -% Output options: +% Output parameters: % y - output / cm % -% IN2CM(x) returns the given value x in centimeters. -% % See also: in2px, cm2px, cm2in, px2in, px2cm %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_general/in2px.m b/SFS_general/in2px.m index 1c988c48..984ffb10 100644 --- a/SFS_general/in2px.m +++ b/SFS_general/in2px.m @@ -3,46 +3,41 @@ % % Usage: y = in2px(x) % -% Input options: +% Input parameters: % x - input / inches % -% Output options: +% Output parameters: % y - output / px % -% IN2PX(x) returns the given value x in pixel. -% % See also: in2cm, cm2px, cm2in, px2in, px2cm %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_general/inverse_cht.m b/SFS_general/inverse_cht.m new file mode 100644 index 00000000..2b0c798b --- /dev/null +++ b/SFS_general/inverse_cht.m @@ -0,0 +1,81 @@ +function [A,Phi] = inverse_cht(Am,Nphi) +%INVERSE_CHT inverse circular harmonics transform (ICHT) +% +% Usage: [A,Phi] = inverse_cht(Am,[Nphi]) +% +% Input parameters: +% Am - circular harmonics coefficients [N x (2*M+1)] +% Nphi - number of equi-angular distributed angles, for which the ICHT +% is computed, optional, default: 2*M+1 +% +% Output parameters: +% A - inverse circular harmonics transform [N x Nphi] +% Phi - corresponding angle of the ICHT [1 x Nphi] +% +% See also: pwd_imp_circexp + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 2; +narginchk(nargmin,nargmax); +isargmatrix(Am); +if nargin == nargmin + Nphi = size(Am, 2); +else + isargpositivescalar(Nphi); +end + + +%% ===== Computation ================================================== +M = (size(Am,2)-1)/2; +N = size(Am,1); + +% Implementation of +% ___ +% \ +% A(phi) = /__ A e^(+i*m*n*2*pi/Nphi) +% m=-M..M m + +% Spatial IFFT +A = zeros(N, Nphi); +% this handles cases where Nphi < M +for l=1:N + A(l,:) = sum(buffer(Am(l,:),Nphi),2); +end +A = circshift(A,[0,-M]); % m = 0, ..., M, ..., -M, ..., -1 +A = ifft(A,[],2) * Nphi; % IFFT includes factor 1/Nphi + +% Axis corresponding to ICHT +if nargout>1 + Phi = 0:2*pi / Nphi:2*pi*(1-1/Nphi); +end diff --git a/SFS_general/inverse_lt.m b/SFS_general/inverse_lt.m new file mode 100644 index 00000000..0e4fea09 --- /dev/null +++ b/SFS_general/inverse_lt.m @@ -0,0 +1,70 @@ +function A = inverse_lt(Am,x) +%INVERSE_LT inverse Legendre transform (ILT) +% +% Usage: [A,mu] = inverse_lt(Am,Nx) +% +% Input parameters: +% Am - Legendre expansion coefficients [N x M] +% x - values for which the ILT is computed [-1:1], [1 x Nx] +% +% Output parameters: +% A - ILT corresponding to mu [N x Nx] +% +% See also: inverse_cht + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2016 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 2; +nargmax = 2; +narginchk(nargmin,nargmax); +isargmatrix(Am); +isargvector(x); + +%% ===== Computation ================================================== +M = (size(Am,2)-1)/2; +N = size(Am,1); +Nx = length(x); + +x = x(:).'; % ensure row vector + +% Implementation of +% ___ +% \ 2m+1 +% A(x) = /__ ------ A P (x) +% m=0..M 2 m m +% +% with P_m(x) being the mth-order Legendre polynomial + +A = zeros(N, Nx); +for m=0:M + A = A + bsxfun(@times, Am(:,m+1), (2.*m+1)./2.*asslegendre(m,0,x)); +end diff --git a/SFS_general/is_dim_custom.m b/SFS_general/is_dim_custom.m new file mode 100644 index 00000000..2bd1c0c7 --- /dev/null +++ b/SFS_general/is_dim_custom.m @@ -0,0 +1,53 @@ +function bool = is_dim_custom(varargin) +%IS_DIM_CUSTOM true for a custom grid +% +% Usage: bool = is_grid_custom(x1,x2,...) +% +% Input parameters: +% x1,x2,... - axis / m; single value or [xmin,xmax] or nD-array +% +% Output parameters: +% bool - array of logical indicating whether each input is an +% nD-array +% +% IS_DIM_CUSTOM(x1,x2,..) checks if we have a custom grid by checking if any +% of the given x,y,z values is a nD-array. +% +% See also: xyz_grid, xyz_axes_selection, plot_sound_field + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking input parameters ======================================= +isargnumeric(varargin{:}); + + +%% ===== Computation ===================================================== +bool = cellfun(@(x) numel(x)>2, varargin); diff --git a/SFS_general/is_dim_singleton.m b/SFS_general/is_dim_singleton.m new file mode 100644 index 00000000..4efa3227 --- /dev/null +++ b/SFS_general/is_dim_singleton.m @@ -0,0 +1,50 @@ +function bool = is_dim_singleton(varargin) +%IS_DIM_SINGLETON true for a singleton axis dimension +% +% Usage: bool = is_dim_singleton(x1,x2,...) +% +% Input parameters: +% x1,x2,... - axis / m; single value or [xmin,xmax] or nD-array +% +% Output parameters: +% bool - array of logical indicating whether each input is a +% singleton dimension +% +% See also: is_dim_custom, xyz_axes_selection, plot_sound_field + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking input parameters ======================================= +isargnumeric(varargin{:}); + + +%% ===== Computation ===================================================== +bool = cellfun(@(x) numel(x) <= 2 && x(1) == x(end), varargin); diff --git a/SFS_general/iseven.m b/SFS_general/iseven.m index d285b663..1a1b13d4 100644 --- a/SFS_general/iseven.m +++ b/SFS_general/iseven.m @@ -1,61 +1,49 @@ -function bool = iseven(number) -%ISEVEN returns true for even integer -% -% Usage: bool = iseven(number) -% -% Input parameters: -% number - number (or vector/matrix with numbers) to be tested -% -% Output parameters: -% bool - true if the number is even, false else -% -% ISEVEN(number) checks if the given number is even. -% -% See also: isodd - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input parameters ======================================= -nargmin = 1; -nargmax = 1; -narginchk(nargmin,nargmax); -isargmatrix(number); - - -%% ===== Computation ===================================================== -% Create answer -bool = false( size(number) ); -% Look for even numbers, use bitget to overcome a mod() bug, see -% http://bit.ly/1wcNYBI -bool(bitget(number,1)==0) = true; +function bool = iseven(number) +%ISEVEN true for even integer +% +% Usage: bool = iseven(number) +% +% Input parameters: +% number - number (or vector/matrix with numbers) to be tested +% +% Output parameters: +% bool - true if the number is even, false else +% +% See also: isodd + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Computation ===================================================== +% Create answer +bool = false( size(number) ); +% Look for even numbers, use bitget to overcome a mod() bug, see +% https://bit.ly/1wcNYBI +bool(bitget(number,1)==0) = true; diff --git a/SFS_general/ismonoinc.m b/SFS_general/ismonoinc.m index 72163a71..221e788b 100644 --- a/SFS_general/ismonoinc.m +++ b/SFS_general/ismonoinc.m @@ -1,63 +1,58 @@ -function bool = ismonoinc(x) -%ISMONOINC checks if the data of x are monotonic increasing -% -% Usage: bool = ismonoinc(x) -% -% Input parameter: -% x - data vector -% -% Output parameter: -% bool - boolean value -% -% ISMONOTONIC(x) checks if the data in vector x are monotonic increasing. -% -% See also: intpol_ir - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 1; -narginchk(nargmin,nargmax); -isargvector(x); - - -%% ===== Computation ==================================================== -bool = true; -for i = 2:length(x) - if x(i). * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input parameters ======================================= -nargmin = 1; -nargmax = 1; -narginchk(nargmin,nargmax); -isargmatrix(number) - - -%% ===== Computation ===================================================== -% Create answer -bool = false( size(number) ); -% Look for odd numbers, use bitget() to overcome a mod() bug, see -% http://bit.ly/1wcNYBI -bool(bitget(number,1)==1) = true; +function bool = isodd(number) +%ISODD true for odd integer +% +% Usage: bool = isodd(number) +% +% Input parameters: +% number - number (or vector/matrix with numbers) to be tested +% +% Output parameters: +% bool - true if the number is odd, false else +% +% See also: iseven + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Computation ===================================================== +% Create answer +bool = false( size(number) ); +% Look for odd numbers, use bitget() to overcome a mod() bug, see +% https://bit.ly/1wcNYBI +bool(bitget(number,1)==1) = true; diff --git a/SFS_general/lagrange_filter.m b/SFS_general/lagrange_filter.m new file mode 100644 index 00000000..1982cc53 --- /dev/null +++ b/SFS_general/lagrange_filter.m @@ -0,0 +1,61 @@ +function b = lagrange_filter(Norder,fdt) +%LAGRANGE_FILTER Lagrange interpolation filter for fractional delays +% +% Usage: b = lagrange_filter(order,fdt) +% +% Input parameter: +% order - order N of Lagrange polynomials +% fdt - vector of fractional delays +% 0 <= fdt < 1 if order is odd, +% -0.5 <= fdt < 0.5 if order is even. +% +% Output parameter: +% b - filter coefficients / [order+1 x Nfdt] +% +% See also: delayline, thiran_filter + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Computation ===================================================== + +D = fdt(:).' + floor(Norder/2); + +% aux = D, (D-1), (D-2),...,(D-N+1),(D-N) +aux = bsxfun(@minus, D, (0:Norder).'); + +% denom = n*(n-1)*...*(n-N+1)*(n-N) = n!*(N-n)!*(-1)^(N-n) +denom = factorial(0:Norder); +denom = denom.*denom(end:-1:1).*(-1).^(Norder:-1:0); + +b = zeros(Norder+1, length(D)); +for ndx=1:Norder+1 + b(ndx,:) = prod(aux([1:ndx-1,ndx+1:end],:), 1)./denom(ndx); +end diff --git a/SFS_general/legpts.m b/SFS_general/legpts.m index 2638a1a6..4ceaa763 100644 --- a/SFS_general/legpts.m +++ b/SFS_general/legpts.m @@ -1,304 +1,304 @@ -function [x w v] = legpts(n,int,meth) -%LEGPTS Legendre points and Gauss Quadrature Weights. -% -% LEGPTS(N) returns N Legendre points X in (-1,1). -% -% [X,W] = LEGPTS(N) returns also a row vector W of weights for Gauss quadrature. -% -% LEGPTS(N,D) scales the nodes and weights for the domain D. D can be -% either a domain object or a vector with two components. If the interval -% is infinite, the map is chosen to be the default 'unbounded map' with -% mappref('parinf') = [1 0] and mappref('adaptinf') = 0. -% -% [X,W,V] = LEGPTS(N) returns additionally a column vector V of weights in -% the barycentric formula corresponding to the points X. -% -% [X,W] = LEGPTS(N,METHOD) allows the user to select which method to use. -% METHOD = 'FASTSMALL' uses the recurrence relation for the Legendre -% polynomials and their derivatives to perform Newton iteration -% on the WKB approximation to the roots. -% METHOD = 'FAST' uses the Glaser-Liu-Rokhlin fast algorithm, which -% is much faster for large N. -% METHOD = 'GW' will use the traditional Golub-Welsch eigenvalue method, -% which is maintained mostly for historical reasons. -% By default LEGPTS uses 'FASTSMALL' when N<=256 and FAST when N>256 -% -% See also chebpts and jacpts. - -% Copyright 2011 by The University of Oxford and The Chebfun Developers. -% See http://www.maths.ox.ac.uk/chebfun/ for Chebfun information. -% -% Redistribution and use in source and binary forms, with or without -% modification, are permitted provided that the following conditions are met: -% * Redistributions of source code must retain the above copyright -% notice, this list of conditions and the following disclaimer. -% * Redistributions in binary form must reproduce the above copyright -% notice, this list of conditions and the following disclaimer in the -% documentation and/or other materials provided with the distribution. -% * Neither the name of the University of Oxford nor the names of its -% contributors may be used to endorse or promote products derived from -% this software without specific prior written permission. -% -% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -% ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -% WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -% DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -% ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -% LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -% ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -% 'GW' by Nick Trefethen, March 2009 - algorithm adapted from [1]. -% 'FAST' by Nick Hale, April 2009 - algorithm adapted from [2]. -% -% References: -% [1] G. H. Golub and J. A. Welsch, "Calculation of Gauss quadrature -% rules", Math. Comp. 23:221-230, 1969, -% [2] A. Glaser, X. Liu and V. Rokhlin, "A fast algorithm for the -% calculation of the roots of special functions", SIAM Journal -% on Scientific Computing", 29(4):1420-1438:, 2007. - -% Defaults -interval = [-1,1]; -method = 'default'; - -if n < 0 - error('CHEBFUN:legpts:n','First input should be a positive number.'); -end - -% Return empty vector if n == 0 -if n == 0 - x = []; w = []; v = []; return -end - -% Check the inputs -if nargin > 1 - if nargin == 3 - interval = int; method = meth; - elseif nargin == 2 - if ischar(int), method = int; else interval = int; end - end - if ~any(strcmpi(method,{'default','GW','fast','fastsmall'})) - error('CHEBFUN:legpts:inputs',['Unrecognised input string.', method]); - end - if isa(interval,'domain') - interval = interval.endsandbreaks; - end - if numel(interval) > 2, - warning('CHEBFUN:legpts:domain',... - 'Piecewise intervals not supported and will be ignored.'); - interval = interval([1 end]); - end -end - -% Decide to use GW or FAST -if n == 1 -% Trivial case when N = 1 - x = 0; w = 2; v = 1; -elseif strcmpi(method,'GW') -% GW, see [1] - beta = .5./sqrt(1-(2*(1:n-1)).^(-2)); % 3-term recurrence coeffs - T = diag(beta,1) + diag(beta,-1); % Jacobi matrix - [V,D] = eig(T); % Eigenvalue decomposition - x = diag(D); [x,i] = sort(x); % Legendre points - w = 2*V(1,i).^2; % Quadrature weights - v = sqrt(1-x.^2).*abs(V(1,i))'; % Barycentric weights - v = v./max(v); - - % Enforce symmetry - ii = 1:floor(n/2); x = x(ii); w = w(ii); - vmid = v(floor(n/2)+1); v = v(ii); - if mod(n,2) - x = [x ; 0 ; -x(end:-1:1)]; w = [w 2-sum(2*w) w(end:-1:1)]; - v = [v ; vmid ; v(end:-1:1)]; - else - x = [x ; -x(end:-1:1)]; w = [w w(end:-1:1)]; - v = [v ; v(end:-1:1)]; - end - v(2:2:n) = -v(2:2:end); -elseif (n < 256 && ~strcmpi(method,'fast')) || strcmpi(method,'fastsmall') -% Fastsmall - [x ders] = fastsmall(n); % Nodes and P_n'(x) - w = 2./((1-x.^2).*ders.^2)'; % Quadrature weights - v = 1./ders; v = v./max(abs(v)); % Barycentric weights - if ~mod(n,2), ii = (floor(n/2)+1):n; v(ii) = -v(ii); end -else -% Fast, see [2] - [x ders] = alg0_Leg(n); % Nodes and P_n'(x) - w = 2./((1-x.^2).*ders.^2)'; % Quadrature weights - v = 1./ders; v = v./max(abs(v)); % Barycentric weights - if ~mod(n,2), ii = (floor(n/2)+1):n; v(ii) = -v(ii); end -end - -% Normalise so that sum(w) = 2 -w = (2/sum(w))*w; - -% Rescale to arbitrary interval -if ~all(interval == [-1 1]) - if ~any(isinf(interval)) - % Finite interval - dab = diff(interval); - x = (x+1)/2*dab + interval(1); - w = dab*w/2; - else - % Infinite interval - m = maps(fun,{'unbounded'},interval); % use default map - if nargout > 1 - w = w.*m.der(x.'); - end - x = m.for(x); - x([1 end]) = interval([1 end]); - end -end - -% -------------------- Routines for FAST_SMALL algorithm ------------------ - -function [x PP] = fastsmall(n) - -% Asymptotic formula (WKB) - only positive x. -if mod(n,2), s = 1; else s = 0; end -k = (n+s)/2:-1:1; theta = pi*(4*k-1)/(4*n+2); -x = (1-(n-1)/(8*n^3)-1/(384*n^4)*(39-28./sin(theta).^2)).*cos(theta); - -% Initialise -Pm2 = 1; Pm1 = x; PPm2 = 0; PPm1 = 1; -dx = inf; l = 0; - -% Loop until convergence -while norm(dx,inf) > eps && l < 10 - l = l + 1; - for k = 1:n-1, - P = ((2*k+1)*Pm1.*x-k*Pm2)/(k+1); Pm2 = Pm1; Pm1 = P; - PP = ((2*k+1)*(Pm2+x.*PPm1)-k*PPm2)/(k+1); PPm2 = PPm1; PPm1 = PP; - end - dx = -P./PP; x = x + dx; - Pm2 = 1; Pm1 = x; PPm2 = 0; PPm1 = 1; -end - -% Once more for derivatives -for k = 1:n-1, - P = ((2*k+1)*Pm1.*x-k*Pm2)/(k+1); Pm2 = Pm1; Pm1 = P; - PP = ((2*k+1)*(Pm2+x.*PPm1)-k*PPm2)/(k+1); PPm2 = PPm1; PPm1 = PP; -end - -% Reflect for negative values -x = [-x(end:-1:1+s) x].'; -PP = [PP(end:-1:1+s) PP].'; - - -% -------------------- Routines for FAST algorithm ------------------------ - -function [roots ders] = alg0_Leg(n) % Driver for 'Fast'. - -% Compute coefficients of P_m(0), m = 0,..,N via recurrence relation. -Pm2 = 0; Pm1 = 1; -for k = 0:n-1, P = -k*Pm2/(k+1); Pm2 = Pm1; Pm1 = P; end - -% Get the first roots and derivative values to initialise. -roots = zeros(n,1); ders = zeros(n,1); % Allocate storage -if mod(n,2) % n is odd - roots((n-1)/2) = 0; % Zero is a root - ders((n+1)/2) = n*Pm2; % P'(0) -else % n is even - [roots(n/2+1) ders(n/2+1)] = alg2_Leg(P,n); % Find first root -end - -[roots ders] = alg1_Leg(roots,ders); % Other roots and derivatives - -% ------------------------------------------------------------------------- - -function [roots ders] = alg1_Leg(roots,ders) % Main algorithm for 'Fast' -n = length(roots); -if mod(n,2), N = (n-1)/2; s = 1; else N = n/2; s = 0; end - -% Approximate roots via asymptotic formula. -k = (n-2+s)/2:-1:1; theta = pi*(4*k-1)/(4*n+2); -roots(((n+4-s)/2):end) = (1-(n-1)/(8*n^3)-1/(384*n^4)*(39-28./sin(theta).^2)).*cos(theta); -x = roots(N+1); - -% Number of terms in Taylor expansion. -m = 30; - -% Storage -hh1 = ones(m+1,1); zz = zeros(m,1); u = zeros(1,m+1); up = zeros(1,m+1); - -% Loop over all the roots we want to find (using symmetry). -for j = N+1:n-1 - % Distance to initial approx for next root (from asymptotic foruma). - h = roots(j+1) - x; - - % Recurrence Taylor coefficients (scaled & incl factorial terms). - M = 1/h; % Scaling - c1 = 2*x/M; c2 = 1./(1-x^2); % Some constants - % Note, terms are flipped for more accuracy in inner product calculation. - u([m+1 m]) = [0 ders(j)/M]; up(m+1) = u(m); - for k = 0:m-2 - up(m-k) = (c1*(k+1)*u(m-k)+(k-n*(n+1)/(k+1))*u(m-k+1)/M^2)*c2; - u(m-(k+1)) = up(m-k)/(k+2); - end - up(1) = 0; - - % Newton iteration - hh = hh1; step = inf; l = 0; - while (abs(step) > eps) && (l < 10) - l = l + 1; - step = (u*hh)/(up*hh)/M; - h = h - step; - Mhzz = (M*h)+zz; - hh = [1;cumprod(Mhzz)]; % Powers of h (This is the fastest way!) - hh = hh(end:-1:1); % Flip for more accuracy in inner product - end - - % Update - x = x + h; - roots(j+1) = x; - ders(j+1) = M*(up*hh); - -end - -% Nodes are symmetric. -roots(1:N+s) = -roots(n:-1:N+1); -ders(1:N+s) = ders(n:-1:N+1); - -% ------------------------------------------------------------------------- - -function [x1 d1] = alg2_Leg(Pn0,n) % Find the first root (note P_n'(0)==0) -% Approximate first root via asymptotic formula -k = ceil(n/2); theta = pi*(4*k-1)/(4*n+2); -x1 = (1-(n-1)/(8*n^3)-1/(384*n^4)*(39-28./sin(theta).^2)).*cos(theta); - -m = 30; % Number of terms in Taylor expansion. - -% Recurrence Taylor coefficients (scaled & incl factorial terms). -M = 1/x1; % Scaling -zz = zeros(m,1); u = [Pn0 zeros(1,m)]; up = zeros(1,m+1); % Allocate storage -for k = 0:2:m-2 - up(k+2) = (k-n*(n+1)/(k+1))*u(k+1)/M^2; - u(k+3) = up(k+2)/(k+2); -end -% Flip for more accuracy in inner product calculation. -u = u(m+1:-1:1); up = up(m+1:-1:1); - -% % Note, terms are flipped for more accuracy in inner product calculation. -% zz = zeros(m,1); u = [zeros(1,m) Pn0]; up = zeros(1,m+1); % Allocate storage -% for k = 0:2:m-2 -% up(m-k) = (k-n*(n+1)/(k+1))*u(m-k+1)/M^2; -% u(m-(k+1)) = up(m-k)/(k+2); -% end - -% Newton iteration -x1k = ones(m+1,1); step = inf; l = 0; -while (abs(step) > eps) && (l < 10) - l = l + 1; - step = (u*x1k)/(up*x1k)/M; - x1 = x1 - step; - x1k = [1;cumprod(M*x1+zz)]; % Powers of h (This is the fastest way!) - x1k = x1k(end:-1:1); % Flip for more accuracy in inner product -end - -% Get the derivative at this root, i.e. P'(x1). -d1 = M*(up*x1k); - - +function [x w v] = legpts(n,int,meth) +%LEGPTS Legendre points and Gauss Quadrature Weights. +% +% LEGPTS(N) returns N Legendre points X in (-1,1). +% +% [X,W] = LEGPTS(N) returns also a row vector W of weights for Gauss quadrature. +% +% LEGPTS(N,D) scales the nodes and weights for the domain D. D can be +% either a domain object or a vector with two components. If the interval +% is infinite, the map is chosen to be the default 'unbounded map' with +% mappref('parinf') = [1 0] and mappref('adaptinf') = 0. +% +% [X,W,V] = LEGPTS(N) returns additionally a column vector V of weights in +% the barycentric formula corresponding to the points X. +% +% [X,W] = LEGPTS(N,METHOD) allows the user to select which method to use. +% METHOD = 'FASTSMALL' uses the recurrence relation for the Legendre +% polynomials and their derivatives to perform Newton iteration +% on the WKB approximation to the roots. +% METHOD = 'FAST' uses the Glaser-Liu-Rokhlin fast algorithm, which +% is much faster for large N. +% METHOD = 'GW' will use the traditional Golub-Welsch eigenvalue method, +% which is maintained mostly for historical reasons. +% By default LEGPTS uses 'FASTSMALL' when N<=256 and FAST when N>256 +% +% See also chebpts and jacpts. + +% Copyright 2011 by The University of Oxford and The Chebfun Developers. +% See https://www.maths.ox.ac.uk/chebfun/ for Chebfun information. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% * Redistributions of source code must retain the above copyright +% notice, this list of conditions and the following disclaimer. +% * Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% * Neither the name of the University of Oxford nor the names of its +% contributors may be used to endorse or promote products derived from +% this software without specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +% ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +% WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +% DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +% ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +% LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +% ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +% 'GW' by Nick Trefethen, March 2009 - algorithm adapted from [1]. +% 'FAST' by Nick Hale, April 2009 - algorithm adapted from [2]. +% +% References: +% [1] G. H. Golub and J. A. Welsch, "Calculation of Gauss quadrature +% rules", Math. Comp. 23:221-230, 1969, +% [2] A. Glaser, X. Liu and V. Rokhlin, "A fast algorithm for the +% calculation of the roots of special functions", SIAM Journal +% on Scientific Computing", 29(4):1420-1438:, 2007. + +% Defaults +interval = [-1,1]; +method = 'default'; + +if n < 0 + error('CHEBFUN:legpts:n','First input should be a positive number.'); +end + +% Return empty vector if n == 0 +if n == 0 + x = []; w = []; v = []; return +end + +% Check the inputs +if nargin > 1 + if nargin == 3 + interval = int; method = meth; + elseif nargin == 2 + if ischar(int), method = int; else interval = int; end + end + if ~any(strcmpi(method,{'default','GW','fast','fastsmall'})) + error('CHEBFUN:legpts:inputs',['Unrecognised input string.', method]); + end + if isa(interval,'domain') + interval = interval.endsandbreaks; + end + if numel(interval) > 2, + warning('CHEBFUN:legpts:domain',... + 'Piecewise intervals not supported and will be ignored.'); + interval = interval([1 end]); + end +end + +% Decide to use GW or FAST +if n == 1 +% Trivial case when N = 1 + x = 0; w = 2; v = 1; +elseif strcmpi(method,'GW') +% GW, see [1] + beta = .5./sqrt(1-(2*(1:n-1)).^(-2)); % 3-term recurrence coeffs + T = diag(beta,1) + diag(beta,-1); % Jacobi matrix + [V,D] = eig(T); % Eigenvalue decomposition + x = diag(D); [x,i] = sort(x); % Legendre points + w = 2*V(1,i).^2; % Quadrature weights + v = sqrt(1-x.^2).*abs(V(1,i))'; % Barycentric weights + v = v./max(v); + + % Enforce symmetry + ii = 1:floor(n/2); x = x(ii); w = w(ii); + vmid = v(floor(n/2)+1); v = v(ii); + if mod(n,2) + x = [x ; 0 ; -x(end:-1:1)]; w = [w 2-sum(2*w) w(end:-1:1)]; + v = [v ; vmid ; v(end:-1:1)]; + else + x = [x ; -x(end:-1:1)]; w = [w w(end:-1:1)]; + v = [v ; v(end:-1:1)]; + end + v(2:2:n) = -v(2:2:end); +elseif (n < 256 && ~strcmpi(method,'fast')) || strcmpi(method,'fastsmall') +% Fastsmall + [x ders] = fastsmall(n); % Nodes and P_n'(x) + w = 2./((1-x.^2).*ders.^2)'; % Quadrature weights + v = 1./ders; v = v./max(abs(v)); % Barycentric weights + if ~mod(n,2), ii = (floor(n/2)+1):n; v(ii) = -v(ii); end +else +% Fast, see [2] + [x ders] = alg0_Leg(n); % Nodes and P_n'(x) + w = 2./((1-x.^2).*ders.^2)'; % Quadrature weights + v = 1./ders; v = v./max(abs(v)); % Barycentric weights + if ~mod(n,2), ii = (floor(n/2)+1):n; v(ii) = -v(ii); end +end + +% Normalise so that sum(w) = 2 +w = (2/sum(w))*w; + +% Rescale to arbitrary interval +if ~all(interval == [-1 1]) + if ~any(isinf(interval)) + % Finite interval + dab = diff(interval); + x = (x+1)/2*dab + interval(1); + w = dab*w/2; + else + % Infinite interval + m = maps(fun,{'unbounded'},interval); % use default map + if nargout > 1 + w = w.*m.der(x.'); + end + x = m.for(x); + x([1 end]) = interval([1 end]); + end +end + +% -------------------- Routines for FAST_SMALL algorithm ------------------ + +function [x PP] = fastsmall(n) + +% Asymptotic formula (WKB) - only positive x. +if mod(n,2), s = 1; else s = 0; end +k = (n+s)/2:-1:1; theta = pi*(4*k-1)/(4*n+2); +x = (1-(n-1)/(8*n^3)-1/(384*n^4)*(39-28./sin(theta).^2)).*cos(theta); + +% Initialise +Pm2 = 1; Pm1 = x; PPm2 = 0; PPm1 = 1; +dx = inf; l = 0; + +% Loop until convergence +while norm(dx,inf) > eps && l < 10 + l = l + 1; + for k = 1:n-1, + P = ((2*k+1)*Pm1.*x-k*Pm2)/(k+1); Pm2 = Pm1; Pm1 = P; + PP = ((2*k+1)*(Pm2+x.*PPm1)-k*PPm2)/(k+1); PPm2 = PPm1; PPm1 = PP; + end + dx = -P./PP; x = x + dx; + Pm2 = 1; Pm1 = x; PPm2 = 0; PPm1 = 1; +end + +% Once more for derivatives +for k = 1:n-1, + P = ((2*k+1)*Pm1.*x-k*Pm2)/(k+1); Pm2 = Pm1; Pm1 = P; + PP = ((2*k+1)*(Pm2+x.*PPm1)-k*PPm2)/(k+1); PPm2 = PPm1; PPm1 = PP; +end + +% Reflect for negative values +x = [-x(end:-1:1+s) x].'; +PP = [PP(end:-1:1+s) PP].'; + + +% -------------------- Routines for FAST algorithm ------------------------ + +function [roots ders] = alg0_Leg(n) % Driver for 'Fast'. + +% Compute coefficients of P_m(0), m = 0,..,N via recurrence relation. +Pm2 = 0; Pm1 = 1; +for k = 0:n-1, P = -k*Pm2/(k+1); Pm2 = Pm1; Pm1 = P; end + +% Get the first roots and derivative values to initialise. +roots = zeros(n,1); ders = zeros(n,1); % Allocate storage +if mod(n,2) % n is odd + roots((n-1)/2) = 0; % Zero is a root + ders((n+1)/2) = n*Pm2; % P'(0) +else % n is even + [roots(n/2+1) ders(n/2+1)] = alg2_Leg(P,n); % Find first root +end + +[roots ders] = alg1_Leg(roots,ders); % Other roots and derivatives + +% ------------------------------------------------------------------------- + +function [roots ders] = alg1_Leg(roots,ders) % Main algorithm for 'Fast' +n = length(roots); +if mod(n,2), N = (n-1)/2; s = 1; else N = n/2; s = 0; end + +% Approximate roots via asymptotic formula. +k = (n-2+s)/2:-1:1; theta = pi*(4*k-1)/(4*n+2); +roots(((n+4-s)/2):end) = (1-(n-1)/(8*n^3)-1/(384*n^4)*(39-28./sin(theta).^2)).*cos(theta); +x = roots(N+1); + +% Number of terms in Taylor expansion. +m = 30; + +% Storage +hh1 = ones(m+1,1); zz = zeros(m,1); u = zeros(1,m+1); up = zeros(1,m+1); + +% Loop over all the roots we want to find (using symmetry). +for j = N+1:n-1 + % Distance to initial approx for next root (from asymptotic foruma). + h = roots(j+1) - x; + + % Recurrence Taylor coefficients (scaled & incl factorial terms). + M = 1/h; % Scaling + c1 = 2*x/M; c2 = 1./(1-x^2); % Some constants + % Note, terms are flipped for more accuracy in inner product calculation. + u([m+1 m]) = [0 ders(j)/M]; up(m+1) = u(m); + for k = 0:m-2 + up(m-k) = (c1*(k+1)*u(m-k)+(k-n*(n+1)/(k+1))*u(m-k+1)/M^2)*c2; + u(m-(k+1)) = up(m-k)/(k+2); + end + up(1) = 0; + + % Newton iteration + hh = hh1; step = inf; l = 0; + while (abs(step) > eps) && (l < 10) + l = l + 1; + step = (u*hh)/(up*hh)/M; + h = h - step; + Mhzz = (M*h)+zz; + hh = [1;cumprod(Mhzz)]; % Powers of h (This is the fastest way!) + hh = hh(end:-1:1); % Flip for more accuracy in inner product + end + + % Update + x = x + h; + roots(j+1) = x; + ders(j+1) = M*(up*hh); + +end + +% Nodes are symmetric. +roots(1:N+s) = -roots(n:-1:N+1); +ders(1:N+s) = ders(n:-1:N+1); + +% ------------------------------------------------------------------------- + +function [x1 d1] = alg2_Leg(Pn0,n) % Find the first root (note P_n'(0)==0) +% Approximate first root via asymptotic formula +k = ceil(n/2); theta = pi*(4*k-1)/(4*n+2); +x1 = (1-(n-1)/(8*n^3)-1/(384*n^4)*(39-28./sin(theta).^2)).*cos(theta); + +m = 30; % Number of terms in Taylor expansion. + +% Recurrence Taylor coefficients (scaled & incl factorial terms). +M = 1/x1; % Scaling +zz = zeros(m,1); u = [Pn0 zeros(1,m)]; up = zeros(1,m+1); % Allocate storage +for k = 0:2:m-2 + up(k+2) = (k-n*(n+1)/(k+1))*u(k+1)/M^2; + u(k+3) = up(k+2)/(k+2); +end +% Flip for more accuracy in inner product calculation. +u = u(m+1:-1:1); up = up(m+1:-1:1); + +% % Note, terms are flipped for more accuracy in inner product calculation. +% zz = zeros(m,1); u = [zeros(1,m) Pn0]; up = zeros(1,m+1); % Allocate storage +% for k = 0:2:m-2 +% up(m-k) = (k-n*(n+1)/(k+1))*u(m-k+1)/M^2; +% u(m-(k+1)) = up(m-k)/(k+2); +% end + +% Newton iteration +x1k = ones(m+1,1); step = inf; l = 0; +while (abs(step) > eps) && (l < 10) + l = l + 1; + step = (u*x1k)/(up*x1k)/M; + x1 = x1 - step; + x1k = [1;cumprod(M*x1+zz)]; % Powers of h (This is the fastest way!) + x1k = x1k(end:-1:1); % Flip for more accuracy in inner product +end + +% Get the derivative at this root, i.e. P'(x1). +d1 = M*(up*x1k); + + diff --git a/SFS_general/linkwitz_riley.m b/SFS_general/linkwitz_riley.m new file mode 100644 index 00000000..2cfc6572 --- /dev/null +++ b/SFS_general/linkwitz_riley.m @@ -0,0 +1,113 @@ +function [z,p,k] = linkwitz_riley(n,wc,ftype,domain) +%LINKWITZ_RILEY zero-poles-gain representation of the Linkwitz-Riley filter +% +% Usage: [z,p,k] = linkwitz_riley(n,wc,ftype,[domain]) +% +% Input parameters: +% n - order of filter (only even allowed) +% wc - cutoff frequency, [0..1] for z-Domain, [0..] rad/s in s-Domain +% ftype - filter type {'low','high','all'} +% domain - 's' for analog/Laplace-Domain +% 'z' for digital/z-Domain (default) +% +% Output parameters: +% z - zeros of filter +% p - poles of filter +% k - gain of filter +% +% References: +% Lipshitz and Vanderkooy (1986), "In-Phase Crossover Network Design", +% Journal of the Audio Engineering Society, vol. 34, no. 11, pp. 889-894, +% http://www.aes.org/e-lib/browse.cfm?elib=5237 + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters =================================== +nargmin = 3; +nargmax = 4; +narginchk(nargmin,nargmax); +isargpositivescalar(n,wc); +if mod(n,2) + error('%s: n (%d) is not an even integer.',upper(mfilename),n); +end +isargchar(ftype) +if ~any(strcmp(ftype, {'low', 'high', 'all'})) + error('%s: ftype (%s) is not a supported filter type.',upper(mfilename), ... + ftype); +end +if nargin == nargmin + domain = 'z'; +else + isargchar(domain); + if ~any(strcmp(domain, {'z', 's'})) + error('%s: domain (%s) must be either "z" or "s".',upper(mfilename), ... + domain); + end +end + +%% ===== Computation ===================================================== +switch ftype +case {'low','high'} + % === lowpass or highpass LR Filter (squared Butterworth Filter) === + % See Lipshitz and Vanderkooy (1986), eq. (6) & (12) + [z,p,k] = butter(n/2,wc,ftype,domain); + z = [z(:); z(:)]; % octave creates row vectors + p = [p(:); p(:)]; % octave creates row vectors + k = k.^2; + if strcmp(ftype, 'high') + k = k.*(-1).^(n/2); + end +case 'all' + % === allpass LR Filter (same phase as lowpass and highpass LR Filter) === + % See Lipshitz and Vanderkooy (1986), eq. (11) + [~,p,~] = butter(n/2,wc,'low',domain); + p = p(:); % octave creates row vectors + if strcmp(domain,'z') + z = 1./conj(p); + k = prod(p).*(-1).^(n/2); + else + z = -p; + k = (-1).^(n/2); + end +end + +% Average complex conjugates to make them exactly symmetrical. +% This avoids the following Octave bug: https://savannah.gnu.org/bugs/?49996 +if ~isempty(z) + [~, idx] = sort(imag(z)); + z = z(idx); + z = 0.5*z + 0.5*conj(z(end:-1:1)); +end +if ~isempty(p) + [~, idx] = sort(imag(p)); + p = p(idx); + p = 0.5*p + 0.5*conj(p(end:-1:1)); +end diff --git a/SFS_general/modal_weighting.m b/SFS_general/modal_weighting.m new file mode 100644 index 00000000..15678f62 --- /dev/null +++ b/SFS_general/modal_weighting.m @@ -0,0 +1,156 @@ +function [win,varargout] = modal_weighting(order,Ninv,conf) +%MODAL_WEIGHTING weighting window for modal coefficients +% +% Usage: [win,Win,Ang] = modal_weighting(order,[Ninv],conf) +% +% Input parameters: +% order - half width of weighting window / 1 +% Ninv - number of bins for the inverse circular/spherical +% harmonics tranform (ICHT/ISHT) / 1 +% (optional, default: 2*order+1) +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% win - the window w_n in the discrete domain, only positive n +% (length = order+1) +% Win - ICHT/ISHT of w_n (length = Ninv) +% Ang - angle corresponding to the ICHT/ISHT +% +% MODAL_WEIGHTING(order,Ninv,conf) calculates a weighting window for the +% modal band limitation applied in NFC-HOA and LSFS-SBL. The window type is +% configured in conf.modal_window. Its default setting is a simple +% rectangular window, for other options have a look into SFS_config. win +% may be different for the 2D/2.5D and the 3D case. For the 2D/2.5D case, Win +% is the inverse circular harmonics transform (ICHT) of win with Ang as +% the corresponding azimuth angle equiangularly distributed within [0,2pi). +% For 3D case, Win is the inverse spherical harmonics transform of win. As the +% transform is rotationally symmetric around the z-axis, i.e. independent of +% the azimuth angle, Win corresponds to the polar angles given in Ang. Latter +% are equiangularly distributed within [0,pi]. +% +% See also: driving_function_imp_nfchoa, driving_function_mono_nfchoa +% +% References: +% Kaiser and Schafer (1980) - "On the use of the I0-sinh window for +% spectrum analysis", IEEE Transactions on Acoustics, Speech, and Signal +% Processing, vol. 28, no. 1, pp. 105-107, +% https://doi.org/10.1109/TASSP.1980.1163349 +% +% Daniel, Rault, Polack (1998) "Ambisonics Encoding of Other Audio +% Formats for Multiple Listening Conditions", 105th Convention of the +% Audio Engineering Society, Paper 4795, +% http://www.aes.org/e-lib/browse.cfm?elib=8385 +% +% Zotter and Frank (2012) - "All-Round Ambisonic Panning and Decoding", +% Journal of the Audio Engineering Society, vol. 60, no. 10, pp. 807-820, +% http://www.aes.org/e-lib/browse.cfm?elib=16554 +% +% Van Trees (2002) - "Optimum Array Processing", John Wiley & Sons, +% ISBN 978-0-471-09390-9 + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking input parameters ======================================= +nargmin = 2; +nargmax = 3; +narginchk(nargmin,nargmax); +isargpositivescalar(order); +if nargin alpha*order a cosine shaped + % fade-out is used. Note, the fade-out of the original Tukey window is + % defined such, that the windows is zero for m=order, if alpha~=0. The + % window is modified such that the slope would yield zero for m=order+1 + alpha = conf.modal_window_parameter; + m = ceil((1-alpha)*order):order; + + win = ones(1,order+1); + win(m+1) = 0.5*(1 + cos(pi*(m-(1-alpha).*order)./(alpha*order+1))); +otherwise + error('%s: unknown weighting type (%s)!',upper(mfilename),wtype); +end + +if nargout>1 + if any( strcmp(dim, {'2D', '2.5D'}) ) + % === Inverse Circular Harmonics Transform === + [varargout{1:nargout-1}] = inverse_cht([win(end:-1:2),win],Ninv); + else + % === Inverse Spherical Harmonics Transform === + % For rotationally symmetric kernels this transform is equal to the + % Inverse Legendre Transform (ILT) weighted by 1/2pi. + % See Zotter and Frank (2012), Eq. (7) + Ang = 0:pi/(Ninv-1):pi; % equiangular distributed polar angle + varargout{1} = inverse_lt(win,cos(Ang))./(2*pi); + if nargout>2 + varargout{2} = Ang; + end + end +end diff --git a/SFS_general/nfchoa_order.m b/SFS_general/nfchoa_order.m index b99c9c15..3c99523d 100644 --- a/SFS_general/nfchoa_order.m +++ b/SFS_general/nfchoa_order.m @@ -1,97 +1,91 @@ -function M = nfchoa_order(nls,conf) -%NFCHOA_ORDER returns the maximum order for the spherical harmonics for the -%given number of secondary sources -% -% Usage: M = nfchoa_order(nls,[conf]) -% -% Input parameters: -% nls - number of secondary sources -% -% Output parameters: -% M - spherical harmonics order -% conf - optional configuration struct (see SFS_config) -% -% NFCHOA_ORDER(nls) returns the maximum order of spherical harmonics for the -% given number of secondary sources in order to avoid spectral repetitions -% (spatial aliasing) of the dirving signals. The order is -% -% / nls/2, even nls -% M = < -% \ (nls-1)/2 odd nls -% -% for a circular array and -% _____ -% M = \|nls/2 -% -% for a spherical array. -% -% References: -% J. Ahrens (2012) - "Analytic Methods of Sound Field Synthesis", Springer. -% -% See also: driving_function_imp_nfchoa, driving_function_mono_nfchoa - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input parameters ======================================= -nargmin = 1; -nargmax = 2; -narginchk(nargmin,nargmax); -if nargin==nargmax-1 - conf = SFS_config; -end -isargpositivescalar(nls); -isargstruct(conf); - - -%% ===== Configuration =================================================== -if conf.nfchoa.order - M = conf.nfchoa.order; - return; -end -dimension = conf.dimension; - - -%% ===== Computation ===================================================== -% Get maximum order of spherical harmonics to avoid spatial aliasing -if strcmp('2D',dimension) || strcmp('2.5D',dimension) - % Ahrens (2012), p. 132 - if isodd(nls) - M = (nls-1)/2; - else - M = nls/2; - end -elseif strcmp('3D',dimension) - % Ahrens (2012), p. 125 - M = floor(sqrt(nls/2)); -end +function M = nfchoa_order(nls,conf) +%NFCHOA_ORDER maximum order of spatial band-limited NFC-HOA +% +% Usage: M = nfchoa_order(nls,conf) +% +% Input parameters: +% nls - number of secondary sources +% +% Output parameters: +% M - spherical harmonics order +% conf - configuration struct (see SFS_config) +% +% NFCHOA_ORDER(nls,conf) returns the maximum order of spherical harmonics for +% the given number of secondary sources in order to avoid spectral repetitions +% (spatial aliasing) of the dirving signals. The order is +% +% / nls/2 - 1, even nls +% M = < +% \ (nls-1)/2 odd nls +% +% for a circular array and +% _____ +% M = \|nls/2 +% +% for a spherical array. +% +% See also: driving_function_imp_nfchoa, driving_function_mono_nfchoa +% +% References: +% Ahrens (2012) - "Analytic Methods of Sound Field Synthesis", Springer, +% ISBN 978-3-642-25743-8 + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking input parameters ======================================= +nargmin = 2; +nargmax = 2; +narginchk(nargmin,nargmax); +isargpositivescalar(nls); +isargstruct(conf); + + +%% ===== Configuration =================================================== +if conf.nfchoa.order + M = conf.nfchoa.order; + return; +end +dimension = conf.dimension; + + +%% ===== Computation ===================================================== +% Get maximum order of spherical harmonics to avoid spatial aliasing +if strcmp('2D',dimension) || strcmp('2.5D',dimension) + % Ahrens (2012), p. 132 + if isodd(nls) + M = (nls-1)/2; + else + M = nls/2 - 1; + end +elseif strcmp('3D',dimension) + % Ahrens (2012), p. 125 + M = floor(sqrt(nls/2)); +end diff --git a/SFS_general/norm_signal.m b/SFS_general/norm_signal.m index d953d436..c8b41928 100644 --- a/SFS_general/norm_signal.m +++ b/SFS_general/norm_signal.m @@ -1,5 +1,5 @@ function sig = norm_signal(sig) -%NORM_SIGNAL normalizes the signal to 1-eps +%NORM_SIGNAL normalizes the signal to the range ]-1:1[ % % Usage: sig = norm_signal(sig) % @@ -9,41 +9,35 @@ % Output parameters: % sig - audio signal normalized to -1. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_general/norm_sound_field.m b/SFS_general/norm_sound_field.m deleted file mode 100644 index 04105070..00000000 --- a/SFS_general/norm_sound_field.m +++ /dev/null @@ -1,71 +0,0 @@ -function P = norm_sound_field(P,conf) -%NORM_SOUND_FIELD normalizes the sound field to 1 -% -% Usage: P = norm_sound_field(P,[conf]) -% -% Input options: -% P - sound field -% conf - optional configuration struct (see SFS_config) -% -% Output options: -% P - normalized sound field -% -% NORM_SOUND_FIELD(P,[conf]) normalizes the given sound field P to -% max(abs(P(:))) = 1. -% -% See also: norm_sound_field_at_xref, sound_field_imp - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ==================================== -nargmin = 1; -nargmax = 2; -narginchk(nargmin,nargmax); -isargnumeric(P); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ==================================== -nargmin = 4; -nargmax = 5; -narginchk(nargmin,nargmax); -isargnumeric(P); -isargvector(x,y,z); -if narginxref(1),1); - check_idx(xidx,x,xref(1),'X',resolution); -end -if dimensions(2) - yidx = find(y>xref(2),1); - check_idx(yidx,y,xref(2),'Y',resolution); -end -if dimensions(3) - zidx = find(z>xref(3),1); - check_idx(zidx,z,xref(3),'Z',resolution); -end - -% Scale signal to 1 -if all(dimensions) - scale = abs(P(zidx,yidx,xidx)); -elseif dimensions(1) && dimensions(2) - scale = abs(P(yidx,xidx)); -elseif dimensions(1) && dimensions(3) - scale = abs(P(zidx,xidx)); -elseif dimensions(2) && dimensions(3) - scale = abs(P(zidx,yidx)); -elseif dimensions(1) - scale = abs(P(xidx)); -elseif dimensions(2) - scale = abs(P(yidx)); -elseif dimensions(3) - scale = abs(P(zidx)); -else - scale = 1; -end -P = P/scale; - -end % of function - - -%% ===== Subfunctions ==================================================== -function check_idx(idx,x,xref,str,resolution) - % abs(x(1)-x(end))/resolution gives us the maximum distance between to samples. - % If abs(x(xidx)-xref(1)) is greater this indicates that we are out of our - % bounds - if isempty(idx) || abs(x(idx)-xref)>2*abs(x(1)-x(end))/resolution - error('%s: your used conf.xref is out of your %s boundaries', ... - upper(mfilename),str); - end -end diff --git a/SFS_general/pm_filter.m b/SFS_general/pm_filter.m new file mode 100644 index 00000000..0ae893df --- /dev/null +++ b/SFS_general/pm_filter.m @@ -0,0 +1,69 @@ +function b = pm_filter(order,wpass,wstop) +%PM_FILTER FIR lowpass-filter using the Parks-McClellan Algorithm +% +% Usage: b = pm_filter(order,wpass,wstop) +% +% Input parameter: +% order - order N of filter in original (not upsampled) domain +% wpass - last normalised passband frequency [0..1] +% wstop - first normalised stopband frequency [0..1] +% +% Output parameter: +% b - filter coefficients / [(order+1) x 1] +% +% See also: delayline, thiran_filter + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Computation ===================================================== +persistent pmCachedOrder +persistent pmCachedWpass +persistent pmCachedWstop +persistent pmCachedCoefficients + +if isempty(pmCachedOrder) || pmCachedOrder ~= order ... + || isempty(pmCachedWpass) || pmCachedWpass ~= wpass ... + || isempty(pmCachedWstop) || pmCachedWstop ~= wstop + + A = [1 1 0 0]; + f = [0.0 wpass wstop 1.0]; + + pmCachedOrder = order; + pmCachedWpass = wpass; + pmCachedWstop = wstop; + if ~isoctave + pmCachedCoefficients = firpm(order,f,A).'; + else + pmCachedCoefficients = remez(order,f,A).'; + end +end + +b = pmCachedCoefficients; diff --git a/SFS_general/px2cm.m b/SFS_general/px2cm.m index 5af06ce2..3cac520b 100644 --- a/SFS_general/px2cm.m +++ b/SFS_general/px2cm.m @@ -3,46 +3,41 @@ % % Usage: y = px2cm(x) % -% Input options: +% Input parameters: % x - input / px % -% Output options: +% Output parameters: % y - output / cm % -% PX2CM(x) returns the given value x in centimeters. -% % See also: px2in, in2cm, in2px, cm2px, cm2in %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_general/px2in.m b/SFS_general/px2in.m index afdf416c..9b0890f7 100644 --- a/SFS_general/px2in.m +++ b/SFS_general/px2in.m @@ -3,46 +3,41 @@ % % Usage: y = px2in(x) % -% Input options: +% Input parameters: % x - input / px % -% Output options: +% Output parameters: % y - output / inches % -% PX2IN(x) returns the given value x in inches. -% % See also: px2cm, in2cm, in2px, cm2px, cm2in %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_general/rad.m b/SFS_general/rad.m index f7c8b538..4ba5ca4f 100644 --- a/SFS_general/rad.m +++ b/SFS_general/rad.m @@ -3,46 +3,41 @@ % % Usage: phi = rad(phi) % -% Input options: +% Input parameters: % phi - angle, can be a scalar or matrix / degree % -% Output options: +% Output parameters: % phi - angle / rad % -% RAD(phi) returns the given angles phi in radians. -% % See also: deg %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_general/rotation_matrix.m b/SFS_general/rotation_matrix.m index 54fd25d3..217fb384 100644 --- a/SFS_general/rotation_matrix.m +++ b/SFS_general/rotation_matrix.m @@ -1,103 +1,100 @@ -function R = rotation_matrix(phi,dim,orientation) -%ROTATION_MATRIX returns a 3D rotation matrix for the given angle and dimension -% -% Usage: R = rotation_matrix(phi,[dim,[orientation]]) -% -% Input parameters: -% phi - angle to rotate the given dim dimension vector / rad -% dim - dimension to turn around (default: 3, z-axis) -% orientation - orientation of the rotation, 'clockwise' or -% 'counterclockwise' (default: 'counterclockwise') -% -% Output parameters: -% R - 3x3 rotation matrix to apply to your vector to -% rotate: R*y -% -% -% ROTATION_MATRIX(phi,dimension,orientation) returns a rotation matrix R, -% which is able to rotate a vector around the given dimension about phi. -% -% See also: sin, cos - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 3; -narginchk(nargmin,nargmax); -isargscalar(phi) -if nargin<3 - % Set defualt orientation of the rotation - orientation = 'counterclockwise'; -end -if nargin<2 - % set default rotation dimension to z-axis - dim = 3; -end -isargchar(orientation); -isargpositivescalar(dim); - - -%% ===== Computation ==================================================== -% Rotation matrix (see: http://en.wikipedia.org/wiki/Rotation_matrix) -% get single matrix entries -r1 = cos(phi); -r4 = cos(phi); -if strcmp('counterclockwise',orientation) - r2 = -sin(phi); - r3 = sin(phi); -elseif strcmp('clockwise',orientation) - r2 = sin(phi); - r3 = -sin(phi); -else - error('%s: the given orientation "%s" is not known.', ... - upper(mfilename),orientation); -end -% Fill up matrix to rotate around the given axis -if dim==1 - - R = [1 0 0; ... - 0 r1 r2; ... - 0 r3 r4]; -elseif dim==2 - R = [r1 0 r2; ... - 0 1 0; ... - r3 0 r4]; -elseif dim==3 - R = [r1 r2 0; ... - r3 r4 0; ... - 0 0 1]; -else - error('%s: dim has to be 1,2, or 3 and not %i',upper(mfilename),dim); -end +function R = rotation_matrix(phi,dim,orientation) +%ROTATION_MATRIX 3D rotation matrix +% +% Usage: R = rotation_matrix(phi,[dim,[orientation]]) +% +% Input parameters: +% phi - angle to rotate the given dim dimension vector / rad +% dim - dimension to turn around (default: 3, z-axis) +% orientation - orientation of the rotation, 'clockwise' or +% 'counterclockwise' (default: 'counterclockwise') +% +% Output parameters: +% R - 3x3 rotation matrix to apply to your vector to +% rotate: R*y +% +% +% ROTATION_MATRIX(phi,dimension,orientation) returns a rotation matrix R, +% which is able to rotate a vector around the given dimension about phi. +% +% See also: sin, cos + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 3; +narginchk(nargmin,nargmax); +isargscalar(phi) +if nargin<3 + % Set defualt orientation of the rotation + orientation = 'counterclockwise'; +end +if nargin<2 + % set default rotation dimension to z-axis + dim = 3; +end +isargchar(orientation); +isargpositivescalar(dim); + + +%% ===== Computation ==================================================== +% Rotation matrix (see: https://en.wikipedia.org/wiki/Rotation_matrix) +% get single matrix entries +r1 = cos(phi); +r4 = cos(phi); +if strcmp('counterclockwise',orientation) + r2 = -sin(phi); + r3 = sin(phi); +elseif strcmp('clockwise',orientation) + r2 = sin(phi); + r3 = -sin(phi); +else + error('%s: the given orientation "%s" is not known.', ... + upper(mfilename),orientation); +end +% Fill up matrix to rotate around the given axis +if dim==1 + + R = [1 0 0; ... + 0 r1 r2; ... + 0 r3 r4]; +elseif dim==2 + R = [r1 0 r2; ... + 0 1 0; ... + r3 0 r4]; +elseif dim==3 + R = [r1 r2 0; ... + r3 r4 0; ... + 0 0 1]; +else + error('%s: dim has to be 1,2, or 3 and not %i',upper(mfilename),dim); +end diff --git a/SFS_general/rounded_box.m b/SFS_general/rounded_box.m new file mode 100644 index 00000000..f5d05ffb --- /dev/null +++ b/SFS_general/rounded_box.m @@ -0,0 +1,152 @@ +function [x0,n0,w0] = rounded_box(t,ratio) +%ROUNDED_BOX computes position and direction vectors in 3D given a parameter +% indicating the position on the boundary of a box with rounded corners. +% +% Usage: [x0,n0,w0] = rounded_box(t,ratio) +% +% Input parameters: +% t - parameter indicating position on the boundary [1 x n] +% ratio - ratio between bending radius of the rounded corners and the +% half edge length of the rectangular bounding box (0,1) +% +% Output parameters: +% x0 - positions [n x 3] +% n0 - unit vector for boundaries normal vector [n x 3] +% w0 - weights for integration [n x 1] +% +% The box has rectangular bounding box in the horizontal plane with an edge +% length of 2 and its center at [0,0,0]. Choosing 0.0 for ratio leads to a +% square, while 1.0 yields a circle. +% +% The parameter t indicates the position on the boundary starting for t=0 +% yielding x0=[1,0,0] and following the boundary in a counter-clockwise +% manner. This function is periodic with respect to t with a period of 1. +% Given two parameters t1 and t2=t1+delta, this function yields two positions +% x01=rounded_box(t1, ratio) and x02=rounded_box(t2, ratio), whose distance +% ALONG THE BOUNDARY of the box is rounded_box(delta, ratio). +% +% n0 is orthogonal to the boundary and is pointing inwards the box. However, +% for ratio=1 and t=1/8, 3/8, 5/8, ..., i.e a location in a corner of a +% square, n0 has an angle of 45 degree to the adjacent edges of the box. +% +% For a correct computation of the integration weights the elements have +% to be sorted, either in ascending or descending order. It is further +% assumed, that the last element of t is the "left" neighbor of the first +% element. The weights are computed on the distance of neighboring elements +% ALONG THE BOUNDARY of the box. +% +% See also: secondary_source_positions + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + +%% ===== Checking of input parameters ======================================= +nargmin = 2; +nargmax = 2; +narginchk(nargmin,nargmax); +isargpositivescalar(ratio); +isargvector(t); + +if ratio > 1.0 + error('%s: ratio has to be between 0.0 and 1.0', upper(mfilename)); +end + +%% ===== Variables =========================================================== + +N = length(t); + +ratio_prime = (1.0 - ratio); + +% the rounded box can be divided into four quarters, where each can be handled +% in the same manner and is rotated afterwards +rot_ind = mod( floor(t*4), 4 ) + 1; % index for rotating +tseg = mod(t, 0.25)*4; % map t to a single quarter + +% length of a quarter of the rounded box +% (quarter circle + 2*linear segment); +l = pi/2*ratio + 2*ratio_prime; + +circle = ratio_prime./l; % value of t, where circular segment begins +circle_prime = 1.0 - circle; % value t, where circular segment ends + +%% ===== Positions & Orientations ============================================ + +x0 = zeros(N, 3); +n0 = zeros(N, 3); + +%%%%% first linear segment %%%%% +seglin1 = ( tseg < circle ); +% x0 = [1.0, t*l, 0] +x0(seglin1, 1) = 1.0; +x0(seglin1, 2) = tseg(seglin1)*l; +% n0 = [-1.0, 0, 0] +n0(seglin1, 1) = -1.0; + +%%%%% second linear segment %%%%% +seglin2 = ( tseg > circle_prime ); +% x0 = [(1.0-t)*l, 1.0, 0] +x0(seglin2 , 1) = ( 1.0 - tseg(seglin2) ) * l; +x0(seglin2 , 2) = 1.0; +% n0 = [0, -1.0, 0] +n0(seglin2, 2) = -1.0; + +%%%%% circular segment %%%%% +segcirc = ~( seglin1 | seglin2 ); +if ratio == 0 + phi = pi/4; +else + phi = (tseg(segcirc) - circle)./(circle_prime - circle)*pi/2; +end +% x0 = circle_center + ratio*[cos(phi), sin(phi), 0] +x0(segcirc, 1) = ratio_prime + ratio*cos(phi); +x0(segcirc, 2) = ratio_prime + ratio*sin(phi); +% n0 = [-cos(phi), -sin(phi), 0] +n0(segcirc, 1) = -cos(phi); +n0(segcirc, 2) = -sin(phi); + +% rotate quarters +rotx = [1, 0, 0; 0,-1, 0;-1, 0, 0; 0, 1, 0]; +roty = [0, 1, 0; 1, 0, 0; 0,-1, 0;-1, 0, 0]; + +x0(:,1:2) = [sum( x0 .* rotx(rot_ind, :), 2), sum( x0 .* roty(rot_ind, :), 2)]; +n0(:,1:2) = [sum( n0 .* rotx(rot_ind, :), 2), sum( n0 .* roty(rot_ind, :), 2)]; + +%% ===== Weights ============================================================= + +% Distance between adjacent samples. This takes the special geometry into +% account and is faster than using the more general secondary_source_distance() +% function. +dist = mod( t - t([N,1:N-1]), 1); % distance to neighbor +dist = min( abs(dist), abs(1 - dist) ); % take periodicity into account +% Half of the distance to the "left" and half of the distance to the +% "right" neighbor +w0 = ( 0.5*dist + 0.5*dist([2:N,1]) )*4*l; +w0 = w0.'; + +end diff --git a/SFS_general/row_vector.m b/SFS_general/row_vector.m index 2e764531..3c4aae12 100644 --- a/SFS_general/row_vector.m +++ b/SFS_general/row_vector.m @@ -1,61 +1,55 @@ -function varargout = row_vector(varargin) -%ROW_VECTOR transforms the given vector to a row vector -% -% Usage: [x1,x2,...] = row_vector(x1,x2,...) -% -% Input parameters: -% x1,x2,... - one or more vectors -% -% Output parameters: -% x1,x2,... - input vectors as row vectors -% -% ROW_VECTOR(x1,x2,...) returns the given vectors x1,x2,... as row -% vectors. -% -% See also: column_vector - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters =================================== -isargvector(varargin{:}); - - -%% ===== Computation ===================================================== -for ii = 1:nargin - if size(varargin{ii},2) 2 + error('%s: only audio data with [NFrames x NChannels] supported', ... + upper(mfilename)); +end + +%% +[NFrames, NChannels] = size(y); % Number of Frames and Channels +NSamples = NFrames*NChannels; % total Samples +Nbits = 32; % 32 floating point +Nbyte = 4; % bytes per Samples + +fileID = fopen(filename,'w', 'ieee-le'); % open wav-file (little Endian) + +fwrite(fileID, 'RIFF', 'char*1'); % RIFF header +% number of bytes following (chunk size) +Noverallbytes = 4 + 4; % for 'WAVE' and 'fmt ' +Noverallbytes = Noverallbytes + 4; % for the number of bytes in 'fmt ' +Noverallbytes = Noverallbytes + 16; % bytes in 'fmt ' +Noverallbytes = Noverallbytes + 12; % for 'fact' +Noverallbytes = Noverallbytes + 8 + Nbyte*NSamples; % 'data' chunk +fwrite(fileID, Noverallbytes, 'uint32'); + +fwrite(fileID, 'WAVE', 'char*1'); % WAVE header + +%% fmt chunk +fwrite(fileID, 'fmt ', 'char*1'); % mind the whitespace! +fwrite(fileID, 16, 'uint32'); % number of bytes following (chunk size) +fwrite(fileID, 3, 'uint16'); % data type (3 for float) +fwrite(fileID, NChannels, 'uint16'); % number of channels +fwrite(fileID, fs, 'uint32'); % samplerate +fwrite(fileID, fs * NChannels * Nbyte, 'uint32'); % bytes per second +fwrite(fileID, NChannels * Nbyte, 'uint16'); % frame size +fwrite(fileID, Nbits, 'uint16'); % bits per sample + +%% fact chunk (floating point only) +fwrite(fileID, 'fact', 'char*1'); +fwrite(fileID, 4, 'uint32'); % number of bytes following (chunk size) +fwrite(fileID, NFrames, 'uint32'); % number of frames + +%% data chunk +fwrite(fileID, 'data', 'char*1'); +fwrite(fileID, Nbyte*NSamples, 'uint32'); % number of bytes following (chunk size) +y = y.'; % prepare data for interlacing +fwrite(fileID, y(:), 'float32'); % interlaced data + +%% +fclose(fileID); + +end \ No newline at end of file diff --git a/SFS_general/secondary_source_amplitudecorrection.m b/SFS_general/secondary_source_amplitudecorrection.m deleted file mode 100644 index ffcad509..00000000 --- a/SFS_general/secondary_source_amplitudecorrection.m +++ /dev/null @@ -1,71 +0,0 @@ -function x0 = secondary_source_amplitudecorrection(x0) -%SECONDARY_SOURCE_AMPLITUDECORRECTION corrects amplitude of secondary sources -% -% Usage: x0 = secondary_source_amplitudecorrection(x0) -% -% Input parameters: -% x0 - secondary sources [n 7] / m -% -% Output options: -% x0 - secondary sources / m, containing the applied amplitude -% correction in its weights in x0(:,7) -% -% SECONDARY_SOURCE_AMPLITUDECORRECTION(x0) -% FIXME: add comment -% -% See also: driving_function_mono_localwfs, driving_function_imp_localwfs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 1; -narginchk(nargmin,nargmax), -isargsecondarysource(x0); - - -%% ===== Calculation ==================================================== -if size(x0,1) < 3 - % Nothing to normalize, if array is to small - return; -end - -xd = vector_norm(x0(2:end,1:3) - x0(1:end-1,1:3),2); -xd = xd./sum(xd,1); - -x0(1,7) = xd(1); -x0(2:end-1,7) = xd(1:end-1) + xd(2:end); -x0(end,7) = xd(end); - -x0(:,7) = x0(:,7)./2; diff --git a/SFS_general/secondary_source_diameter.m b/SFS_general/secondary_source_diameter.m new file mode 100644 index 00000000..01c57110 --- /dev/null +++ b/SFS_general/secondary_source_diameter.m @@ -0,0 +1,90 @@ +function [diam,center] = secondary_source_diameter(conf) +%SECONDARY_SOURCE_DIAMETER diameter and center of secondary sources +% +% Usage: [diam,center] = secondary_source_diameter(conf) +% +% Input parameters: +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% diam - diameter of secondary source distribution / m +% center - center of the ball containing SSD / m [1x3] +% +% SECONDARAY_SOURCE_DIAMETER(conf) calculates the maximum +% Euklidian distance between the given secondary sources. Additionaly, +% the center of the encompassing ball is returned. If one of the predefined +% secondary source distributions 'linear', 'circular', or 'spherical' is used, +% the returned diameter is equal to conf.secondary_sources.size. +% If 'box' or 'rounded-box' is used, the diameter of the bounding box +% is returned. +% +% See also: driving_function_imp_wfs, secondary_source_positions + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); +isargstruct(conf); + + +%% ===== Configuration ================================================== +geometry = conf.secondary_sources.geometry; + + +%% ===== Calculation ==================================================== +if strcmp('line',geometry) || strcmp('linear',geometry) || ... + strcmp('circle',geometry) || strcmp('circular',geometry) || ... + strcmp('sphere',geometry) || strcmp('spherical',geometry) + diam = conf.secondary_sources.size; + center = conf.secondary_sources.center; +elseif strcmp('box',geometry) + dx0 = conf.secondary_sources.size/(conf.secondary_sources.number/4-1); + diam = (conf.secondary_sources.size+dx0)*sqrt(2); + center = conf.secondary_sources.center; +elseif strcmp('rounded-box',geometry) + diam = (conf.secondary_sources.size)*sqrt(2); + center = conf.secondary_sources.center; +else + x0 = conf.secondary_sources.x0; + if isempty(x0) + error(['%s: conf.secondary_sources.x0 must contain the secondary ',... + 'sources when using geometry %s.'],upper(mfilename),geometry); + end + % Find source1 := source with largest distance from origin + [~,idx1] = max(vector_norm(x0(:,1:3),2)); + % Find source2 := source with maximum distance to source1 + [diam,idx2] = max(vector_norm(x0(:,1:3) - ... + repmat(x0(idx1,1:3),[size(x0,1),1]),2)); + % Center is half-way between source1 and source2 + center = x0(idx1,1:3) + 0.5 * (x0(idx2,1:3) - x0(idx1,1:3)); +end diff --git a/SFS_general/secondary_source_distance.m b/SFS_general/secondary_source_distance.m index 8558b042..f1225c4e 100644 --- a/SFS_general/secondary_source_distance.m +++ b/SFS_general/secondary_source_distance.m @@ -1,93 +1,89 @@ -function [dx0,dx0_single] = secondary_source_distance(x0,approx) -%SECONDARY_SOURCE_DISTANCE calculates the average distance between the secondary -%sources -% -% Usage: dx0 = secondary_source_distance(x0,[approx]) -% -% Input parameters: -% x0 - secondary sources / m -% approx - flag (0/1). If set only the first 100 secondary sources -% are used to calculate the distance. This can speed up a -% lot the calculation if you are using many secondary -% sources. Default: 0. -% -% Output parameters: -% dx0 - average distance of secondary sources / m -% dx0_single - vector containing the minimum distances of -% all secondary sources to the other ones / m -% -% SECONDARAY_SOURCE_DISTANCE,approx(x0) calculates the average distance dx0 -% between the given secondary sources. First, the distance to its nearest -% source is calculated for every single secondary source, afterwads the mean -% about these values is returned. -% -% See also: aliasing_frequency, secondary_source_positions - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 2; -narginchk(nargmin,nargmax), -isargsecondarysource(x0); -if nargin==nargmax-1 - approx = false; -end - - -%% ===== Calculation ==================================================== -% Calculate the distance to the nearest secondary source for all secondary -% sources -if size(x0,1)==1 - % If we have only one speaker - dx0 = Inf; -else - if approx - % Approximate by using only the first <=100 sources - x0 = x0(1:min(100,size(x0,1)),:); - end - dx0_single = zeros(size(x0,1),1); - for ii=1:size(x0,1) - % First secondary source position - x01 = x0(ii,1:3); - % All other positions - x02 = [x0(1:ii-1,1:3); x0(ii+1:end,1:3)]; - % Get distance between x01 and all secondary sources within x02 - dist = vector_norm(bsxfun(@minus,x02,x01),2); - % Get the smallest distance (which is the one to the next source) - dx0_single(ii) = min(dist); - end - % Get the mean distance between all secondary sources - dx0 = mean(dx0_single); -end +function [dx0,dx0_single] = secondary_source_distance(x0,approx) +%SECONDARY_SOURCE_DISTANCE average distance between secondary sources +% +% Usage: dx0 = secondary_source_distance(x0,[approx]) +% +% Input parameters: +% x0 - secondary sources / m +% approx - flag (0/1). If set only the first 100 secondary sources +% are used to calculate the distance. This can speed up a +% lot the calculation if you are using many secondary +% sources. Default: 0. +% +% Output parameters: +% dx0 - average distance of secondary sources / m +% dx0_single - vector containing the minimum distances of +% all secondary sources to the other ones / m +% +% SECONDARAY_SOURCE_DISTANCE,approx(x0) calculates the average distance dx0 +% between the given secondary sources. First, the distance to its nearest +% source is calculated for every single secondary source, afterwads the mean +% about these values is returned. +% +% See also: aliasing_frequency, secondary_source_positions + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 2; +narginchk(nargmin,nargmax), +isargsecondarysource(x0); +if nargin==nargmax-1 + approx = false; +end + + +%% ===== Calculation ==================================================== +% Calculate the distance to the nearest secondary source for all secondary +% sources +if size(x0,1)==1 + % If we have only one speaker + dx0 = Inf; +else + if approx + % Approximate by using only the first <=100 sources + x0 = x0(1:min(100,size(x0,1)),:); + end + dx0_single = zeros(size(x0,1),1); + for ii=1:size(x0,1) + % First secondary source position + x01 = x0(ii,1:3); + % All other positions + x02 = [x0(1:ii-1,1:3); x0(ii+1:end,1:3)]; + % Get distance between x01 and all secondary sources within x02 + dist = vector_norm(bsxfun(@minus,x02,x01),2); + % Get the smallest distance (which is the one to the next source) + dx0_single(ii) = min(dist); + end + % Get the mean distance between all secondary sources + dx0 = mean(dx0_single); +end diff --git a/SFS_general/secondary_source_positions.m b/SFS_general/secondary_source_positions.m index 703b8f38..0f997b26 100644 --- a/SFS_general/secondary_source_positions.m +++ b/SFS_general/secondary_source_positions.m @@ -1,120 +1,59 @@ function x0 = secondary_source_positions(conf) -%SECONDARY_SOURCE_POSITIONS generates the positions, directions, and weights of -% the secondary sources +%SECONDARY_SOURCE_POSITIONS positions, directions, weights of secondary sources % -% Usage: x0 = secondary_source_positions([conf]) +% Usage: x0 = secondary_source_positions(conf) % -% Input options: -% conf - optional configuration struct (see SFS_config) +% Input parameters: +% conf - configuration struct (see SFS_config) % -% Output options: -% x0 - secondary source positions, directions and weights -% [n 7] / m +% Output parameters: +% x0 - secondary source positions, directions and weights +% [x0 y0 z0 nx0 ny0 nz0 w] / m % % SECONDARY_SOURCES_POSITIONS(conf) generates the positions and directions % x0 of secondary sources for a given geometry % (conf.secondary_sources.geometry) and array size -% (conf.secondary_sources.size). Alternatively, if conf.secondary_sources.x0 -% is set, it returns the positions and directions specified there. +% (conf.secondary_sources.size). Alternatively, if +% conf.secondary_sources.geomrtry is set to 'custom' the field +% conf.secondary_sources.x0 is used to supply x0. It can be a [n 7] matrix +% consiting of n sources or it can be a SOFA file/struct from the source +% positions are extracted. +% % The direction of the sources is given as their unit vectors pointing in the % given direction. For a linear array the secondary sources are pointing % towards the negative y-direction. If you create a linear array with default % position conf.secondary_sources.center = [0 0 0], your listening area is in % the area y<0, which means the y value of conf.xref should also be <0! % -% Default geometry for a linear array: -% -% y-axis -% ^ -% | -% | secondary sources -% | | -% | v -% -------------x--x--x--x--x--x--x--x--x--x--x------------> x-axis -% | | | | | | | | | | | <- secondary source direction -% | -% | -% | -% -% Default geometry for a circular/spherical array: -% -% y-axis -% ^ -% | -% x -% x | x -% \ | / -% x_ | _x -% - | - -% x-_ | _-x -% | -% --------------x---------------------------x------------------> x-axis -% _ | _ -% x- | -x -% _- | -_ -% x | x -% / | \ -% x | x -% x -% | -% -% -% Default geometry for a box-shape array: -% -% y-axis -% ^ -% | -% x x x x x x x -% | | | | | | | -% x-- | --x -% | -% x-- | --x -% | -% x-- | --x -% | -% -------------x-----------------------------x-----------------> x-axis -% | -% x-- | --x -% | -% x-- | --x -% | -% x-- | --x -% | | | | | | | -% x x x x x x x -% | -% -% see also: secondary_source_selection, secondary_source_tapering +% See also: secondary_source_selection, secondary_source_tapering %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** % NOTE: If you wanted to add a new type of loudspeaker array, do it in a way, @@ -123,63 +62,138 @@ %% ===== Checking of input parameters =================================== -nargmin = 0; +nargmin = 1; nargmax = 1; narginchk(nargmin,nargmax); -if nargin x-axis + % | | | | | | | | | | | <- secondary source direction + % | + % | + % + x0 = zeros(nls,7); + x0(:,2) = X0(2); + x0(:,3) = X0(3); + x0(:,5) = -1; % Direction of secondary sources points in -y direction + + if conf.secondary_sources.logspread == 1.0 + % equi-distantant sampling + x0(:,1) = X0(1) + linspace(-L/2,L/2,nls).'; + % Weight each secondary source by the inter-loudspeaker distance + x0(:,7) = L./(nls-1); + else + % the distance between the loudspeakers grows exponentially + % + % L exp(mu*|n|) + C + % x0 = --- * sgn(n) * ----------------- + X0 + % 2 exp(mu*N) + C + % + % odd number of loudspeakers: + % n = -N,...,N and N = (nls-1)/2. + % C = -1 + % even number of loudspeakers: + % n = -N,...,-1,1,...,N and N = nls/2. + % C = -0.5*(exp(mu)+1) + + N = floor(nls/2); + mu = log(conf.secondary_sources.logspread)./(N-1); + if mod(nls,2) % for odd numbers + C = -1; + n = -N:N; + else % for even numbers + C = -0.5*exp(mu) - 0.5; + n = [-N:-1,1:N]; + end + a0 = L/2/(exp(mu.*N)+C); + x0(:,1) = sign(n).*(exp(mu.*abs(n))+C).*a0 + X0(1); + x0(:,7) = exp(mu.*abs(n)).*a0.*mu; + end elseif strcmp('circle',geometry) || strcmp('circular',geometry) % === Circular array === - % Azimuth angles - phi = linspace(0,(2-2/nls)*pi,nls)'; % 0..2pi - %phi = linspace(pi/2,(5/2-2/nls)*pi,nls)'; % pi/2..5/2pi, Room Pinta - % Elevation angles - theta = zeros(nls,1); - % Positions of the secondary sources - [cx,cy,cz] = sph2cart(phi,theta,L/2); - x0(:,1:3) = [cx,cy,cz] + repmat(X0,nls,1); - % Direction of the secondary sources - x0(:,4:6) = direction_vector(x0(:,1:3),repmat(X0,nls,1).*ones(nls,3)); - % Equal weights for all sources - x0(:,7) = ones(nls,1); + % + % y-axis + % ^ + % | + % x + % x | x + % \ | / + % x_ | _x + % - | - + % x-_ | _-x + % | + % ----x---------------------------x------> x-axis + % _ | _ + % x- | -x + % _- | -_ + % x | x + % / | \ + % x | x + % x + % | + % + % 'circle' is special case of 'rounded-box' with fully rounded corners + t = (0:nls-1)/nls; + [x0(:,1:3), x0(:,4:6), x0(:,7)] = rounded_box(t,1.0); % 1.0 for circle + % Scale unit circle and shift center to X0 + x0(:,1:3) = bsxfun(@plus, x0(:,1:3).*L/2, X0); + % Scale weights + x0(:,7) = x0(:,7).*L/2; elseif strcmp('box',geometry) % === Boxed loudspeaker array === + % + % y-axis + % ^ + % | + % x x x x x x x + % | | | | | | | + % x-- | --x + % | + % x-- | --x + % | + % x-- | --x + % | + % ---x-----------------------------x-----> x-axis + % | + % x-- | --x + % | + % x-- | --x + % | + % x-- | --x + % | | | | | | | + % x x x x x x x + % | + % + % 'box' is special case of 'rounded-box' where there is no rounding + % and the sources in the corners are skipped + % % Number of secondary sources per linear array % ensures that nls/4 is always an integer. if rem(nls,4)~=0 @@ -188,35 +202,31 @@ else nbox = nls/4; end - % distance between secondary sources + % Distance between secondary sources dx0 = L/(nbox-1); - % Position and direction of the loudspeakers - % top - x0(1:nbox,1) = X0(1) + linspace(-L/2,L/2,nbox)'; - x0(1:nbox,2) = X0(2) + ones(nbox,1) * L/2 + dx0; - x0(1:nbox,3) = X0(3) + zeros(nbox,1); - x0(1:nbox,4:6) = direction_vector(x0(1:nbox,1:3), ... - x0(1:nbox,1:3)+repmat([0 -1 0],nbox,1)); - % Right - x0(nbox+1:2*nbox,1) = X0(1) + ones(nbox,1) * L/2 + dx0; - x0(nbox+1:2*nbox,2) = X0(2) + linspace(L/2,-L/2,nbox)'; - x0(nbox+1:2*nbox,3) = X0(3) + zeros(nbox,1); - x0(nbox+1:2*nbox,4:6) = direction_vector(x0(nbox+1:2*nbox,1:3), ... - x0(nbox+1:2*nbox,1:3)+repmat([-1 0 0],nbox,1)); - % Bottom - x0(2*nbox+1:3*nbox,1) = X0(1) + linspace(L/2,-L/2,nbox)'; - x0(2*nbox+1:3*nbox,2) = X0(2) - ones(nbox,1) * L/2 - dx0; - x0(2*nbox+1:3*nbox,3) = X0(3) + zeros(nbox,1); - x0(2*nbox+1:3*nbox,4:6) = direction_vector(x0(2*nbox+1:3*nbox,1:3), ... - x0(2*nbox+1:3*nbox,1:3)+repmat([0 1 0],nbox,1)); - % Left - x0(3*nbox+1:nls,1) = X0(1) - ones(nbox,1) * L/2 - dx0; - x0(3*nbox+1:nls,2) = X0(2) + linspace(-L/2,L/2,nbox)'; - x0(3*nbox+1:nls,3) = X0(3) + zeros(nbox,1); - x0(3*nbox+1:nls,4:6) = direction_vector(x0(3*nbox+1:nls,1:3), ... - x0(3*nbox+1:nls,1:3)+repmat([1 0 0],nbox,1)); - % Equal weights for all sources - x0(:,7) = ones(nls,1); + % Length of one edge of the rectangular bounding box + Lbound = L + 2*dx0; + % Index t for the positions on the boundary + t = linspace(-L/2,L/2,nbox)./Lbound; % this skips the corners + t = [t, t+1, t+2, t+3]*0.25; % repeat and shift to get all 4 edges + % 'box' is special case of 'rounded-box' where there is no rounding + [x0(:,1:3), x0(:,4:6), x0(:,7)] = rounded_box(t,0.0); % 0.0 for square + % Scale "unit" box and shift center to X0 + x0(:,1:3) = bsxfun(@plus, x0(:,1:3).*Lbound/2, X0); + % Scale integration weights + x0(:,7) = x0(:,7).*Lbound/2; + % Correct weights of loudspeakers near corners + corners = [1,nbox,nbox+1,2*nbox,2*nbox+1,3*nbox,3*nbox+1,4*nbox]; + x0(corners,7) = (1 + sqrt(2)) *dx0/2; % instead of 3/2 * dx0 +elseif strcmp('rounded-box', geometry) + % Ratio for rounding the edges + ratio = 2*conf.secondary_sources.corner_radius./L; + t = (0:nls-1)/nls; + [x0(:,1:3), x0(:,4:6), x0(:,7)] = rounded_box(t, ratio); + % Scale "unit" rounded-box and shift center to X0 + x0(:,1:3) = bsxfun(@plus, x0(:,1:3).*L/2, X0); + % Scale integration weights + x0(:,7) = x0(:,7).*L/2; elseif strcmp('spherical',geometry) || strcmp('sphere',geometry) % Get spherical grid + weights [points,weights] = get_spherical_grid(nls,conf); @@ -224,13 +234,18 @@ x0(:,1:3) = L/2 * points + repmat(X0,nls,1); % Secondary source directions x0(:,4:6) = direction_vector(x0(:,1:3),repmat(X0,nls,1)); - % Secondary source weights - x0(:,7) = weights; - % Add integration weights (because we integrate over a sphere) to the grid - % weights - [~,theta] = cart2sph(x0(:,1),x0(:,2),x0(:,3)); % get elevation - x0(:,7) = x0(:,7) .* cos(theta); - + % Secondary source weights + distance scaling + x0(:,7) = weights .* L^2/4; +elseif strcmp('custom',geometry) + % Custom geometry defined by conf.secondary_sources.x0. + % This could be in the form of a n x 7 matrix, where n is the number of + % secondary sources or as a SOFA file/struct. + if ischar(conf.secondary_sources.x0) || isstruct(conf.secondary_sources.x0) + x0 = sofa_get_secondary_sources(conf.secondary_sources.x0); + else + x0 = conf.secondary_sources.x0; + end + isargsecondarysource(x0); else error('%s: %s is not a valid array geometry.',upper(mfilename),geometry); end diff --git a/SFS_general/secondary_source_selection.m b/SFS_general/secondary_source_selection.m index be4987b6..8867f1c2 100644 --- a/SFS_general/secondary_source_selection.m +++ b/SFS_general/secondary_source_selection.m @@ -1,9 +1,9 @@ function [x0,idx] = secondary_source_selection(x0,xs,src) -%SECONDARY_SOURCE_SELECTION selects which secondary sources are active +%SECONDARY_SOURCE_SELECTION selects active secondary sources for WFS % % Usage: [x0,idx] = secondary_source_selection(x0,xs,src) % -% Input options: +% Input parameters: % x0 - secondary source positions, directions and weights / m [nx7] % xs - position and for focused sources also direction of the % desired source model / m [1x3] or [1x6] or [mx6] @@ -11,55 +11,49 @@ % 'pw' - plane wave (xs is the direction of the % plane wave in this case) % 'ps' - point source +% 'ls' - line source % 'fs' - focused source % 'vss' - distribution of focused sources for local WFS % -% Output options: +% Output parameters: % x0 - secondary sources / m, containing only the active % ones [mx7] % idx - index of the selected sources from the original x0 % matrix [mx1] % % SECONDARY_SOURCE_SELECTION(x0,xs,src) returns only the active secondary -% sources for the given geometry and virtual source. In addition the index of -% the chosen secondary sources is returned. -% -% References: -% H. Wierstorf, J. Ahrens, F. Winter, F. Schultz, S. Spors (2015) - -% "Theory of Sound Field Synthesis" +% sources for the given geometry and virtual source in WFS. In addition the +% index of the chosen secondary sources is returned. % % See also: secondary_source_positions, secondary_source_tapering %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** @@ -71,21 +65,20 @@ isargchar(src); if strcmp('vss', src) && size(xs,2)~=6 - error(['%s: you have chosen "vss" as source type, then xs has ', ... - 'to be [nx6] including the direction of each virtual secondary', ... - 'source.'], upper(mfilename)); - isargmatrix(xs); + error(['%s: you have chosen "vss" as source type, then xs has ', ... + 'to be [nx6] including the direction of each virtual secondary', ... + 'source.'], upper(mfilename)); + isargmatrix(xs); elseif ~strcmp('vss', src) - isargxs(xs); + isargxs(xs); end - if strcmp('fs',src) && size(xs,2)~=6 error(['%s: you have chosen "fs" as source type, then xs has ', ... - 'to be [1x6] including the direction of the focused source.'], ... + 'to be [1x6] including the direction of the focused source.'], ... upper(mfilename)); -elseif ~strcmp('fs',src) && ~strcmp('vss',src) && size(xs,2)~=3 - error(['%s: for all source types beside "fs" and "vss", the size of xs ', ... - 'has to be [1x3].'],upper(mfilename)); +elseif ~strcmp('fs',src) && ~strcmp('vss',src) && ~strcmp('ls',src) && size(xs,2)~=3 + error(['%s: for all source types beside "fs", "ls" and "vss", ', ... + 'the size of xs has to be [1x3].'],upper(mfilename)); end @@ -94,27 +87,23 @@ x0_tmp = x0; nx0 = x0(:,4:6); x0 = x0(:,1:3); -% Make the size of the xs position the same as the number of secondary sources -% in order to allow x0-xs -xs = repmat(xs,size(x0,1),1); if strcmp('pw',src) % === Plane wave === % direction of the plane wave - nk = bsxfun(@rdivide,xs,vector_norm(xs,2)); + nk = xs; % the length of the vector is not relavant for the selection % Secondary source selection % % / 1, if nk nx0 > 0 % a = < % \ 0, else % - % see Wierstorf et al. (2015), eq.(#wfs:pw:selection) + % https://sfs.rtfd.io/en/3.2/d_wfs/#equation-wfs-secondary-source-selection-plane % - % Direction of plane wave (nxs) is set above - idx = (( vector_product(nk,nx0,2)>=eps )); - x0 = x0_tmp(idx,:); + % Direction of plane wave (nk) is set above + idx = nx0*nk(:) >= eps; -elseif strcmp('ps',src) || strcmp('ls',src) +elseif strcmp('ps',src) % === Point source === % Secondary source selection % @@ -122,11 +111,37 @@ % a = < % \ 0, else % - % see Wierstorf et al. (2015), eq.(#wfs:ps:selection) and - % eq.(#wfs:ls:selection) + % https://sfs.rtfd.io/en/3.2/d_wfs/#equation-wfs-secondary-source-selection-point + % + idx = sum(nx0.*x0,2) - nx0*xs(1:3).' >= -2*eps; + +elseif strcmp('ls',src) + % === Line source === + % Secondary source selection + % + % / 1, if v nx0 > 0 + % a = < + % \ 0, else + % + % where v = x0-xs - nxs, + % and |nxs| = 1. + % + % https://sfs.rtfd.io/en/3.2/d_wfs/#equation-wfs-secondary-source-selection-line % - idx = (( vector_product(x0-xs,nx0,2)>=eps )); - x0 = x0_tmp(idx,:); + %NOTE: We don't check if we are in a 2D or 3D scenario and use xs(4:6) + % whenever it is present. This can only provide problems if you use the + % 2D or 2.5D case together with x0(:,6) ~= 0. + % If you want to avoid this from happening, you have to add conf as a + % parameter to this function and use the following code instead of the + % if-esle-statement: + %[xs,nxs] = get_position_and_orientation_ls(xs,conf); + if size(xs,2)~=6 + nxs = [0 0 1]; + else + nxs = xs(4:6) / norm(xs(4:6),2); + end + v = (x0 - repmat(xs(1:3),[size(x0,1),1]))*(eye(3) - nxs'*nxs); + idx = (vector_product(v,nx0,2) >= -2*eps); elseif strcmp('fs',src) % === Focused source === @@ -137,25 +152,26 @@ % a = < % \ 0, else % - % see Wierstorf et al. (2015), eq.(#wfs:fs:selection) + % https://sfs.rtfd.io/en/3.2/d_wfs/#equation-wfs-secondary-source-selection-focused % - nxs = xs(:,4:6); - xs = xs(:,1:3); - idx = (( vector_product(nxs,xs-x0,2)>=eps )); - x0 = x0_tmp(idx,:); + nxs = xs(4:6); % vector for orientation of focused source + xs = xs(1:3); % vector for position of focused source + idx = xs*nxs(:) - x0*nxs(:) >= eps; + elseif strcmp('vss', src) % === Virtual secondary sources === % Multiple focussed source selection - selector = false(size(x0_tmp,1),1); + idx = false(size(x0_tmp,1),1); for xi=xs' - [~, xdx] = secondary_source_selection(x0_tmp, xi(1:6)', 'fs'); - selector(xdx) = true; + % ~idx tests only the x0, which have not been selected before + idx(~idx) = xi(1:3).'*xi(4:6) - x0(~idx,:)*xi(4:6) >= eps; end - x0 = x0_tmp(selector,:); else error('%s: %s is not a supported source type!',upper(mfilename),src); end +x0 = x0_tmp(idx,:); + if size(x0,1)==0 - warning('%s: 0 secondary sources were selected.',upper(mfilename)); + warning('SFS:x0','%s: 0 secondary sources were selected.',upper(mfilename)); end diff --git a/SFS_general/secondary_source_tapering.m b/SFS_general/secondary_source_tapering.m index 950cfb41..bb8a4a04 100644 --- a/SFS_general/secondary_source_tapering.m +++ b/SFS_general/secondary_source_tapering.m @@ -1,13 +1,13 @@ -function x0 = secondary_source_tapering(x0,varargin) +function x0 = secondary_source_tapering(x0,conf) %SECONDARY_SOURCE_TAPERING applies a tapering window to the secondary sources % % Usage: x0 = secondary_source_tapering(x0,conf) % -% Input options: +% Input parameters: % x0 - secondary sources / m -% conf - optional configuration struct (see SFS_config) +% conf - configuration struct (see SFS_config) % -% Output options: +% Output parameters: % x0 - secondary sources / m, containing the applied tapering % window in its weights in x0(:,7) % @@ -18,44 +18,41 @@ % See also: secondary_source_positions, tapering_window %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 1; +nargmin = 2; nargmax = 2; narginchk(nargmin,nargmax); %% ===== Calculation ==================================================== % Apply tapering window to secondary sources -x0(:,7) = x0(:,7) .* tapering_window(x0,varargin{:}); +x0(:,7) = x0(:,7) .* tapering_window(x0,conf); diff --git a/SFS_general/signal_from_spectrum.m b/SFS_general/signal_from_spectrum.m new file mode 100644 index 00000000..d4f615f4 --- /dev/null +++ b/SFS_general/signal_from_spectrum.m @@ -0,0 +1,117 @@ +function outsig = signal_from_spectrum(amplitude,phase,f,dim,conf) +%SIGNAL_FROM_SPECTRUM time signal from single-sided spectrum +% +% Usage: outsig = signal_from_spectrum(amplitude,phase,f,[dim],conf) +% +% Input parameters: +% amplitude - the single-sided amplitude spectrum +% phase - the single-sided phase spectrum / rad +% f - the corresponding frequency vector +% dim - dimension along which the ifft is performed +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% outsig - one channel audio (time) signal +% +% SIGNAL_FROM_SPECTRUM(amplitude,phase,f,conf) generates the time signal from +% single-sided amplitude and phase spectra using ifft. It is the counterpart +% of SPECTRUM_FROM_SIGNAL and not interchangeable with calling ifft. +% +% See also: spectrum_from_signal, ifft + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking input arguments ======================================== +nargmin = 4; +nargmax = 5; +narginchk(nargmin,nargmax); +if nargin == nargmin + conf = dim; + dim = find(size(amplitude)~=1, 1); % find first non-singleton dimension +else + isargpositivescalar(dim); +end +isargstruct(conf); + +Ndims = ndims(amplitude); +dim = min(dim,Ndims); +amplitude = permute(amplitude, [dim:Ndims, 1:dim-1]); % move dim to first dimension +phase = permute(phase, [dim:Ndims, 1:dim-1]); % move dim to first dimension +s = size(amplitude); +Nx = s(1); +amplitude = reshape(amplitude, Nx, []); % squeeze all other dimensions +phase = reshape(phase, Nx, []); % squeeze all other dimensions + +%% ===== Configuration =================================================== +fs = conf.fs; + + +%% ===== Regenerating wave form from spectrum ============================ +% Provided number of frequency bins +bins = length(f); +if bins ~= Nx + error('%s: size of spectrum does not match length of frequency vector',... + upper(mfilename)); +end + +if f(end) == fs/2 % -> even time signal length + % Length of the signal to generate + samples = 2 * (bins-1); + % Rescaling (see spectrum_from_signal()) + amplitude = [amplitude(1,:); amplitude(2:end-1,:)/2; amplitude(end,:)] ... + * samples; + % Mirror the amplitude spectrum ( 2*pi periodic [0, fs[ ) + amplitude = [amplitude; amplitude(end-1:-1:2,:)]; + % Mirror the phase spectrum and build the inverse (complex conjugate) + phase = [phase; -1 * phase(end-1:-1:2,:)]; + +else % -> odd time signal length + % Length of the signal to generate + samples = 2*bins - 1; + % Rescaling (see signal_from_spectrum) + amplitude = [amplitude(1,:); amplitude(2:end,:)/2] * samples; + % Mirror the amplitude spectrum ( 2*pi periodic [0, fs-bin] ) + amplitude = [amplitude; amplitude(end:-1:2,:)]; + % Mirror the phase spectrum and build the inverse (complex conjugate) + phase = [phase; -1*phase(end:-1:2,:)]; +end + +% Convert to complex spectrum +compspec = amplitude .* exp(1i*phase); + +% Build the inverse fft and assume spectrum is conjugate symmetric +outsig = real(ifft(compspec)); + + +%% ===== Output ========================================================== +% undo reshape and permute +outsig = reshape(outsig, [samples, s(2:end)]); +outsig = permute(outsig, [Ndims-dim+2:Ndims, 1:Ndims-dim+1]); diff --git a/SFS_general/spectrum_from_signal.m b/SFS_general/spectrum_from_signal.m new file mode 100644 index 00000000..ad59b6af --- /dev/null +++ b/SFS_general/spectrum_from_signal.m @@ -0,0 +1,135 @@ +function varargout = spectrum_from_signal(signal,dim,conf) +%SPECTRUM_FROM_SIGNAL single-sided amplitude and phase spectra of signal +% +% Usage: [amplitude,phase,f] = spectrum_from_signal(sig,[dim],conf) +% +% Input parameters: +% signal - multi channel audio (time) signal +% dim - dimension along which the fft is performed +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% amplitude - single-sided amplitude spectrum of the input signal +% phase - single-sided phase spectrum of the input signal / rad +% f - corresponding frequency axis for the spectrum +% => plot(f,amplitude) / Hz +% +% SPECTRUM_FROM_SIGNAL(signal,conf) calculates the single-sided amplitude and +% phase spectra of a time signal by using the fast Fourier transformation. +% In addition to the amplitude and phase, the corresponding frequency axis is +% returned. +% +% See also: signal_from_spectrum, fft + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Check input arguments =========================================== +nargmin = 2; +nargmax = 3; +narginchk(nargmin,nargmax); +if nargin == nargmin + conf = dim; + dim = find(size(signal)~=1, 1); % find first non-singleton dimension +else + isargpositivescalar(dim); +end +isargstruct(conf); + +Ndims = ndims(signal); +dim = min(dim,Ndims); +signal = permute(signal, [dim:Ndims, 1:dim-1]); % move dim to first dimension +s = size(signal); +Nx = s(1); +signal = reshape(signal, Nx, []); % squeeze all other dimensions + +%% ===== Configuration =================================================== +fs = conf.fs; +useplot = conf.plot.useplot; + + +%% ===== Calcualate spectrum ============================================= +% Generate fast fourier transformation (=> complex output) +compspec = fft(signal,[],1); + +% Length of the signal => number of points of fft +bins = size(signal,1); + +if mod(bins,2) % For odd signal length + % Calculate corresponding frequency axis + f = fs/bins * (0:(bins-1)/2)'; + % Get amplitude and phase spectra and use only the first half of the + %>spectrum [0, fs/2[ + amplitude = abs(compspec(1:length(f),:)); + phase = angle(compspec(1:length(f),:)); + % Scale the amplitude (factor two for mirrored frequencies + %>divide by number of bins) + amplitude = [amplitude(1,:); 2*amplitude(2:end,:)] / bins; + +else % For even signal length + % Calculate corresponding frequency axis + f = fs/bins * (0:bins / 2)'; + % Get amplitude and phase spectra and use only the first half of the + %>spectrum [0, fs/2] + amplitude = abs(compspec(1:length(f),:)); + phase = angle(compspec(1:length(f),:)); + % Scale the amplitude (factor two for mirrored frequencies + %>divide by number of bins) + amplitude = [amplitude(1,:); 2*amplitude(2:end-1,:); amplitude(end,:)] / bins; +end + + +%% ===== Plotting ======================================================== +if nargout==0 || useplot + figure; title('Spectrum'); + subplot(2,1,1) + semilogx(f,20 * log10(abs(amplitude))); xlim([1, fs/2]); + grid on; xlabel('frequency / Hz'); ylabel('amplitude / dB') + subplot(2,1,2) + semilogx(f,unwrap(phase,[],1)); xlim([1, fs/2]); + grid on; xlabel('frequency / Hz'); ylabel('phase / rad') +end + + +%% ===== Output ========================================================== +% Return values +if nargout>0 + % undo reshape and permute + amplitude = reshape(amplitude, [length(f), s(2:end)]); + amplitude = permute(amplitude, [Ndims-dim+2:Ndims, 1:Ndims-dim+1]); + varargout{1}=amplitude; +end +if nargout>1 + % undo reshape and permute + phase = reshape(phase, [length(f), s(2:end)]); + phase = permute(phase, [Ndims-dim+2:Ndims, 1:Ndims-dim+1]); + varargout{2}=phase; +end +if nargout>2, varargout{3}=f; end diff --git a/SFS_general/sphbesselh.m b/SFS_general/sphbesselh.m index ee879fa2..07afb39c 100644 --- a/SFS_general/sphbesselh.m +++ b/SFS_general/sphbesselh.m @@ -1,69 +1,63 @@ -function out = sphbesselh(nu,k,z) -% SPHBESSELH spherical hankel function of order nu, kind k, and argument z -% -% Usage: out = sphbesselh(nu,k,z) -% -% Input parameters: -% nu - order of hankel function -% k - kind of hankel function (1 ^= first kind, 2 ^= second kind) -% z - argument of hankel function -% -% Output parameters: -% out - value of hankel function at point z -% -% SPHBESSELH(nu,k,z) spherical hankel function of order nu, kind k, and -% argument z -% -% See also: sphbesselj, sphbessely - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input parameters ======================================= -nargmin = 3; -nargmax = 3; -narginchk(nargmin,nargmax); -isargscalar(nu) -if (k==1) - sign = 1; -elseif (k==2) - sign = -1; -else - error(['%s: Invalid kind of Hankel function is asked ',... - '(k has to be 1 or 2).'],upper(mfilename)); -end -isargnumeric(z) - - -%% ===== Computation ===================================================== -out = sphbesselj(nu, z) + 1j .* sign .* sphbessely(nu, z); +function out = sphbesselh(nu,k,z) +% SPHBESSELH spherical Hankel function of order nu, kind k, and argument z +% +% Usage: out = sphbesselh(nu,k,z) +% +% Input parameters: +% nu - order of Hankel function +% k - kind of Hankel function (1 ^= first kind, 2 ^= second kind) +% z - argument of Hankel function +% +% Output parameters: +% out - value of Hankel function at point z +% +% See also: sphbesselj, sphbessely + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking input parameters ======================================= +nargmin = 3; +nargmax = 3; +narginchk(nargmin,nargmax); +isargscalar(nu) +if (k==1) + sign = 1; +elseif (k==2) + sign = -1; +else + error(['%s: Invalid kind of Hankel function is asked ',... + '(k has to be 1 or 2).'],upper(mfilename)); +end +isargnumeric(z) + + +%% ===== Computation ===================================================== +out = sphbesselj(nu, z) + 1i .* sign .* sphbessely(nu, z); diff --git a/SFS_general/sphbesselh_zeros.m b/SFS_general/sphbesselh_zeros.m index 843e0d46..bc5ab3e8 100644 --- a/SFS_general/sphbesselh_zeros.m +++ b/SFS_general/sphbesselh_zeros.m @@ -1,102 +1,181 @@ -function [z,p] = sphbesselh_zeros(order) -%SPHBESSELH_ZEROS finds zeros/roots of spherical hankel function -% -% Usage: [z,p] = sphbesselh_zeros(order) -% -% Input parameters: -% order - order of hankel function -% -% Output parameters: -% z - zeros/roots fo the Bessel function -% p - roots of the Bessel function -% -% SPHBESSELH_ZEROS(order) finds zeros and roots for a spherical hankel functin -% of the specified order. -% -% See also: sphbesselh, driving_function_imp_nfchoa - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input parameters ======================================= -nargmin = 1; -nargmax = 1; -narginchk(nargmin,nargmax); -isargpositivescalar(order); - - -%% ===== Main ============================================================ -if order<86 - % --- Compute --- - B = zeros(1,order+2); - A = B; - for n=0:order - B(n+1) = factorial(2*order-n)/(factorial(order-n)*factorial(n)*2^(order-n)); - end - B = B(end:-1:1); - % Find zeros/roots - z = roots(B); - % Find roots - A(2) = 1; - p = roots(A); -else - % --- use pre-computed --- - % For orders greater than 85 Matlab/Octave is not able to compute the zeros, - % because the factorial function returns Inf. We solved this by using the - % Multiprecission Toolbox from http://www.advanpix.com and the code given at - % the end of this function. With the Toolbox we were able to compute the - % zeros up to an order of ... and stored the resulting zeros at - % http://github.com/sfstoolbox/data/tree/master/sphbesselh_zeros - filename = sprintf('sphbesselh_zeros_order%04.0f.mat',order); - file = sprintf('%s/data/sphbesselh_zeros/%s',get_sfs_path(),filename); - url = ['https://dev.qu.tu-berlin.de/projects/data/repository/revisions/master/' ... - 'raw/sphbesselh_zeros/' filename]; - % Download file if not present - if ~exist(file,'file') - download_file(url,file); - end - load(file); -end -return - - -%% ===== Computation with Multiprecission Toolbox ======================== -B = mp(zeros(1,order+2)); -A = B; -for n=mp(0:order) - B(n+1) = factorial(2*order-n)/(factorial(order-n)*factorial(n)*2^(order-n)); -end -B = B(end:-1:1); -z = roots(B); -A(2) = mp(1); -p = roots(A); +function [z,p] = sphbesselh_zeros(order) +%SPHBESSELH_ZEROS finds zeros/roots of spherical Hankel function +% +% Usage: [z,p] = sphbesselh_zeros(order) +% +% Input parameters: +% order - order of Hankel function +% +% Output parameters: +% z - zeros/roots fo the Bessel function +% p - roots of the Bessel function +% +% SPHBESSELH_ZEROS(order) finds zeros and poles for a spherical Hankel +% function of the specified order. It is based on the investigations in +% Hahn and Spors (2017) and the Python implementation in from scipy in +% signal.filter_design._bessel_zeros. +% +% See also: sphbesselh, driving_function_imp_nfchoa +% +% References: +% Hahn, Spors (2017) - "Further Investigations on the Design of Radial +% Filters for the Driving Functions of Near-Field Compensated +% Higher-Order Ambisonics", 142nd Convention of the Audio Engineering +% Society, Paper 9732, http://www.aes.org/e-lib/browse.cfm?elib=18609 +% +% Campos, Calderon (2011) - "Approximate closed-form formulas for the +% zeros of the Bessel Polynomials", https://arxiv.org/abs/1105.0957 +% +% This implementation is based on scipy: https://bit.ly/2tPfePn + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking input parameters ======================================= +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); +isargpositivescalar(order); + + +%% ===== Constants ======================================================= +TOL = 1E-15; +MAXITER = 50; + + +%% ===== Main ============================================================ +p = zeros(order,1); % poles are always zero + +if order < 2 + z = -ones(order,1); + return +end + +% Approximate roots of nth-order ordinary Bessel polynomial as starting points +r = campos_zeros(order); + +% Zeros of nth-order ordinary Bessel polynomial y_n are the same as for +% the exponentially scaled modified Bessel function of second kind K_v: +% \sqrt{2pi/x} * exp(1/x) * K_{n+0.5}(1/x) = y_n(x), +% see for example https://bit.ly/2unx63m. +% Hence, we define the target function and its first derivative as +f = @(x) besselk(order+0.5, 1./x, 1); +fp = @(x) besselk(order-0.5, 1./x, 1)./2./x.^2 - ... + besselk(order+0.5, 1./x, 1)./x.^2 + ... + besselk(order+1.5, 1./x, 1)./2./x.^2; + +% Simulataneous root finding using the method of Aberth-Ehrlich method +r = aberth(f,fp,r,TOL,MAXITER); + +% Refine root position using Newton-Raphson method +for idx=1:order + r(idx) = newton(f,fp,r(idx),TOL,MAXITER); +end + +% Average complex conjugates to make them exactly symmetrical +r = 0.5*r + 0.5*conj(r(end:-1:1)); + +% Roots should sum to -1 +if abs(sum(r) + 1) > TOL + error(['%s: Generated roots of the ordinary Bessel polynomial are' ... + ' inaccurate, order=%d'],upper(mfilename),order); +end + +% Zeros are the inverted roots of nth-order ordinary Bessel polynomial +z = 1./r; + +end + + +%% ===== Auxiliary Functions ============================================= +function z0 = campos_zeros(n) + % Approximate roots of ordinary Bessel polynomial of nth order, see + % Campos and Calderon (2011) and https://bit.ly/2txLJyM + + if n == 1 + z0 = -1; + return + end + + % See Campos and Calderon (2011), Eq. (7) + r = polyval( [1 2 0 0],n); % n^3 + n^2 + a1 = polyval( [-6 -6],n) / r; % ( -6n - 6 ) / r + a2 = 6 / r; + + s = polyval( [1 -3 0 2 0 0],n); % n^5 - 3n^4 + 2n^2 + b3 = polyval( [-8 16],n) / s; % ( -8n + 16 ) / s + b2 = polyval( [12 -12 -24],n) / s; % ( 12n^2 - 12n - 24 ) / s + b1 = polyval( [-2 -12 24 8],n) / s; % ( -2n^3 - 12n^2 + 24n + 8 ) / s + b0 = polyval( [-1 5 0 -6 0],n) / s; % ( -n^4 + 5n^3 - 6n ) / s + + % See Campos and Calderon (2011), Eq. (4) + k = (1:n).'; + x0 = polyval( [a2 a1 0],k); % real part + y0 = polyval( [b3 b2 b1 b0],k); % imaginary part + + % See Campos and Calderon (2011), Eq. (8) + z0 = x0 + 1i*y0; + +end + +function x = aberth(f,fp,x0,TOL,MAXITER) + % Ehrlich-Aberth method to simulatenous approximation of roots, + % see https://bit.ly/2sOfeiT + N = length(x0); + beta = zeros(size(x0)); + x = x0; + for iter=1:MAXITER + alpha = -f(x) ./ fp(x); + + for k=1:N + beta(k) = sum(1./(x(k) - x([1:k-1,k+1:N]))); + end + + x = x + alpha./(1 + alpha .* beta); + + if all(abs(alpha) <= TOL) + return + end + end + warning('%s: maximum iterations in aberth() reached; order = %d', ... + upper(mfilename), N); +end + +function x = newton(f,fp,x0,TOL,MAXITER) + % Newton-Rapheson method for approximation of a single root + for iter=1:MAXITER + x = x0 - f(x0) ./ fp(x0); + if abs(x - x0) < TOL + return + end + x0 = x; + end + warning('%s: maximum iterations in newton() reached', upper(mfilename)); +end diff --git a/SFS_general/sphbesselj.m b/SFS_general/sphbesselj.m index fa7c5f46..fc988733 100644 --- a/SFS_general/sphbesselj.m +++ b/SFS_general/sphbesselj.m @@ -10,41 +10,35 @@ % Output parameters: % out - value of bessel function at point z % -% SPHBESSELJ(nu,z) spherical bessel function of order nu, frist type, and -% argument z -% % See also: sphbesselh, sphbessely %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_general/sphbessely.m b/SFS_general/sphbessely.m index 739d15fd..c871d1fb 100644 --- a/SFS_general/sphbessely.m +++ b/SFS_general/sphbessely.m @@ -1,61 +1,54 @@ -function out = sphbessely(nu,z) -% SPHBESSELY spherical bessel function of second kind, of order nu, and -% argument z -% -% Usage: out = sphbesselj(nu,z) -% -% Input parameters: -% nu - order of bessel function -% z - argument of bessel function -% -% Output parameters: -% out - value of bessel function at point z -% -% SPHBESSELY(nu,z) spherical bessel function of order nu, frist type, and -% argument z -% -% See also: sphbesselh, sphbesselj - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input parameters ======================================= -nargmin = 2; -nargmax = 2; -narginchk(nargmin,nargmax); -isargscalar(nu) -isargnumeric(z) - - -%% ===== Computation ===================================================== -out = sqrt(pi./(2.*z)) .* bessely(nu+0.5, z); +function out = sphbessely(nu,z) +%SPHBESSELY spherical bessel function of second kind, of order nu +% +% Usage: out = sphbesselj(nu,z) +% +% Input parameters: +% nu - order of bessel function +% z - argument of bessel function +% +% Output parameters: +% out - value of bessel function at point z +% +% See also: sphbesselh, sphbesselj + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking input parameters ======================================= +nargmin = 2; +nargmax = 2; +narginchk(nargmin,nargmax); +isargscalar(nu) +isargnumeric(z) + + +%% ===== Computation ===================================================== +out = sqrt(pi./(2.*z)) .* bessely(nu+0.5, z); diff --git a/SFS_general/sphharmonics.m b/SFS_general/sphharmonics.m index e3355f7f..199e66f7 100644 --- a/SFS_general/sphharmonics.m +++ b/SFS_general/sphharmonics.m @@ -1,79 +1,74 @@ -function [ Ynm ] = sphharmonics(n,m,theta,phi); -% SPHHARMONICS spherical harmonics function -% -% Usage: Ynm = sphharmonics(n,m,theta,phi) -% -% Input parameters: -% n - spherical harmonic degree -% m - spherical harmonic order -% theta - elevation angle -% phi - azimuth angle -% -% Output parameters: -% Ynm - values of spherical harmonics function -% -% SPHHARMONICS(n,m,theta,phi) spherical harmonics function of degree n and -% order m for the angles phi, theta. -% phi and theta can be arrays but have to be of same size or one of them -% has to be a scalar. -% -% See also: sphbesselj, sphbessely, sphbesselh, asslegendre - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% Copyright (c) 2012 Jens Ahrens * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input parameters ======================================= -nargmin = 4; -nargmax = 4; -narginchk(nargmin,nargmax); -isargpositivescalar(n) -isargscalar(m) -isargnumeric(phi,theta) -if n. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 2; -narginchk(nargmin,nargmax); -isargsecondarysource(x0); -if nargin==nargmax-1 - conf = SFS_config; -end -isargstruct(conf); - - -%% ===== Configuration ================================================== -usetapwin = conf.usetapwin; -tapwinlen = conf.tapwinlen; -geometry = conf.secondary_sources.geometry; - - -%% ===== Calculation ===================================================== -% Number of secondary sources -nls = size(x0,1); -% FIXME: at the moment the tapering window is not working for spherical arrays, -% because we are not able to find the edges of the array. -if usetapwin && nls>2 && ... - ~(strcmp('sphere',geometry)||strcmp('spherical',geometry)) - win = ones(1,nls); - % Get the mean distance between secondary sources and the smallest distance - % to neighbour source for every secondary source. Due to long computing time - % for really large secondary source numbers, the distance is approximated by - % the first 100 (or less) sources. If you don't want this behavior, change - % the following command to dx0 = secondary_source_distance(x0,0); - dx0 = secondary_source_distance(x0,1); - % Use only positions - x0 = x0(:,1:3); - % Find the edges of the array - edges = []; - for ii=1:nls-1 - if norm(x0(ii,:)-x0(ii+1,:))>2*dx0 - edges = [edges; ii; ii+1]; - end - end - if norm(x0(end,:)-x0(1,:))>2*dx0 - edges = [edges; nls; 1]; - end - % If we have any edges in our array apply a tapering window for every array - % part, consiting of two edges - if ~isempty(edges) - % Generate tapwin for every array part within the x0 vector - for ii=2:length(edges)-2 - part_nls = edges(ii+1)-edges(ii)+1; - win(edges(ii):edges(ii+1)) = part_hann_win(part_nls,tapwinlen); - end - % Generate tapwin for every array part consiting of the first and the - % last edge within the x0 vector - if edges(1)==nls - win = part_hann_win(nls,tapwinlen); - else - part_nls = edges(1) + nls-edges(end)+1; - part_win = part_hann_win(part_nls,tapwinlen); - win(1:edges(1)) = part_win(end-edges(1)+1:end); - win(edges(end):end) = part_win(1:end-edges(end)+1); - end - end -else - % If you want to use no tapering window: - win = ones(1,nls); -end - -% Ensure the window will be a column vector -win = column_vector(win); - -end - -function [win] = part_hann_win(nls,tapwinlen) - % Length of window (given by the value of tapwinlen). The window will be - % splitted to both sides of the loudspeaker array. - lenwin = round(tapwinlen*nls)+2; - % - % Check if we have a to short window to apply it in a useful way. This can - % be the case for very short loudspeaker arrays (as used in Wierstorf2010). - if lenwin<4 - win = ones(1,nls); - else - % Create a squared Hann window with length lenwin - win = hann_window(floor((lenwin-2)/2),floor((lenwin-2)/2),nls).^2; - - end -end +function win = tapering_window(x0,conf) +%TAPERING_WINDOW tapering window for secondary sources +% +% Usage: win = tapering_window(x0,conf) +% +% Input parameters: +% x0 - secondary sources / m +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% win - tapering window [nlsx1] +% +% TAPERING_WINDOW(x0,conf) generates a tapering window for a secondary source +% distribution given by x0. The window is created from a squared Hann window. +% The strength of the tapering is controlled by the conf.tapwinlen setting. +% If the secondary source distribution has some gaps, every joint part gets +% its own tapering. +% +% Tapering windows reduce diffraction in the synthesis sound field that +% results from truncated secondary source distributions, see Sect. 3.2 of +% Wierstorf (2014). The diffraction part of the sound field can be described +% by cylindrical waves originating from the edges of the distribution, see +% Sect. 8.3.2 in Born, Wolf (1999). Therefore a good method to reduce +% truncation artifacts in the sound field is to fade out the amplitude of the +% driving function at the edges of the array. +% +% See also: secondary_source_position, sound_field_mono_wfs, hann +% +% +% References: +% +% Born, Wolf (1999) - "Principles of Optics", Cambridge University Press, +% 7th edition, ISBN 9780521642224 +% +% Wierstorf (2014) - "Perceptual Assessment of Sound Field Synthesis", +% TU Berlin, https://doi.org/10.14279/depositonce-4310 + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 2; +nargmax = 2; +narginchk(nargmin,nargmax); +isargsecondarysource(x0); +isargstruct(conf); + + +%% ===== Configuration ================================================== +usetapwin = conf.usetapwin; +tapwinlen = conf.tapwinlen; +geometry = conf.secondary_sources.geometry; + + +%% ===== Calculation ===================================================== +% Number of secondary sources +nls = size(x0,1); +% Standard window with equal weights +win = ones(1,nls); +% FIXME: at the moment the tapering window is not working for spherical arrays, +% see https://github.com/sfstoolbox/sfs-matlab/issues/21 +if usetapwin && nls>2 && ... + ~(strcmp('sphere',geometry) || strcmp('spherical',geometry)) + % Get the mean distance between secondary sources and the smallest distance + % to neighbour source for every secondary source. Due to long computing time + % for really large secondary source numbers, the distance is approximated by + % the first 100 (or less) sources. If you don't want this behavior, change + % the following command to dx0 = secondary_source_distance(x0,0); + dx0 = secondary_source_distance(x0,1); + % Use only positions + x0 = x0(:,1:3); + % === Find the edges of the array === + edges = []; + for ii=1:nls-1 + if norm(x0(ii,:)-x0(ii+1,:))>2*dx0 + edges = [edges; ii; ii+1]; + end + end + if norm(x0(end,:)-x0(1,:))>2*dx0 + edges = [edges; nls; 1]; + end + % === Apply tapering window at all edges === + % If we have any edges in our array apply a tapering window for every array + % part, consisting of two edges + if ~isempty(edges) + if edges(end)==1 + % First and last entry of secondary source is an edge + edges = circshift(edges,[1,0]); + start_idx = 1; + else + % First and last entry of secondary source is not an edge + part_nls = edges(1) + nls-edges(end)+1; + part_win = part_hann_win(part_nls,tapwinlen); + win(1:edges(1)) = part_win(end-edges(1)+1:end); + win(edges(end):end) = part_win(1:end-edges(1)); + start_idx = 2; + end + % Generate tapwin for every array part within the x0 vector + for ii=start_idx:2:length(edges)-1 + part_nls = edges(ii+1)-edges(ii)+1; + win(edges(ii):edges(ii+1)) = part_hann_win(part_nls,tapwinlen); + end + end +end + +% Ensure the window will be a column vector +win = column_vector(win); + +end + +function [win] = part_hann_win(nls,tapwinlen) + % Length of window (given by the value of tapwinlen). The window will be + % splitted to both sides of the loudspeaker array. + lenwin = round(tapwinlen*nls)+2; + % + % If we have less than four secondary sources, the usage of a tapering + % window is no longer desired. + if lenwin<4 + win = ones(1,nls); + else + % Create a squared Hann window with length lenwin + win = hann_window(floor((lenwin-2)/2),floor((lenwin-2)/2),nls).^2; + end +end diff --git a/SFS_general/thiran_filter.m b/SFS_general/thiran_filter.m new file mode 100644 index 00000000..9006f587 --- /dev/null +++ b/SFS_general/thiran_filter.m @@ -0,0 +1,60 @@ +function [b,a] = thiran_filter(Norder,fdt) +%THIRAN_FILTER Thiran's IIR allpass for Maximally Flat Group Delay +% +% Usage: [b,a] = thiran_filter(order,fdt) +% +% Input parameter: +% order - order of filter +% fdt - vector of fractional delays -0.5 <= fdt < 0.5 +% +% Output parameter: +% b - numerator polynomial of H(z) / [Norder+1 x Nfdt] +% a - denominator polynomial of H(z) / [Norder+1 x Nfdt] +% +% See also: delayline, lagrange_filter + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Computation ===================================================== + +% Shift fractional delay in order to optimize performance +fdt = fdt(:); % ensure column vector +Nfdt = numel(fdt); + +% Denomimator polynomial of H(z) +a = [ones(1,Nfdt); zeros(Norder,Nfdt)]; +for kdx=1:Norder + a(kdx+1,:) = (-1).^kdx * ... + factorial(Norder)/(factorial(kdx)*factorial(Norder-kdx)) * ... + prod( bsxfun(@plus,fdt,0:Norder)./bsxfun(@plus,fdt,kdx:kdx+Norder), 2 ); +end +% Numerator polynomial of H(z) +b = a(end:-1:1,:); diff --git a/SFS_general/vector_norm.m b/SFS_general/vector_norm.m index 2e956c49..b831227e 100644 --- a/SFS_general/vector_norm.m +++ b/SFS_general/vector_norm.m @@ -1,5 +1,5 @@ function y = vector_norm(x,dim) -%VECTOR_NORM calculates the norm for the rows/columns of a matrix +%VECTOR_NORM norm for the rows/columns of a matrix % % Usage: y = vector_norm(x,dim) % @@ -16,35 +16,32 @@ % See also: norm, vector_product %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_general/vector_product.m b/SFS_general/vector_product.m index d80787b8..241d9dd2 100644 --- a/SFS_general/vector_product.m +++ b/SFS_general/vector_product.m @@ -1,5 +1,5 @@ function y = vector_product(x1,x2,dim) -%VECTOR_PRODUCT calculates the scalar product for two vectors within matrices +%VECTOR_PRODUCT scalar product for two vectors within matrices % % Usage: y = vector_product(x1,x2,dim) % @@ -11,41 +11,35 @@ % Output parameter: % y - scalar product between the vectors [1 x m] or [n x 1] % -% VECTOR_PRODUCT(x1,x2,dim) calculates the scalar product between the vectors -% given within the matrices along the dimension dim. -% % See also: vector_norm %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_general/virtual_secondary_source_positions.m b/SFS_general/virtual_secondary_source_positions.m index 2ebd8acc..c7896679 100644 --- a/SFS_general/virtual_secondary_source_positions.m +++ b/SFS_general/virtual_secondary_source_positions.m @@ -1,10 +1,10 @@ function xv = virtual_secondary_source_positions(x0,xs,src,conf) -%VIRTUAL_SECONDARY_SOURCE_POSITIONS generates the positions and directions of a +%VIRTUAL_SECONDARY_SOURCE_POSITIONS positions and directions of a % virtual secondary source distribution % % Usage: xv = virtual_secondary_source_positions(x0,xs,src,conf) % -% Input options: +% Input parameters: % x0 - positions, directions and weights of real secondary % sources [nx7] % xs - position and for focused sources also direction of the @@ -14,236 +14,227 @@ % plane wave in this case) % 'ps' - point source % 'fs' - focused source (not supported, yet) -% conf - optional configuration struct (see SFS_config) +% conf - configuration struct (see SFS_config) % -% Output options: +% Output parameters: % xv - virtual secondary source positions, directions and % weights / m % % VIRTUAL_SECONDARY_SOURCE_POSITIONS(x0,xs,src,conf) generates the positions % and directions xv of virtual secondary sources for a local area geometry -% (conf.localsfs.geometry) and local area size(conf.localsfs.size). +% (conf.localsfs.geometry) and local area size (conf.localsfs.size). % The direction of the virtual sources is given as their unit vectors % pointing in the given direction. -% Optionally (conf.localsfs.vss.consider_target_field == true), the algorithm -% takes the sound field, which is to be reproduced, into account for the -% positioning. -% Optionally (conf.localsfs.vss.consider_secondary_sources == true), the +% Optionally (conf.localwfs_vss.consider_target_field == true), the +% algorithm takes the sound field, which is to be reproduced, into account +% for the positioning. +% Optionally (conf.localwfs_vss.consider_secondary_sources == true), the % algorithm takes the positions of the real loudspeakers into account. % % See also: driving_function_mono_localwfs, driving_function_imp_localwfs %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters =================================== -nargmin = 3; +nargmin = 4; nargmax = 4; narginchk(nargmin,nargmax); isargxs(xs); -if ~isempty(x0) - isargsecondarysource(x0); -end +isargsecondarysource(x0); isargchar(src); -if nargin 0 + xmax = min(xmax, t); + else + xmin = max(xmin, t); + end + end + end + xmax = min(xmax, Rl); + xmin = max(xmin, -Rl); + else + xmax = Rl; + xmin = -Rl; + end - elseif strcmp('linear',geometry) - % ===================================================================== - % Virtual linear Array - % ===================================================================== - % valid line of virtual secondary sources + % SOURCE POSITIONING ================================================== + % === Equi-distant sampling on valid line === + x = linspace(xmin, xmax, nls); - % CONSTRAINT 1 ======================================================== - % Consider the target field which shall reproduced - if consider_target_field - nd = ns; - ndorth = ns*[0 1 0; -1 0 0; 0 0 1]; + % Positions of the secondary sources + xv(:,1:3) = repmat(xl, nls, 1) + x'*ndorth; + % Direction of the secondary sources + xv(:,4:6) = repmat(-nd, nls, 1); + % Equal weights for all sources + xv(:,7) = ones(nls,1)*(xmax-xmin)/(nls-1); else - nd = [0, 1, 0]; - ndorth = [-1, 0, 0]; - end - - % CONSTRAINT 2 ======================================================== - % Consider the position of the real loudspeaker array - if (consider_secondary_sources && ~isempty(x0)) - xmax = inf; - xmin = -inf; - % For each secondary source - for idx=1:size(x0,1) - % This calculates the parameter t for the intersection between the linear - % virtual array and the plane spanned by one loudspeaker (position + - % orientation) - n0 = x0(idx, 4:6); - ntmp = (ndorth*n0'); - if ntmp ~= 0 - t = (x0(idx,1:3) - xl)*n0'./ntmp; - if t > 0 - xmax = min(xmax, t); - else - xmin = max(xmin, t); - end + xv = secondary_source_positions(virtualconf); + if consider_target_field + xv = secondary_source_selection(xv, xs, src); end - end - xmax = min(xmax, Rl); - xmin = max(xmin, -Rl); - else - xmax = Rl; - xmin = -Rl; - end - - % SOURCE POSITIONING ================================================== - % === Equi-distant sampling on valid line === - x = linspace(xmin, xmax, nls); - - % Positions of the secondary sources - xv(:,1:3) = repmat(xl, nls, 1) + x'*ndorth; - % Direction of the secondary sources - xv(:,4:6) = repmat(-nd, nls, 1); - % Equal weights for all sources - xv(:,7) = ones(nls,1); - else - xv = secondary_source_positions(virtualconf); - if consider_target_field - xv = secondary_source_selection(xv, xs, src); end - end else - % ===================================================================== - % Non-adaptive positioning of virtual secondary sources - % ===================================================================== - % Just position the virtual secondary sources as you would do it with the - % loudspeakers. This ignores the virtual source position, the size of - % the local listening area and the position of the real loudspeakers - xv = secondary_source_positions(virtualconf); + % ===================================================================== + % Non-adaptive positioning of virtual secondary sources + % ===================================================================== + % Just position the virtual secondary sources as you would do it with the + % loudspeakers. This ignores the virtual source position, the size of + % the local listening area and the position of the real loudspeakers + xv = secondary_source_positions(virtualconf); end diff --git a/SFS_general/warning_if_zero.m b/SFS_general/warning_if_zero.m new file mode 100644 index 00000000..6ba6b1d9 --- /dev/null +++ b/SFS_general/warning_if_zero.m @@ -0,0 +1,60 @@ +function warning_if_zero(P,t) +%WARNING_IF_ZERO returns a warning if the whole sound field is zero or NaN +% +% Usage: warning_if_zero(P,t) +% +% Input parameters: +% P - sound field +% t - time t / s +% +% WARNING_IF_ZERO(P,t) returns a warning if the whole sound field is zero or +% NaN. If the sound field consist only of one point no warning is given. +% +% See also: sound_field_imp_wfs, norm_sound_field + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ==================================== +nargmin = 2; +nargmax = 2; +narginchk(nargmin,nargmax); +isargnumeric(P); +isargscalar(t); + + +%% ===== Computation ===================================================== +if length(P)==1, return; end +% +if max(abs(P(:)))==0 || all(isnan(P(:))) + warning('SFS:check_sound_field',... + ['The activity in the simulated sound field is zero. ',... + 'Maybe you should use another time t than %i s. '],t); +end diff --git a/SFS_general/weights_for_points_on_a_sphere_rectangle.m b/SFS_general/weights_for_points_on_a_sphere_rectangle.m index d863d4a0..a84725f0 100644 --- a/SFS_general/weights_for_points_on_a_sphere_rectangle.m +++ b/SFS_general/weights_for_points_on_a_sphere_rectangle.m @@ -1,6 +1,6 @@ function [w] = weights_for_points_on_a_sphere_rectangle(phi,theta) -%WEIGHTS_FOR_POINTS_ON_A_SPHERE_RECTANGLE returns the weights for a given -% set of points on a sphere. +%WEIGHTS_FOR_POINTS_ON_A_SPHERE_RECTANGLE weights for a given set of points +%on a sphere. % % Usage: [w] = weights_for_points_on_a_sphere_rectangle(phi,theta) % @@ -19,35 +19,32 @@ % See also: get_spherical_grid %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_general/xyz_axes.m b/SFS_general/xyz_axes.m deleted file mode 100644 index 373e25a8..00000000 --- a/SFS_general/xyz_axes.m +++ /dev/null @@ -1,72 +0,0 @@ -function [x,y,z] = xyz_axes(X,Y,Z,conf) -%XYZ_AXES returns the x-, y-, and z-axis for the listening area -% -% Usage: [x,y,z] = xyz_aex(X,Y,Z,[conf]) -% -% Input parameters: -% X - x-axis / m; single value or [xmin,xmax] -% Y - y-axis / m; single value or [ymin,ymax] -% Z - z-axis / m; single value or [zmin,zmax] -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% x,y,z - x-, y-, z-axis / m -% -% XYZ_AXES(X,Y,Z,conf) creates the x-, y-, and -z-axis for the listening area. -% -% See also: xyz_grid, xyz_axes_selection - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input parameters ======================================= -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -[X,Y,Z] = axis_vector(X,Y,Z); -if nargin. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** @@ -57,50 +55,16 @@ nargmin = 3; nargmax = 3; narginchk(nargmin,nargmax); -isargvector(x,y,z); +isargnumeric(x,y,z); %% ===== Computation ===================================================== -dimensions = [1 1 1]; -% Check if we have any inactive dimensions -if x(1)==x(end) - dimensions(1) = 0; -end -if y(1)==y(end) - dimensions(2) = 0; -end -if z(1)==z(end) - dimensions(3) = 0; -end +dims = {x,y,z}; +dimensions = ~is_dim_singleton(dims{:}); +Nd = sum(dimensions); + +newdims = {x(1),y(1),z(1)}; % default case, if all dimensions are singleton +newdims(Nd+1:end) = newdims(~dimensions); % move singleton dimensions to the end +newdims(1:Nd) = dims(dimensions); % move non-singleton dimensions to the front -% Return the axis -x1=x; -x2=y; -x3=z; -if all(dimensions) - % Do nothing -elseif dimensions(1) && dimensions(2) - x3=z(1); -elseif dimensions(1) && dimensions(3) - x2=z; - x3=y(1); -elseif dimensions(2) && dimensions(3) - x1=y; - x2=z; - x3=x(1); -elseif dimensions(1) - x2=y(1); - x3=z(1); -elseif dimensions(2) - x1=y; - x2=x(1); - x3=z(1); -elseif dimensions(3) - x1=z; - x2=x(1); - x3=z(1); -else - x1=x(1); - x2=y(1); - x3=z(1); -end +[x1, x2, x3] = newdims{:}; diff --git a/SFS_general/xyz_grid.m b/SFS_general/xyz_grid.m index a86b62be..b64579ac 100644 --- a/SFS_general/xyz_grid.m +++ b/SFS_general/xyz_grid.m @@ -1,96 +1,84 @@ -function [xx,yy,zz,x,y,z] = xyz_grid(X,Y,Z,conf) -%XYZ_GRID returns a xyz-grid for the listening area +function [xx,yy,zz] = xyz_grid(X,Y,Z,conf) +%XYZ_GRID returns xyz-grid for the listening area % -% Usage: [xx,yy,zz,x,y,z] = xyz_grid(X,Y,Z) +% Usage: [xx,yy,zz] = xyz_grid(X,Y,Z,conf) % % Input parameters: % X - x-axis / m; single value or [xmin,xmax] % Y - y-axis / m; single value or [ymin,ymax] % Z - z-axis / m; single value or [zmin,zmax] -% conf - optional configuration struct (see SFS_config) +% conf - configuration struct (see SFS_config) % % Output parameters: -% xx,yy,zz - matrices representing the xy-grid / m -% x,y,z - x-, y-, z-axis / m +% xx,yy,zz - matrices representing the xyz-grid / m % -% XYZ_GRID(X,Y,Z) creates a xyz-grid to avoid a loop in the sound field -% calculation for the whole listening area. It returns also the x-, y-, z-axis -% for the listening area, defined by the points given with X,Y,Z. +% XYZ_GRID(X,Y,Z,conf) creates a xyz-grid to avoid a loop in the sound field +% calculation for the whole listening area. % -% See also: xyz_axes, xyz_axes_selection, sound_field_mono +% See also: xyz_axes_selection, is_dim_custom, sound_field_mono %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking input parameters ======================================= -nargmin = 3; +nargmin = 4; nargmax = 4; narginchk(nargmin,nargmax); -isargvector(X,Y,Z); -if nargin size(xx)==[resolution resolution resolution] - [xx,yy,zz] = meshgrid(x,y,z); -elseif dimensions(1) && dimensions(2) - % Create a 2D grid => size(xx)==[resolution resolution] - [xx,yy] = meshgrid(x,y); - zz = meshgrid(z,y); -elseif dimensions(1) && dimensions(3) - [xx,zz] = meshgrid(x,z); - yy = meshgrid(y,z); -elseif dimensions(2) && dimensions(3) - [yy,zz] = meshgrid(y,z); - xx = meshgrid(x,z); -elseif any(dimensions) - % Create a 1D grid => size(xx)==[resolution 1] - xx = x; - yy = y; - zz = z; +dims = {X,Y,Z}; + +if any( is_dim_custom(X,Y,Z) ) + xx = X; + yy = Y; + zz = Z; else - % Create a 0D grid => size(xx)==[1 1] - xx = x(1); - yy = y(1); - zz = z(1); + % Check which dimensions will be non singleton + dimensions = xyz_axes_selection(X,Y,Z); + % Create xyz-axes + xyz_axes = {X(1),Y(1),Z(1)}; + % create regular grid in each non-singleton dimension + xyz_axes(dimensions) = cellfun( @(D) linspace(D(1),D(2),resolution).', ... + dims(dimensions),'UniformOutput',false ); + % Create xyz-grid + grids = xyz_axes; + if sum(dimensions)>=2 + % create 2D/3D grid + [grids{dimensions}] = meshgrid(xyz_axes{dimensions}); + end + [xx,yy,zz] = grids{:}; end diff --git a/SFS_helper/addirspath.m b/SFS_helper/addirspath.m deleted file mode 100644 index beffc010..00000000 --- a/SFS_helper/addirspath.m +++ /dev/null @@ -1,71 +0,0 @@ -function addirspath(conf) -%ADDIRSPATH adds directories containing irs files to the path -% -% Usage: addirspath(conf) -% -% Input parameters: -% conf - optional configuration struct (see SFS_config) -% -% ADDIRSPATH(conf) adds the directories specified in conf.ir.dir to your -% search path for easy loading with read_irs(). If you have more than one -% directory they have to be seperated by ':'. - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -% ===== Checking of input parameters ==================================== -nargmin = 0; -nargmax = 1; -narginchk(nargmin,nargmax); -if nargin==nargmax-1 - conf = SFS_config; -end -isargstruct(conf); - - -%% ===== Configuration ================================================== -% NOTE: newer versions of Matlab can do the following with the strsplit -% function -%dirs = strsplit(conf.ir.path,':'); -dirs = regexp(conf.ir.path,':','split') - - -%% ===== Adding pathes ================================================== -for ii = 1:length(dirs) - if exist(dirs{ii},'dir') - path = genpath(dirs{ii}); - addpath(path,'-end'); - else - warning('%s: %s does not exist.',upper(mfilename),dirs{ii}); - end -end diff --git a/SFS_helper/get_position_and_orientation_ls.m b/SFS_helper/get_position_and_orientation_ls.m new file mode 100644 index 00000000..63ebc496 --- /dev/null +++ b/SFS_helper/get_position_and_orientation_ls.m @@ -0,0 +1,82 @@ +function [xs,nxs] = get_position_and_orientation_ls(xs,conf); +%GET_POSITION_AND_ORIENTATION_LS position and orientation for a line source +% +% Usage: [xs,nxs] = get_position_and_orientation_ls(xs,conf); +% +% Input parameters: +% xs - combined position and orientation / m [nx3] or [nx6] +% args - list of args +% +% Output parameters: +% xs - position of line source / m [nx3] +% nxs - orientation of line source / m [nx3] +% +% GET_POSITION_AND_ORIENTATION_LS(xs,conf) returns the position and +% orientation of a point source. The orientation is a vector perpendicular to +% the traveling direction of the line source. For 2D or 2.5D the orientation +% will always be returned as [0 0 1]. For 3D [0 0 1] will be returned if no +% explicit orientation is given. +% +% See also: secondary_source_selection, driving_function_mono_wfs + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 2; +nargmax = 2; +narginchk(nargmin,nargmax); +isargnumeric(xs); +isargstruct(conf); + + +%% ===== Configuration =================================================== +dimension = conf.dimension; + + +%% ===== Checking for vector ============================================= +% Handling of line source orientation +if (strcmp('2D',dimension) || strcmp('2.5D',dimension)) + % Ignore orientation for 2D and 2.5D + if size(xs,2)>3 + warning('%s: %s-WFS ignores virtual line source orientation.', ... + upper(mfilename),dimension); + end + xs(:,3) = 0; + nxs = repmat([0 0 1],[size(xs,1) 1]); +else + if size(xs,2)~=6 + warning('%s: set ls orientation to [0 0 1]',upper(mfilename)); + nxs = repmat([0 0 1],[size(xs,1) 1]); + else + nxs = xs(:,4:6) / norm(xs(1,4:6),2); + end +end +xs = xs(:,1:3); diff --git a/SFS_helper/get_sfs_path.m b/SFS_helper/get_sfs_path.m index c9340467..edce355a 100644 --- a/SFS_helper/get_sfs_path.m +++ b/SFS_helper/get_sfs_path.m @@ -1,39 +1,36 @@ function path = get_sfs_path() -%GET_SFS_PATH returns the base path of the SFS Toolbox +%GET_SFS_PATH base path of the SFS Toolbox % % Usage: path = get_sfs_path(); % %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/isargchar.m b/SFS_helper/isargchar.m index 4054dfbe..1f51109a 100644 --- a/SFS_helper/isargchar.m +++ b/SFS_helper/isargchar.m @@ -1,46 +1,40 @@ function isargchar(varargin) -%ISARGCHAR tests if the given arg is a char and returns an error otherwise +%ISARGCHAR throws an error if not a char % % Usage: isargstruct(arg1,arg2,...) % -% Input options: +% Input parameters: % args - list of args % -% ISARGCHAR(args) tests if all given args are a char and returns -% an error otherwise. -% % See also: isargstruct %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/isargcoord.m b/SFS_helper/isargcoord.m index 16570875..23d7a580 100644 --- a/SFS_helper/isargcoord.m +++ b/SFS_helper/isargcoord.m @@ -1,9 +1,9 @@ function isargcoord(varargin) -%ISARGCOORD tests if the given arg is a point in an euclidian coordinate system +%ISARGCOORD throws an error if not a point in an euclidian coordinate system % % Usage: isargcoord(args) % -% Input options: +% Input parameters: % args - list of args % % ISARGCOORD(args) tests if all given args are a point in an euclidian @@ -13,35 +13,32 @@ function isargcoord(varargin) % See also: isargvector %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/isargdir.m b/SFS_helper/isargdir.m index 461dc3bd..375eb1b2 100644 --- a/SFS_helper/isargdir.m +++ b/SFS_helper/isargdir.m @@ -1,46 +1,40 @@ function isargdir(varargin) -%ISARGDIR tests if the given arg is a directory +%ISARGDIR throws an error if not a directory % % Usage: isargdirectory(arg1,arg2,...) % -% Input options: +% Input parameters: % args - variable number of args % -% ISARGDIR(args) tests if all given args are a directory and -% returns an error otherwise. -% % See also: isargfile %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/isargequallength.m b/SFS_helper/isargequallength.m index ddc4a2a6..1e9b0896 100644 --- a/SFS_helper/isargequallength.m +++ b/SFS_helper/isargequallength.m @@ -1,46 +1,40 @@ function isargequallength(x1,varargin) -%ISARGEQUALSIZE tests if the given arrays have the same size +%ISARGEQUALSIZE throws an error if not the same length % % Usage: isargequallength(x1,x2,...) % -% Input options: +% Input parameters: % x1,x2,... - matrices to test % -% ISARGEQUALLENGTH(x1,x2,...) tests if all given arigs have the same size. -% Reports an error otherwise. -% % See also: isargequalsize %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/isargequalsize.m b/SFS_helper/isargequalsize.m index c4b7b375..5575c3af 100644 --- a/SFS_helper/isargequalsize.m +++ b/SFS_helper/isargequalsize.m @@ -1,46 +1,40 @@ function isargequalsize(x1,varargin) -%ISARGEQUALSIZE tests if the given arrays have the same size +%ISARGEQUALSIZE throws an error if not the same size % % Usage: isargequalsize(x1,x2,...) % -% Input options: +% Input parameters: % x1,x2,... - matrices to test % -% ISARGEQUALSIZE(x1,x2,...) tests if all given arrays have the same size. -% Reports an error otherwise. -% % See also: isargequallength %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** @@ -53,6 +47,6 @@ function isargequalsize(x1,varargin) %% ===== Checking for equal size ========================================= for ii = 1:nargin-1 if ~isequal(size(varargin{ii}),size(x1)) - error('%s and %s have not the same size',inputname(1),inputname(2)); + error('%s and %s have not the same size',inputname(1),inputname(ii+1)); end end diff --git a/SFS_helper/isargfile.m b/SFS_helper/isargfile.m index 58469e44..a7aa442f 100644 --- a/SFS_helper/isargfile.m +++ b/SFS_helper/isargfile.m @@ -1,46 +1,40 @@ function isargfile(varargin) -%ISARGFILE tests if the given arg is a file and returns an error otherwise +%ISARGFILE throws an error if not a file % % Usage: isargfile(arg1,arg2,...) % -% Input options: +% Input parameters: % args - list of args % -% ISARGFILE(args) tests if all given args are a file and returns -% an error otherwise. -% % See also: isargdir %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/isargmatrix.m b/SFS_helper/isargmatrix.m index 0feb0474..2e42fe8a 100644 --- a/SFS_helper/isargmatrix.m +++ b/SFS_helper/isargmatrix.m @@ -1,46 +1,40 @@ function isargmatrix(varargin) -%ISARGMATRIX tests if the given arg is a matrix and returns an error otherwise +%ISARGMATRIX throws an error if not a matrix % % Usage: isargmatrix(arg1,arg2,...) % -% Input options: +% Input parameters: % args - list of args % -% ISARGMATRIX(args) tests if all given args are a matrix and returns -% an error otherwise. -% % See also: isargvector, isargscalar %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/isargnegativescalar.m b/SFS_helper/isargnegativescalar.m index 43e65e9e..1cc64e32 100644 --- a/SFS_helper/isargnegativescalar.m +++ b/SFS_helper/isargnegativescalar.m @@ -1,46 +1,40 @@ function isargnegativescalar(varargin) -%ISARGNEGATIVESCALAR tests if the given arg is a negative scalar +%ISARGNEGATIVESCALAR throws an error if not a negative scalar % % Usage: isargnegativescalar(arg1,arg2,...) % -% Input options: +% Input parameters: % args - list of args % -% ISARGNEGATIVESCALAR(args) tests if all given args are a negative -% scalar and returns an error otherwise. -% % See also: isargscalar, isargpositivescalar %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/isargnumeric.m b/SFS_helper/isargnumeric.m index e39fcc19..2169f5a6 100644 --- a/SFS_helper/isargnumeric.m +++ b/SFS_helper/isargnumeric.m @@ -1,46 +1,40 @@ function isargnumeric(varargin) -%ISARGNUMERIC tests if the given arg is numeric and returns an error otherwise +%ISARGNUMERIC throws an error if not numeric % % Usage: isargnumeric(arg1,arg2,...) % -% Input options: +% Input parameters: % args - list of args % -% ISARGNUMRIC(args) tests if all given args are numeric and returns -% an error otherwise. -% % See also: isargscalar %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/isargposition.m b/SFS_helper/isargposition.m index d934cb5f..f4ee51fd 100644 --- a/SFS_helper/isargposition.m +++ b/SFS_helper/isargposition.m @@ -1,47 +1,40 @@ function isargposition(varargin) -%ISARGPOSITION tests if the given arg is a [1x3] vector and returns an error -%otherwise +%ISARGPOSITION throws an error if not a [1x3] vector % % Usage: isargposition(args) % -% Input options: +% Input parameters: % args - list of args % -% ISARGPOSITION(args) tests if all given args are [1x3] vectors and -% returns an error otherwise. -% % See also: isargscalar, isargvector, isargxs %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/isargpositivescalar.m b/SFS_helper/isargpositivescalar.m index 02d48ef9..feee50a9 100644 --- a/SFS_helper/isargpositivescalar.m +++ b/SFS_helper/isargpositivescalar.m @@ -1,46 +1,40 @@ function isargpositivescalar(varargin) -%ISARGPOSITIVESCALAR tests if the given arg is a positive scalar +%ISARGPOSITIVESCALAR throws an error if not a positive scalar % % Usage: isargpositivescalar(arg1,arg2,...) % -% Input options: +% Input parameters: % args - list of args % -% ISARGPOSITIVESCALAR(args) tests if all given args are a positive -% scalar and returns an error otherwise. -% % See also: isargscalar, isargnegativescalar %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/isargscalar.m b/SFS_helper/isargscalar.m index b36022df..44073880 100644 --- a/SFS_helper/isargscalar.m +++ b/SFS_helper/isargscalar.m @@ -1,45 +1,40 @@ function isargscalar(varargin) -%ISARGSCALAR tests if the given arg is a scalar and returns an error otherwise +%ISARGSCALAR throws an error if not a scalar +% % Usage: isargscalar(arg1,arg2,...) % -% Input options: +% Input parameters: % args - list of args % -% ISARGSCALAR(args) tests if all given args are a scalar and returns -% an error otherwise. -% % See also: isargpositivescalar %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/isargsecondarysource.m b/SFS_helper/isargsecondarysource.m index dabc2d23..f48dea74 100644 --- a/SFS_helper/isargsecondarysource.m +++ b/SFS_helper/isargsecondarysource.m @@ -1,10 +1,9 @@ function isargsecondarysource(varargin) -%ISARGSECONDARYSOURCE tests if the given arg is a matrix containing secondary -% source positions and directions and return an error otherwise +%ISARGSECONDARYSOURCE throws an error if not secondary sources % % Usage: isargsecondarysource(args) % -% Input options: +% Input parameters: % args - list of args % % ISARGSECONDARYSOURCE(args) tests if all given args are a matrix @@ -14,35 +13,32 @@ function isargsecondarysource(varargin) % See also: isargmatrix %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/isargstruct.m b/SFS_helper/isargstruct.m index 756ff22d..32bc1c87 100644 --- a/SFS_helper/isargstruct.m +++ b/SFS_helper/isargstruct.m @@ -1,46 +1,40 @@ function isargstruct(varargin) -%ISARGSTRUCT tests if the given arg is a struct and returns an error otherwise +%ISARGSTRUCT throws an error if not a struct % % Usage: isargstruct(arg1,arg2,...) % -% Input options: +% Input parameters: % args - list of args % -% ISARGSTRUCT(args) tests if all given args are a struct and returns -% an error otherwise. -% % See also: isargchar %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/isargvector.m b/SFS_helper/isargvector.m index a636f99e..c97e2c0d 100644 --- a/SFS_helper/isargvector.m +++ b/SFS_helper/isargvector.m @@ -1,46 +1,40 @@ function isargvector(varargin) -%ISARGVECTOR tests if the given arg is a vector and returns an error otherwise +%ISARGVECTOR throws an error if not a vector % % Usage: isargvector(args) % -% Input options: +% Input parameters: % args - list of args % -% ISARGVECTOR(args) tests if all given args are a vector and returns -% an error otherwise. -% % See also: isargscalar, isargmatrix %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/isargxs.m b/SFS_helper/isargxs.m index 3abf91b0..9f80e2df 100644 --- a/SFS_helper/isargxs.m +++ b/SFS_helper/isargxs.m @@ -1,47 +1,40 @@ function isargxs(varargin) -%ISARGXS tests if the given args are a [1x3] and/or [1x6] vector and returns -%an error otherwise +%ISARGXS throws an error if not a [1x3] and/or [1x6] vector % % Usage: isargxs(args) % -% Input options: +% Input parameters: % args - list of args % -% ISARGXS(args) tests if all given args are a [1x3] and/or [1x6] vectors and -% returns an error otherwise. -% % See also: isargscalar, isargvector, isargposition %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/isoctave.m b/SFS_helper/isoctave.m index 2c4a44cb..92e6a55e 100644 --- a/SFS_helper/isoctave.m +++ b/SFS_helper/isoctave.m @@ -1,41 +1,41 @@ function bool = isoctave() -%ISOCTAVE True if the operating environment is octave. +%ISOCTAVE true if the operating environment is octave % -% Usage: t = isoctave(); +% Usage: status = isoctave(); % -% ISOCTAVE returns 1 if the operating environment is Octave, otherwise -% 0 (Matlab) +% Output parameters: +% status - boolean +% +% See also: iswindows + %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/iswindows.m b/SFS_helper/iswindows.m index ba699904..1272b7d9 100644 --- a/SFS_helper/iswindows.m +++ b/SFS_helper/iswindows.m @@ -1,40 +1,40 @@ function bool = iswindows() -%ISWINDOWS True if the operating system is Windows +%ISWINDOWS true if the operating system is Windows % % Usage: status = iswindows(); % -% ISWINDOWS returns 1 if the operating system is Windows, otherwise 0 +% Output parameters: +% status - boolean +% +% See also: isoctave %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_helper/progress_bar.m b/SFS_helper/progress_bar.m index 79325906..e461409f 100644 --- a/SFS_helper/progress_bar.m +++ b/SFS_helper/progress_bar.m @@ -1,87 +1,80 @@ -function progress_bar(ii,nii) -%PROGRESS_BAR show a progress of an iteration +function progress_bar(ii,nii,message) +%PROGRESS_BAR show the progress of an iteration % -% Usage: progress_bar(ii,nii) +% Usage: progress_bar(ii,nii,[message]) % % Input parameters: -% ii - current iteration -% nii - number of iterations -% -% PROGRESS_BAR(ii,nii) displays the progress of a loop. -% +% ii - current iteration +% nii - number of iterations +% message - string printed before progress bar (default: 'Progress') %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ==================================== nargmin = 2; -nargmax = 2; +nargmax = 3; narginchk(nargmin,nargmax); isargpositivescalar(ii,nii); +if nargin<3 + message = 'Progress'; +end + + +%% ===== Settings ======================================================== +bar_width = 10; +bar_prefix = '['; +bar_suffix = ']'; +bar_empty = ' '; +bar_full = '.'; %% ===== Generate the progress bar ======================================= -% \r is not working under some Windows systems, therefore we use \b to clear the -% line -% calculate percentage -perc = ii/nii * 100; -% get bar -if perc<10 - bar = '[. ]'; -elseif perc<20 - bar = '[.. ]'; -elseif perc<30 - bar = '[... ]'; -elseif perc<40 - bar = '[.... ]'; -elseif perc<50 - bar = '[..... ]'; -elseif perc<60 - bar = '[...... ]'; -elseif perc<70 - bar = '[....... ]'; -elseif perc<80 - bar = '[........ ]'; -elseif perc<90 - bar = '[......... ]'; -else - bar = '[..........]'; -end -str = sprintf('Progress: %s %3.0f%%%%',bar,perc); +% Format progress bar +progress = ii/nii; +nfull = floor(min(bar_width*progress,bar_width)); % number of full chars +nempty = bar_width - nfull; % number of empty chars +bar = repmat(bar_full,1,nfull); +empty = repmat(bar_empty,1,nempty); +% Print to screen +str = sprintf('%s: %s%s%s%s %3.0f%%%%', ... + message, ... + bar_prefix, ... + bar, ... + empty, ... + bar_suffix, ... + progress*100); if ii==1 fprintf(1,str); else - clear_line(length(str)-1); + clear_line(length(str)); fprintf(1,str); end if ii==nii @@ -97,6 +90,8 @@ function progress_bar(ii,nii) %% ------ Subfunctions --------------------------------------------------- function clear_line(str_length) + % \r is not working under some Windows systems, therefore we use \b to + % clear the line for ii=1:str_length fprintf(1,'\b'); end diff --git a/SFS_helper/to_be_implemented.m b/SFS_helper/to_be_implemented.m index 7e98383e..cb01a138 100644 --- a/SFS_helper/to_be_implemented.m +++ b/SFS_helper/to_be_implemented.m @@ -1,5 +1,5 @@ function to_be_implemented(mfile) -%TO_BE_IMPLEMENTED indicates that the code had to be implemented +%TO_BE_IMPLEMENTED throws an error indicating missing code % % Usage: to_be_implemented([mfilename]) % @@ -7,40 +7,34 @@ function to_be_implemented(mfile) % mfilename - string containing the name of the calling m file. % NOTE: this variable is already available in all m files as % mfilename! -% -% TO_BE_IMPLEMENTED(mfilename) results in an error that indicates the desired -% code functionality has to be implemented yet. %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_ir/IR_format.txt b/SFS_ir/IR_format.txt deleted file mode 100644 index a2e424e6..00000000 --- a/SFS_ir/IR_format.txt +++ /dev/null @@ -1,2 +0,0 @@ -Documentation regarding the used file format for the irs data sets can be found here: -https://dev.qu.tu-berlin.de/projects/measurements/wiki/IRs_file_format diff --git a/SFS_ir/check_irs.m b/SFS_ir/check_irs.m deleted file mode 100644 index 946551fc..00000000 --- a/SFS_ir/check_irs.m +++ /dev/null @@ -1,164 +0,0 @@ -function check_irs(irs) -%CHECK_IRS checks if the given irs is stored in the right format -% -% Usage: check_irs(irs) -% -% Input options -% irs - irs struct -% -% CHECK_IRS(irs) checks if the given irs is stored in our own format. -% For format details have a look at the IR_format.txt file. -% -% See also: new_irs, IR_format.txt - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 1; -narginchk(nargmin,nargmax); -isargstruct(irs); - - -%% ===== Format checking ================================================= -% Check for the right field entries in the given irs struct -% Get a reference implementation of a irs and optional fields of this reference -% irs -[ref_irs,opt_fields] = new_irs(); -% Get fields of reference implementation -ref_fields = fieldnames(ref_irs); -% Get the fields for the given irs -fields = fieldnames(irs); -idx = []; -for ii = 1:length(ref_fields) - % Check if all needed fields are present - if ~isfield(irs,ref_fields{ii}) && ~strcmp(opt_fields,ref_fields{ii}) - error('%s: The given irs misses the field: %s!',... - upper(mfilename),ref_fields{ii}); - end - % Get unneeded optional fields - if ~isfield(irs,ref_fields{ii}) && strcmp(opt_fields,ref_fields{ii}) - idx = [idx ii]; - end -end -% Remove unneeded optional fields -ref_fields(idx) = []; - -% Check if the order of the fields is standard conform to new_irs() -for ii = 1:length(ref_fields) - if ~strcmp(fields{ii},ref_fields{ii}) - warning('SFS:irs_fields_order',... - ['%s: the order of fields is not standard conform. ',... - 'please use order_irs_fields(irs).'],upper(mfilename)); - break; - end -end - -% Check for right measurement angle types -if ~isnumeric(irs.head_azimuth) || ~isvector(irs.head_azimuth) - error('%s: head_azimuth needs to be a vector.',upper(mfilename)); -elseif ~isnumeric(irs.head_elevation) || ~isvector(irs.head_elevation) - error('%s: head_elevation needs to be a vector.',upper(mfilename)); -elseif ~isnumeric(irs.torso_azimuth) || ~isvector(irs.torso_azimuth) - error('%s: torso_azimuth needs to be a vector.',upper(mfilename)); -elseif ~isnumeric(irs.torso_elevation) || ~isvector(irs.torso_elevation) - error('%s: torso_elevation needs to be a vector.',upper(mfilename)); -end - -% Check for the right number of entries for the signals and apparent angles -if size(irs.left,2)~=size(irs.right,2) - error(['%s: the number of entries for the left ear signal is not ',... - 'consistent with the number of entries in the right channel.'],... - upper(mfilename)); -elseif size(irs.left,2)~=length(irs.apparent_azimuth) - error(['%s: the number of entries for the left ear signal is not ',... - 'consistent with the number of entries for the apparent_azimuth.'],... - upper(mfilename)); -elseif size(irs.left,2)~=length(irs.apparent_elevation) - error(['%s: the number of entries for the left ear signal is not ',... - 'consistent with the number of entries in the apparent_elevation.'],... - upper(mfilename)); -end - -% Check for the right sizes of the entries for the positions -if all(~isnumeric(irs.head_position)) || size(irs.head_position,1)~=3 - error('%s: head_position needs to be a 3x1 vector.',upper(mfilename)); -elseif all(~isnumeric(irs.head_reference)) || size(irs.head_reference,1)~=3 - error('%s: head_reference needs to be a 3x1 vector.',upper(mfilename)); -elseif all(~isnumeric(irs.source_position)) || size(irs.source_position,1)~=3 - error('%s: source_position needs to be a 3xn vector.',upper(mfilename)); -elseif all(~isnumeric(irs.source_reference)) || size(irs.source_reference,1)~=3 - error('%s: source_reference needs to be a 3xn vector.',upper(mfilename)); -%elseif isfield(irs,'room_corners') -% if size(irs.room_corners,1)~=3 -% error('%s: room_corners needs to be a 3xn vector.',upper(mfilename)); -% end -end - -% Check sampling rate -if ~isnumeric(irs.fs) || irs.fs<=0 - error('%s: fs needs to be a positive number.',upper(mfilename)); -end - -% Check distance -if isscalar(irs.distance) - if ~isnumeric(irs.distance) || ... - irs.distance-norm(irs.head_position-irs.source_position)>0.0001 - error('%s: distance has to be norm(head_position-source_position).',... - upper(mfilename)); - end -else - for ii = 1:length(irs.distance) - if ~isnumeric(irs.distance(ii)) || ... - irs.distance(ii) - ... - norm(irs.head_position - irs.source_position(:,ii))>0.0001 - error(... - '%s: distance has to be norm(head_position-source_position).',... - upper(mfilename)); - end - end -end - -% Check string entries -if ~ischar(irs.description) - error('%s: description needs to be a string.',upper(mfilename)); -elseif ~ischar(irs.source) - error('%s: loudspeaker needs to be a string.',upper(mfilename)); -elseif ~ischar(irs.room) - error('%s: room needs to be a string.',upper(mfilename)); -elseif ~ischar(irs.head) - error('%s: head needs to be a string.',upper(mfilename)); -elseif ~ischar(irs.ears) - error('%s: ears needs to be a string.',upper(mfilename)); -end diff --git a/SFS_ir/conversion/bkoldenburg2mat.m b/SFS_ir/conversion/bkoldenburg2mat.m deleted file mode 100644 index 7382b4c9..00000000 --- a/SFS_ir/conversion/bkoldenburg2mat.m +++ /dev/null @@ -1,129 +0,0 @@ -function bkoldenburg2mat(irsset,irspath) -%BKOLDENBURG2MAT converts IRs from BK dummy head from Oldenburg to irs format -% -% Usage: bkoldenburg2mat(irspath); -% -% Input parameters: -% irsset - IR sets: -% 'RAR_08m' - HRIR of RAR with 0.8 m distance. -% 'RAR_3m' - HRIR of RAR with 3 m distance. -% irspath - path to the directory containing the IR data -% -% BKOLDENBURG2MAT(irsset,irspath) converts the IRs data given by the irsset -% and measured with a B&K dummy head in Oldenburg and stored at the given -% irspath in our own mat-file based format. For format details, see: -% https://dev.qu.tu-berlin.de/projects/measurements/wiki/IRs_file_format -% -% The Oldenburg HRTF data base can be found here: -% http://medi.uni-oldenburg.de/hrir/ - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 2; -nargmax = 2; -narginchk(nargmin,nargmax); -isargchar(irsset); -isargdir(irspath); - - -%% ===== Computation ===================================================== -outdir = 'ir_databases'; - -% Initialize a new IR struct -irs = new_irs(); -% Add common entries -irs.fs = 48000; -irs.loudspeaker = 'Tannoy 800A LH'; -irs.room = 'Anechoic chamber of Carl-von-Ossietzky Universität Oldenburg'; -irs.head = 'Brüel & Kjaer Type 4128C'; -irs.head_elevation = NaN; -irs.head_azimuth = NaN; -irs.head_position = [0 0 0]; -irs.head_reference = [0 1 0]; -irs.source_reference = [0 0 0]; - -if strcmp(irsset,'RAR_08m') - irs.description = ... - ['Anechoic measurements with a B&K dummy head in the anechoic ',... - 'chamber of Carl-von-Ossietzky Universität Oldenburg. ',... - 'Used elevation angle: -10 degree,0 degree, 10 degree ,20 degree; ',... - 'azimuth resolution: 5 degree. Distance: 0.8 m. ', ... - 'For further information have a look at: ',... - 'http://medi.uni-oldenburg.de/hrir/index.html']; - irs.distance = 0.8; - irs.source_position = [0 0.8 0]; -elseif strcmp(irsset,'RAR_3m') - irs.description = ... - ['Anechoic measurements with a B&K dummy head in the anechoic ',... - 'chamber of Carl-von-Ossietzky Universität Oldenburg. ',... - 'Used elevation angle: -10 degree,0 degree, 10 degree ,20 degree; ',... - 'azimuth resolution: 5 degree. Distance: 3 m. ', ... - 'For further information have a look at: ',... - 'http://medi.uni-oldenburg.de/hrir/index.html']; - irs.distance = 3; - irs.source_position = [0 3 0]; -end - -% Read data -idx = 1; -for delta = -10:10:20 - for azimuth = -180:5:175 - irfile = sprintf('%s/anechoic_distcm_%i_el_%i_az_%i.wav',... - irspath,irs.distance*100,delta,azimuth); - sig = wavread(irfile); - irs.left(:,idx) = sig(:,1); - irs.right(:,idx) = sig(:,2); - irs.apparent_azimuth(idx) = -correct_azimuth(rad(azimuth)); - irs.torso_azimuth(idx) = correct_azimuth(rad(azimuth)); - irs.apparent_elevation(idx) = correct_elevation(rad(delta)); - irs.torso_elevation(idx) = -correct_elevation(rad(delta)); - idx = idx+1; - end -end - - -% Reorder entries -irs = correct_irs_angle_order(irs); -irs = order_irs_fields(irs); -check_irs(irs); - -% Create the outdir -if ~exist(outdir,'dir') - mkdir(outdir); -end - -% Write IR mat-file -outfile = sprintf('%s/BKOldenburg_%s.mat',outdir,irsset); -save('-v7',outfile,'irs'); diff --git a/SFS_ir/conversion/cipic2mat.m b/SFS_ir/conversion/cipic2mat.m deleted file mode 100644 index 54342d08..00000000 --- a/SFS_ir/conversion/cipic2mat.m +++ /dev/null @@ -1,215 +0,0 @@ -function cipic2mat(irsset,irspath) -%CIPIC2MAT converts IRs data given from the CIPIS measurements to our mat-file -%based format -% -% Usage: cipic2mat(irsset,irspath); -% -% Input options: -% irsset - IR sets measured from CIPIS. -% Currently the following are available: -% 'large_pinna_frontal' - HRIR from KEMAR with large ears, -% only from the front (spacing of -% 2.8125°) -% 'small_pinna_frontal' - HRIR from KEMAR with small ears, -% only from the front (spacing of -% 2.8125°) -% 'large_pinna_final' - HRIR from KEMAR with large ears -% (spacing of 5°) -% 'small_pinna_final' - HRIR from KEMAR with small ears -% (spacing of 5°) -% 'subject_xxx' - for example subject_003 , here -% real persons were taken, also -% elevation-data available -% 'subject_021' - KEMAR with large pinnae, also -% elevation-data available -% 'subject_165' - KEMAR with small pinnae, also -% elevation-data available -% NOTE: you still have to give the matching path to the -% CIPIC-data -% irspath - path to the directory containing the CIPIC-data -% -% CIPIC2MAT(irsset,irspath) converts the IRs data given by the irsset -% and stored at the given irspath in our own mat-file based format. See: -% https://dev.qu.tu-berlin.de/projects/measurements/wiki/IRs_file_format -% -% The CIPIC data set can be found here: -% http://interface.cipic.ucdavis.edu/sound/hrtf.html - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 2; -nargmax = 2; -narginchk(nargmin,nargmax); -isargchar(irsset); -isargdir(irspath); - - -%% ===== Computation ===================================================== -% Dir to save the IRs -outdir = 'ir_databases'; - -% Initialize a new IR struct -irs = new_irs(); - -% Add common struct entries -irs.fs = 44100; - -irs.head_azimuth = NaN; -irs.torso_azimuth = NaN; -irs.head_position = [0,0,0]'; -irs.head_reference = [0 1 0]'; -irs.source_reference = [0 0 0]'; -irs.head_elevation = NaN; -irs.torso_elevation = NaN; -irs.room = 'CIPIC'; -irs.source ='5x BOSE ACOUSTIMASS 6,4cm'; -irs.room_corners = [0 0 -1.7;]'; - - -if strcmp(irsset,'large_pinna_frontal') - irs.head = 'KEMAR'; - irs.description = 'CIPIC measurement with KEMAR,spacing of 2.8125°'; - irs.ears = 'large'; -elseif strcmp(irsset,'small_pinna_frontal') - irs.head = 'KEMAR'; - irs.description = 'CIPIC measurement with KEMAR,spacing of 2.8125°'; - irs.ears = 'small'; -elseif strcmp(irsset,'large_pinna_final') - irs.head = 'KEMAR'; - irs.description = 'CIPIC measurement with KEMAR,spacing of 5°'; - irs.ears = 'large'; -elseif strcmp(irsset,'small_pinna_final') - irs.head = 'KEMAR'; - irs.description = 'CIPIC measurement with KEMAR,spacing of 5°'; - irs.ears = 'small'; -elseif strncmp(irsset,'subject',7) - irs.head = sprintf('%s for more details see anthro.mat',irsset); - irs.ears = sprintf('%s for more details see anthro.mat',irsset); - irs.description = ... - ['CIPIC; azimuth resolution: 5° (-45° to +45°) and +- 55° 65° 80° ']; - -end - - - -if strcmp(irsset,'large_pinna_frontal') | strcmp(irsset,'small_pinna_frontal') - irfile = sprintf('%s/special_kemar_hrir/kemar_frontal/%s.mat',irspath,irsset); - load(irfile); - for ii = 1:99 - theta = 0; % elevation - phi = rad(135-(ii-1)*2.8125); % azimuth - r = 1; % radius - - irs.distance(ii) = r; - [x y z] = sph2cart(phi,theta,r); - irs.source_position(:,ii) = [x y z]'; - - irs.apparent_azimuth(ii) = correct_azimuth(-phi); - irs.apparent_elevation(ii) = theta; - - irs.left(:,ii) = left(:,ii); - irs.right(:,ii) = right(:,ii); - end -elseif strcmp(irsset,'large_pinna_final') | strcmp(irsset,'small_pinna_final') - irfile = sprintf('%s/special_kemar_hrir/kemar_horizontal/%s.mat',irspath,irsset); - load(irfile); - for ii = 1:72 - theta = 0; % elevation - phi = rad(180-(ii-1)*5); % azimuth - r = 1; % radius - - irs.distance(ii) = r; - [x y z] = sph2cart(phi,theta,r); - irs.source_position(:,ii) = [x y z]'; - - irs.apparent_azimuth(ii) = correct_azimuth(-phi); - irs.apparent_elevation(ii) = round(theta*10000)/10000; - - irs.left(:,ii) = left(:,ii); - irs.right(:,ii) = right(:,ii); - end - -elseif strncmp(irsset,'subject',7) - irfile = sprintf('%s/standard_hrir_database/%s/hrir_final.mat',irspath,irsset); - load(irfile); - azimuths = [-80 -65 -55 -45:5:45 55 65 80]; - elevations = -45:5.625:235; - - ii=1; - for a = 1:25 - for e = 1:50 - theta = rad(elevations(e)); % elevation - phi = rad(azimuths(a)); % azimuth - r = 1; % radius - - - if theta > pi/2 % behind should be defined by the azimuth instead of elevation - theta = pi - theta; - phi = pi-phi; - end - - irs.distance(ii) = r; - [x y z] = sph2cart(phi,theta,r); - - irs.source_position(:,ii) = [x y z]'; - irs.apparent_azimuth(ii) = correct_azimuth(-phi); - irs.apparent_elevation(ii) = round(theta*100000)/100000; - - irs.left(:,ii) = hrir_l(a,e,:); - irs.right(:,ii) = hrir_r(a,e,:); - ii = ii+1; - end - end -end - - - - -% Reorder fields -irs = order_irs_fields(irs); -% Reorder entries -irs = correct_irs_angle_order(irs); -% Check irs format -check_irs(irs); - -% Create the outdir -if ~exist(outdir,'dir') - mkdir(outdir); -end - -% Write IR mat-file -outfile = sprintf('%s/CIPIC_%s.mat',outdir,irsset); -%v6 is used for the Windows-Version of Octave, better use v7 -save('-v7',outfile,'irs'); diff --git a/SFS_ir/conversion/fabian3D2mat.m b/SFS_ir/conversion/fabian3D2mat.m deleted file mode 100644 index 7a6529c8..00000000 --- a/SFS_ir/conversion/fabian3D2mat.m +++ /dev/null @@ -1,88 +0,0 @@ -function fabian3D2mat(irsset) -%FABIAN3D2mat converts 3D IRs data given by the FABIAN HRIR measurement -% from Oldenburg to our mat-file based format -% -% Usage: fabian3D2mat(irsset) with irsset = load('az0.mat'); -% -% Note: irsset has to be an *.mat file containing an irs-struct -% -% Input options: -% irsset - IR sets measured with FABIAN. Currently the -% following are available: -% 'az0.mat' -% -% FABIAN3D2mat(irsset) converts the IRs data given by the irsset -% in our own mat-file based format. See: -% https://dev.qu.tu-berlin.de/projects/sfs/wiki/IRs_mat-file_format - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 1; -narginchk(nargmin,nargmax); -outdir = 'ir_databases'; - - -%% ===== Computation ===================================================== -irs = irsset; -irs.apparent_azimuth = correct_azimuth(rad(irs.source_azimuth)'); -irs.apparent_elevation = correct_elevation(rad(irs.source_elevation)'); -irs.distance = irs.distance'; -irs = rmfield(irs,'source_azimuth'); -irs = rmfield(irs,'source_elevation'); -irs.ears = 'ear'; -irs.head_position = [0;0;0]; -irs.head_reference = [0;1;0]; - -irs.source_reference = [0;0;0]; -irs.head_elevation = NaN; -irs.torso_azimuth = NaN; -irs.torso_elevation = NaN; -[x,y,z] =sph2cart(irs.apparent_azimuth,irs.apparent_elevation,irs.distance); -irs.source_position = [x;y;z]; - -irs = rmfield(irs,'microphone'); -irs = rmfield(irs,'itd'); - -irs = order_irs_fields(irs); - -% Create the outdir -if ~exist(outdir,'dir') - mkdir(outdir); -end - -% Write IR mat-file -OutputName = 'FABIAN_3D_anechoic'; -save([OutputName '.mat'], 'irs'); diff --git a/SFS_ir/conversion/kemarmit2mat.m b/SFS_ir/conversion/kemarmit2mat.m deleted file mode 100644 index 7cff2f5f..00000000 --- a/SFS_ir/conversion/kemarmit2mat.m +++ /dev/null @@ -1,131 +0,0 @@ -function kemarmit2mat(irspath) -%KEMARMIT2MAT converts IRs data given by KEMAR MIT to our mat-file based format -% -% Usage: kemarmit2mat(irspath); -% -% Input options: -% irspath - path to the directory containing the IR data -% -% KEMARMIT2MAT(irspath) converts the IRs data given by the KEMAR MIT -% measurement and stored at the given irspath in our own mat-file based -% format. See: -% https://dev.qu.tu-berlin.de/projects/measurements/wiki/IRs_file_format -% -% The MIT HRTF data base can be found here: -% http://sound.media.mit.edu/resources/KEMAR.html - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 1; -narginchk(nargmin,nargmax); -isargdir(irspath); - - -%% ===== Computation ===================================================== -outdir = 'ir_databases'; -% Initialize a new IR struct -irs = new_irs(); -irs.description = ... - ['MIT anechoic measurements with KEMAR',... - 'Used elevation angle: 0°; azimuth resolution: 5°. ', ... - 'For further information have a look at: ',... - 'http://sound.media.mit.edu/resources/KEMAR.html']; -irs.head = 'KEMAR DB-4004'; -irs.room = 'Anechoic chamber of MIT'; -irs.loudspeaker = 'Optimus Pro 7'; -irs.distance = 1.7; -irs.fs = 44100; -irs.head_position = [0 0 0]; -irs.head_reference = [0 1 0]; -irs.source_position = [0 1.7 0]; -irs.source_reference = [0 0 0]; -irs.head_azimuth = NaN; -irs.head_elevation = NaN; - -% Read the data -elevs = -40:10:80; -steps = [6.43,6,5,5,5,5,5,6,6.43,8,10,15,30]; -idx = 1; -for jj = 1:length(elevs) - for phi = 0:steps(jj):180 - irfile = sprintf('%s/elev%i/H%ie%03.0fa.wav',irspath,elevs(jj),... - elevs(jj),phi); - ir = wavread(irfile); - irs.apparent_azimuth(idx) = correct_azimuth(rad(-phi)); - irs.apparent_elevation(idx) = correct_elevation(rad(elevs(jj))); - irs.head_azimuth(idx) = correct_azimuth(rad(phi)); - irs.head_elevation(idx) = correct_elevation(rad(-elevs(jj))); - irs.left(:,idx) = ir(:,1); - irs.right(:,idx) = ir(:,2); - idx = idx+1; - end - for phi = steps(jj):steps(jj):180-steps(jj) - irfile = sprintf('%s/elev%i/H%ie%03.0fa.wav',irspath,elevs(jj),... - elevs(jj),phi); - ir = wavread(irfile); - irs.apparent_azimuth(idx) = correct_azimuth(rad(phi)); - irs.apparent_elevation(idx) = correct_elevation(rad(elevs(jj))); - irs.head_azimuth(idx) = correct_azimuth(rad(-phi)); - irs.head_elevation(idx) = correct_elevation(rad(-elevs(jj))); - irs.left(:,idx) = ir(:,2); - irs.right(:,idx) = ir(:,1); - idx = idx+1; - end -end -irfile = sprintf('%s/elev90/H90e000a.wav',irspath); -ir = wavread(irfile); -irs.apparent_azimuth(idx) = correct_azimuth(0); -irs.apparent_elevation(idx) = correct_elevation(rad(90)); -irs.head_azimuth(idx) = correct_azimuth(0); -irs.head_elevation(idx) = correct_elevation(rad(-90)); -irs.left(:,idx) = ir(:,1); -irs.right(:,idx) = ir(:,2); - -% Reorder fields -irs = order_irs_fields(irs); -% Reorder entries -irs = correct_irs_angle_order(irs); -% Check irs format -check_irs(irs); - -% Create the outdir -if ~exist(outdir,'dir') - mkdir(outdir); -end - -% Write IR mat-file -outfile = sprintf('%s/KEMAR_MIT.mat',outdir); -save('-v7',outfile,'irs'); diff --git a/SFS_ir/correct_irs_angle_order.m b/SFS_ir/correct_irs_angle_order.m deleted file mode 100644 index 008a37ef..00000000 --- a/SFS_ir/correct_irs_angle_order.m +++ /dev/null @@ -1,90 +0,0 @@ -function irs = correct_irs_angle_order(irs,conf) -%CORRECT_IRS_ANGLE_ORDER reorders the angle entries of a irs to be increasing -% -% Usage: irs = correct_irs_angle_order(irs,[conf]) -% -% Input options -% irs - irs struct -% conf - optional configuration struct (see SFS_config) -% -% Output options -% irs - irs struct with corrected angle ordering -% -% CORRECT_IRS_ANGLE_ORDER(irs,conf) corrects the order of the azimuth and -% elevation entries to be increasing over the whole range. This is needed for -% the interpolation functions. -% -% See also: ir_intpol - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 2; -narginchk(nargmin,nargmax); -if nargin==nargmax-1 - conf = SFS_config; -end -if conf.debug - check_irs(irs); -end - - -%% ===== Computation ===================================================== -% Sort azimuth angle and reorder the whole irs -irs.apparent_azimuth = correct_azimuth(irs.apparent_azimuth); -[~,idx] = sort(irs.apparent_azimuth); -irs.left = irs.left(:,idx); -irs.right = irs.right(:,idx); -irs.apparent_azimuth = irs.apparent_azimuth(idx); -irs.apparent_elevation = irs.apparent_elevation(idx); -if ~isequal(size(irs.head_azimuth),[1 1]) - irs.head_azimuth = irs.head_azimuth(idx); -end -if ~isequal(size(irs.head_elevation),[1 1]) - irs.head_elevation = irs.head_elevation(idx); -end -if ~isequal(size(irs.torso_azimuth),[1 1]) - irs.torso_azimuth = irs.torso_azimuth(idx); -end -if ~isequal(size(irs.torso_elevation),[1 1]) - irs.torso_elevation = irs.torso_elevation(idx); -end -if ~isequal(size(irs.distance),[1 1]) - irs.distance = irs.distance(idx); -end -if ~(isequal(size(irs.source_position),[3 1]) || ... - isequal(size(irs.source_position),[1 3])) - irs.source_position = irs.source_position(:,idx); -end diff --git a/SFS_ir/dummy_irs.m b/SFS_ir/dummy_irs.m index 9f5ffd24..cb45b8e4 100644 --- a/SFS_ir/dummy_irs.m +++ b/SFS_ir/dummy_irs.m @@ -1,82 +1,89 @@ -function irs = dummy_irs(nsamples) -% DUMMY_IRS creates a dummy dirac pulse IR set -% -% Usage: irs = dummy_irs([nsamples]) -% -% Input parameters: -% nsamples - length of impulse response in samples, default: 1024 -% -% Output parameters: -% irs - irs struct -% -% DUMMY_IRS(nsamples) creates a dummy IR data set (Dirac impulse) to check -% processing without IRs. It has a resolution of 1 deg for phi and theta, its -% length is given by nsamples. -% -% See also: new_irs, IR_format.txt - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input parameters ======================================= -nargmin = 0; -nargmax = 1; -narginchk(nargmin,nargmax); -if nargin>0 - isargpositivescalar(nsamples); -else - nsamples = 1024; -end - - -%% ===== Computation ===================================================== -% Create dirac pulse -ir = zeros(nsamples,1); -ir(300) = 1; -% Angles of dummy irs -theta = rad(-90:89); -phi = rad(-180:179); -% Replicate ir for all directions -ir = repmat(ir,1,length(phi)*length(theta)); -% Store data -irs = new_irs(); -irs.left = ir; -irs.right = ir; -tmp = repmat(phi,length(theta),1); -irs.apparent_azimuth = tmp(:)'; -irs.apparent_elevation = repmat(theta,1,length(phi)); -irs.source_position = [0 2.333 0]'; -irs.head_position = [0 0 0]'; -irs.distance = 2.333; -irs.description = ['HRIR dummy set (Dirac pulse) for testing your',... - 'frequency response, etc.']; +function sofa = dummy_irs(nsamples,conf) +%DUMMY_IRS dirac pulse impulse response SOFA dataset +% +% Usage: irs = dummy_irs([nsamples],conf) +% +% Input parameters: +% nsamples - length of impulse response in samples, default: 1024 +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% sofa - sofa struct +% +% DUMMY_IRS(nsamples,conf) creates a dummy impulse response data set (Dirac +% impulse) to check processing without real impulse responses. It returns only +% one Dirac impulse, which is then applied for all direction if you for +% example use it together with ir_wfs(). +% +% See also: SOFAgetConventions, get_ir, ir_wfs + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking input parameters ======================================= +nargmin = 1; +nargmax = 2; +narginchk(nargmin,nargmax); +if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 2; -narginchk(nargmin,nargmax); -if nargin==nargmax-1 - conf = SFS_config; -end -isargstruct(conf); - - -%% ===== Configuration =================================================== -c = conf.c; -fs = conf.fs; -N = conf.N; - - -%% ===== Main ============================================================ -% Get distance of HRTF data set -dist = max(irs.distance); -if dist>10 - warning(['%s: Your maximum distance of the HRTF set is more than 10m. ', ... - 'We will only pad zeros for 10m, this can lead to problems with ', ... - 'get_ir().'],upper(mfilename)); - dist = 10; -end -% Append zeros at the beginning of the HRTFs corresponding to its maximum -% distance -samples = ceil(dist/c * fs); -if N-samples<128 - error(['%s: choose a larger conf.N value, because otherwise you ', ... - 'will have only %i samples of your original impulse response.'], ... - upper(mfilename),N-samples); -end -channels = size(irs.left,2); -irs.left = [zeros(samples,channels); fix_length(irs.left,N-samples)]; -irs.right = [zeros(samples,channels); fix_length(irs.right,N-samples)]; diff --git a/SFS_ir/get_ir.m b/SFS_ir/get_ir.m index c0c8f9fa..7b9a4a60 100644 --- a/SFS_ir/get_ir.m +++ b/SFS_ir/get_ir.m @@ -1,177 +1,251 @@ -function ir = get_ir(irs,xs,coordinate_system,conf) -%GET_IR returns a IR for the given apparent angle +function ir = get_ir(sofa,X,head_orientation,xs,coordinate_system,conf) +%GET_IR impulse response for the given apparent angle % -% Usage: ir = get_ir(irs,xs,[coordinate_system],[conf]) +% Usage: ir = get_ir(sofa,X,head_orientation,xs,coordinate_system,conf) % % Input parameters: -% irs - IR data set -% xs - position of the desired source / m -% this is always assumed to be from the position of the listener -% which is et to [0 0 0] implicitly -% coordinate_system - coordinate system xs is specified in, avialable -% systems are: -% 'spherical' - spherical system with phi / rad, -% delta / rad, r / m (default) -% 'cartesian' - cartesian system with x,y,z / m -% conf - optional configuration struct (see SFS_config) +% sofa - impulse response data set (sofa struct/file) +% X - position of the listener, specified in the defined +% coordinate_system, see below +% head_orientation - orientation of the listener with [phi theta] / +% (rad, rad) +% xs - position of the desired source, specified in the +% defined coordinate_system, see below. For +% SOFA convention SimpleFreeFieldHRIR xs will be +% interpreted relative to X, for MultiSpeakerBRIR as +% an absolute position. +% coordinate_system - coordinate system X and xs are specified in, +% avialable systems are: +% 'cartesian' - cartesian system (default) with +% [x y z] / m +% 'spherical' - spherical system with +% [phi theta r] / (rad, rad, m) +% conf - configuration struct (see SFS_config) % % Output parameters: -% ir - IR for the given position (length of IR x 2) +% ir - impulse response for the given position (length of IR x 2) % -% GET_IR(irs,phi,delta,r,X0) returns a single IR set for the given angles -% phi and delta. If the desired angles are not present in the IR data set -% an interpolation is applied to create the desired angles. -% The desired radius is achieved by delaying and weighting the impulse -% response. +% GET_IR(sofa,X,head_orientation,xs,conf) returns a single impulse response +% from the given SOFA file or struct. The impulse response is determined by +% the position X and head orientation head_orientation of the listener, and +% the position xs of the desired point source. +% If the desired angles are not present in the SOFA data set and +% conf.ir.useinterpolation is set to true an interpolation is applied to +% create the impulse response. For the SOFA convention MultiSpeakerBRIR the +% interpolation is only performed for the head orientations not the different +% loudspeaker positions. % -% See also: read_irs, slice_irs, intpol_ir +% For the SOFA convention SimpleFreeFieldHRIR the desired distance between +% the point source and listener is achieved by delaying and weighting the +% impulse response. In this case zeros are padded at the beginning and end +% of the impulse response and the length of ir is given by conf.N. The zeros +% added at the beginning correspond to the actual radius of the measured +% impulse response. +% +% For a description of the SOFA file format see: https://sofaconventions.org +% +% See also: SOFAload, sofa_get_header, sofa_get_data_fir, sofa_get_data_fire, +% interpolate_ir, ir_correct_distance %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 2; -nargmax = 4; +nargmin = 5; +nargmax = 6; narginchk(nargmin,nargmax) -if nargin==nargmax-1 - if isstruct(coordinate_system) - conf = coordinate_system; - coordinate_system = 'spherical'; - else - conf = SFS_config; - end -elseif nargin==nargmax-2 - coordinate_system = 'spherical'; - conf = SFS_config; +if nargin0.01 + warning('SFS:get_ir',['Your chosen listening position (%.2f,', ... + '%.2f,%.2f)m is not available, using the ', ... + 'measured one (%.2f,%.2f,%.2f)m instead.'], ... + X(1),X(2),X(3),X_sofa(1),X_sofa(2),X_sofa(3)); + end + % Find nearest loudspeaker + x0 = sofa_get_secondary_sources(header,'cartesian'); + x0 = x0(:,1:3); % need position only + idx_emitter = findnearestneighbour(x0,xs,1); + x0_new = x0(idx_emitter,:); + if norm(x0_new-xs)>0.01 + warning('SFS:get_ir',['Your chosen loudspeaker position (%.2f,', ... + '%.2f,%.2f)m deviates from the measured ', ... + 'one (%.2f,%.2f,%.2f)m.'], ... + xs(1),xs(2),xs(3),x0_new(1),x0_new(2),x0_new(3)); + end + % Get nearest neighbour point or points for interpolation for head orientation + [phi,theta,r] = sofa_get_head_orientations(header); + [sofa_head_orientations(:,1),sofa_head_orientations(:,2),... + sofa_head_orientations(:,3)] = sph2cart(phi,theta,r); + [head_orientation(1),head_orientation(2),head_orientation(3)] = ... + sph2cart(head_orientation(1),head_orientation(2),1); + [idx_head,weights] = point_selection(... + sofa_head_orientations,head_orientation,conf); + % Get impulse responses according to point selection + ir = sofa_get_data_fire(sofa,idx_head,idx_emitter); + ir = reshape(ir,[size(ir,1) size(ir,2) size(ir,4)]); % [M R E N] => [M R N] + % Select or interpolate to desired impulse response + ir = interpolate_ir(ir,weights,conf); -% Find the three nearest positions to the desired one (incorporating only angle -% values and disregarding the radius) -[neighbours,idx] = findnearestneighbour(x0(:,1:2)',xs,3); +elseif strcmp('SingleRoomDRIR',header.GLOBAL_SOFAConventions) + % + % http://www.sofaconventions.org/mediawiki/index.php/SingleRoomDRIR + % + error(['%s: SingleRoomDRIR is not supported as it should handle ', ... + 'microphone array recordings. If you used it for (multiple) ', ... + 'loudspeakers in a room you should consider to use ', ... + 'MultiSpeakerBRIR instead.'], upper(mfilename)); -% Check if we have found directly the desired point or have to interpolate -% bewteen different impulse responses -if norm(neighbours(:,1)-xs)10, ir_distance = 10; end - % Delay only if we have an delay other than 0 - if abs(r-ir_distance)>0.0001 % ~0.01 samples - % Time delay of the source (at the listener position) - delay = (r-ir_distance)/conf.c*conf.fs; % / samples - % Amplitude weighting (point source model) - % This gives weight=1 for r==ir_distance - weight = ir_distance/r; - if abs(delay)>size(ir,1) - error(['%s: your impulse response is to short for a desired ', ... - 'delay of %i samples.'],upper(mfilename),delay); - end - % Apply delay and weighting - ir = delayline(ir,[delay; delay],[weight; weight],conf); +% ========================================================================= + +function [idx,weights] = point_selection(x0,xs,conf) +%POINT_SELECTION selects points out of x0 with weights that can be used to +% interpolate an impulse response associated with xs out of impulse responses +% associated with x0(idx,:). Instead of interpolation, the nearest neighbour point +% can be selected as well. +% +% Input parameters: +% x0 - points in R^3 / m [nx3] +% xs - desired point in R^3 / m [1x3] +% conf - +% +% Output parameters: +% idx - row indices of N points in A [Nx1] +% weights - weights [Nx1] +useinterpolation = conf.ir.useinterpolation; +% Check for old configuration +if useinterpolation + if ~isfield(conf.ir,'interpolationpointselection') + warning('SFS:get_ir:interpolationpointselection',... + ['%s: no method for selection of interpolation points provided, ', ... + 'will use method ''nearestneighbour''.'],upper(mfilename)); + interpolationpointselection = 'nearestneighbour'; + else + interpolationpointselection = conf.ir.interpolationpointselection; end end +% Get nearest neighbour point or points for interpolation +if useinterpolation + switch interpolationpointselection + case 'nearestneighbour' + [idx,weights] = findnearestneighbour(x0,xs,2); + case 'delaunay' + [idx,weights] = findconvexcone(x0,xs); + case 'voronoi' + [idx,weights] = findvoronoi(x0, xs); + otherwise + error(['%s: ''%s'' is an unknown method to select interpolation ', ... + 'points.'],upper(mfilename),interpolationpointselection); + end +else + [idx,weights] = findnearestneighbour(x0,xs,1); +end +end diff --git a/SFS_ir/interpolate_ir.m b/SFS_ir/interpolate_ir.m new file mode 100644 index 00000000..816bafb8 --- /dev/null +++ b/SFS_ir/interpolate_ir.m @@ -0,0 +1,169 @@ +function ir = interpolate_ir(ir,weights,conf) +%INTERPOLATE_IR interpolates the given impulse responses according to their weights +% +% Usage: ir = interpolate_ir(ir,weights,conf) +% +% Input parameters: +% ir - matrix containing impulse responses in the form [M C N], where +% M ... Number of measurements +% C ... Number of channels +% N ... Number of samples +% weights - M weights for impulse reponses [M 1] +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% ir - impulse response for the given position [1 C N] +% +% INTERPOLATE_IR(ir,weights,conf) interpolates the given impulse responses +% by applying the given weights and returns the interpolated impulse response. +% Only impulse responses with weights larger that the precision prec=0.001 will +% be used. +% The interpolation method differs depending on the setting of +% conf.ir.interpolationmethod: +% 'simple' - Interpolation in the time domain performed samplewise. +% This does not heed the times of arrival of the impulse +% responses. +% 'freqdomain' - Interpolation in the frequency domain performed separately +% for magnitude and phase. +% 'timedomain' - Interpolation in the time domain with cross-correlation for +% estimation of time of arrival (TOA) differences +% Note that the given parameters are not checked if they all have the correct +% dimensions in order to save computational time, because this function could +% be called quite often. +% +% See also: get_ir, interpolation +% +% References: +% Hartung, Braasch, Sterbing (1999) - "Comparison of different methods for +% the interpolation of head-related transfer functions", 16th Conference +% of the Audio Engineering Society, Paper 16-028, +% http://www.aes.org/e-lib/browse.cfm?elib=8026 +% +% Itoh (1982) - "Analysis of the phase unwrapping algorithm", Applied +% Optics 21(14), p. 2470, https://doi.org/10.1364/AO.21.002470 + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters =================================== +nargmin = 3; +nargmax = 3; +narginchk(nargmin,nargmax); + + +%% ===== Configuration ================================================== +useinterpolation = conf.ir.useinterpolation; +% Check for old configuration +if useinterpolation + if ~isfield(conf.ir,'interpolationmethod') + warning('SFS:irs_intpolmethod',... + 'no interpolation method provided, will use method ''simple''.'); + interpolationmethod = 'simple'; + else + interpolationmethod = conf.ir.interpolationmethod; + end +end + +% Precision of the weights. Impulse responses with smaller weights are left out. +prec = 0.001; + + +%% ===== Computation ==================================================== +% Leave out impulse responses with weights smaller than prec +ir = ir(weights>=prec,:,:); +weights = weights(weights>=prec); + +% === IR interpolation === +if useinterpolation && length(weights)>1 + switch interpolationmethod + case 'simple' + ir = sum(bsxfun(@times,ir,weights),1); + case 'freqdomain' + % See Itoh (1982), Hartung et al. (1999) + % + % Upsample to avoid phase aliasing in unwrapping of phase + TF = fft(ir,4*size(ir,3),3); + % Magnitude and phase will be interpolated separately + idx_half = 2*size(ir,3)+1; % index for first half of spectrum + magnitude = abs(TF(:,:,1:idx_half)); + phase = unwrap(angle(TF(:,:,1:idx_half)),[],3); + % Mirror magnitude and phase + magnitude = cat(3,magnitude,magnitude(:,:,idx_half-1:-1:2)); + phase = cat(3,phase,-phase(:,:,idx_half-1:-1:2)); + % Calculate interpolation of the spectrum and downsample + magnitude = sum(bsxfun(@times,magnitude(:,:,1:4:end),weights),1); + phase = sum(bsxfun(@times,phase(:,:,1:4:end),weights),1); + % Calculate interpolated impulse response from new magnitude and phase + ir = ifft(magnitude.*exp(1i*phase),[],3); + % Avoid round-off errors + ir = real(ir); + case 'timedomain' + % See Hartung et al. (1999) + % + % Loop over channels + ir_results = zeros(1,size(ir,2),size(ir,3)); + for n = 1:size(ir,2) + % Determine TOA differences + ir_upsampled = resample(squeeze(ir(:,n,:))',10,1); + for nn = 1:size(ir,1) + [~,idx_max(nn)] = ... + max(xcorr(ir_upsampled(:,1),ir_upsampled(:,nn))); + end + N = size(ir_upsampled,1); + k = -(N-1):(N-1); + shifts = k(idx_max); + + % Shift all irs back to align with last ir + max_shift = max(shifts)-min(shifts); + TOA_diff_to_last = shifts-min(shifts); + ir_shifted = zeros(N+max_shift,size(ir,1)); + for nn = 1:size(ir,1) + ir_shifted(:,nn) = [zeros(TOA_diff_to_last(nn),1); ... + ir_upsampled(:,nn); ... + zeros(max_shift-TOA_diff_to_last(nn),1)]; + end + + % Interpolate aligned irs + ir_interp = sum(bsxfun(@times,ir_shifted,weights'),2); + + % Interpolate TOA differences and shift interpolated ir accordingly + TOA_diff_interp = round(TOA_diff_to_last*weights); + ir_interp = ... + ir_interp(TOA_diff_interp+1:end-(max_shift-TOA_diff_interp)); + + % Downsample and collect results per channel + ir_results(1,n,:) = resample(ir_interp,1,10); + end + ir = ir_results; + otherwise + error('%s: %s is an unknown interpolation method.', ... + upper(mfilename),interpolationmethod); + end +end diff --git a/SFS_ir/intpol_ir.m b/SFS_ir/intpol_ir.m deleted file mode 100644 index 99208353..00000000 --- a/SFS_ir/intpol_ir.m +++ /dev/null @@ -1,95 +0,0 @@ -function ir = intpol_ir(varargin) -%INTPOL_IR interpolates three given IRs for the given angle -% -% Usage: ir = intpol_ir(ir1,ir2,[ir3],x0,xs) -% -% Input parameters: -% ir1 - IR 1 -% ir2 - IR 2 -% ir3 - IR 3 (optional) -% x0 - matrix containing positions of single impulse -% responses / [rad rad] -% xs - desired position after interpolation / [rad rad] -% -% Output parameters: -% ir - IR for the given position -% -% INTPOL_IR(ir1,ir2,ir3,x0,xs) -% interpolates the three given IRs ir1,ir2 and ir3 with their corresponding -% angles x0 for the given angles xs and returns an interpolated impulse -% response. -% Note that the given parameter are not checked if they have all the right -% dimensions in order to save computational time, because this function could -% be called quiet often. -% -% See also: get_ir, shorten_ir, read_irs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 4; -nargmax = 5; -narginchk(nargmin,nargmax); - -%% ===== Computation ==================================================== -% --- 1D interpolation --- -if nargin==4 - ir1 = varargin{1}; - ir2 = varargin{2}; - x0 = varargin{3}; - xs = varargin{4}; - % Linear interpolation - ir = ir1 + (ir2-ir1) * norm(xs-x0(:,1))/norm(x0(:,2)-x0(:,1)); -else - ir1 = varargin{1}; - ir2 = varargin{2}; - ir3 = varargin{3}; - x0 = varargin{4}; - xs = varargin{5}; - % Linear interpolation - % - % x0(:,ii) xs - % w(ii) = -------------- - % |x0(:,ii)||xs| - % - w = vector_product(x0,repmat(xs',[1 3]),1) / ... - ( vector_norm(x0,1)./norm(xs)); - % The interpolation with 3 points hasn't been checked yet, hence we are - % including a checking of the w parameters - if any(w<0) - error('%s: one of your interpolation weights is <0.',upper(mfilename)); - end - % Calculate desired ir with linear combination of ir1,ir2 and ir3 - ir = w(1)*ir1 + w(2)*ir2 + w(3)*ir3; -end diff --git a/SFS_ir/ir_correct_distance.m b/SFS_ir/ir_correct_distance.m new file mode 100644 index 00000000..153de856 --- /dev/null +++ b/SFS_ir/ir_correct_distance.m @@ -0,0 +1,78 @@ +function ir = ir_correct_distance(ir,ir_distance,r,conf) +%IR_CORRECT_DISTANCE weights and delays an impulse reponse for a desired +%distance +% +% Usage: ir = ir_correct_distance(ir,ir_distance,r,conf) +% +% Input parameters: +% ir - impulse responses [M C N] +% M ... number of measurements +% C ... number of receiver channels +% N ... number of samples +% ir_distance - distance of the given impulse responses [M 1] +% r - desired distance [1] +% conf - configuration struct (see SFS_config) +% +% Output paramteres: +% ir - impulse responses [M C N] +% +% IR_CORRECT_DISTANCE(ir,ir_distance,r,conf) weights and delays the given +% impulse responses, that they are conform with the specified distance r. +% The impulse responses are zero-padded to length conf.N. +% +% See also: get_ir + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Configuration ================================================== +c = conf.c; +N = conf.N; +fs = conf.fs; +hrirpredelay = conf.ir.hrirpredelay / fs; + + +%% ===== Computation ==================================================== +% Append zeros at the end of the impulse responses to reach a length of N +ir_origlength = size(ir,3); +ir = cat(3,ir,zeros(size(ir,1),size(ir,2),N-ir_origlength)); +% Amplitude weighting (point source model) +% This gives weight=1 for r==ir_distance +weight = ir_distance./r; +% Time delay of the source (at the listener position) +delay = r/c - hrirpredelay; % / s +% Check if impulse responses are long enough compared to intended delay +if ir_origlength+delay*fs>conf.N + warning('SFS:get_ir',['%s: Choose a conf.N value larger than %i. ', ... + 'Otherwise you will lose samples from the end of the original ', ... + 'impulse response.'],upper(mfilename),ceil(ir_origlength+delay*fs)); +end +% Apply delay and weighting +ir = delayline(ir,delay,[weight; weight],conf); diff --git a/SFS_ir/irs2brs.m b/SFS_ir/irs2brs.m deleted file mode 100644 index 32f896de..00000000 --- a/SFS_ir/irs2brs.m +++ /dev/null @@ -1,79 +0,0 @@ -function brs = irs2brs(irs) -%IRS2BRS converts a irs data set to an brs set suitable for the SSR -% -% Usage: brs = irs2brs(irs) -% -% Input parameters: -% irs - irs data set -% -% Output parameters: -% brs - brs data set -% -% IRS2BRS(irs) converts a irs data set into a brs set suitable for the -% SoundScape Renderer. The brs data set is a matrix containing the -% channels for all directions. -% -% See also: set_wfs_25d - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 2; -narginchk(nargmin,nargmax) -if nargin==nargmax-1 - conf = SFS_config; -end -check_irs(irs); -isargstruct(conf); - - -%% ===== Main =========================================================== - -% Check if only one elevation angle is given -if length(unique(irs.apparent_elevation))~=1 - error(['%s: Your irs set has different elevation angles, which is',... - ' not supported by the SoundScape Renderer.'],upper(mfilename)); -end - -% TODO: check the order of angles -% I think the user have to check this by itself. Because the user -% could also be interested in a particular angle order - -for ii = 1:length(irs.apparent_azimuth) - brs(:,(ii-1)*2+1:ii*2) = [irs.left(:,ii) irs.right(:,ii)]; -end - - - diff --git a/SFS_ir/irs_with_particular_azimuth.m b/SFS_ir/irs_with_particular_azimuth.m deleted file mode 100644 index a5988d12..00000000 --- a/SFS_ir/irs_with_particular_azimuth.m +++ /dev/null @@ -1,70 +0,0 @@ -function irs = irs_with_particular_azimuth(irs,phi) -%IRS_WITH_PARTICULAR_ELEVATION(irs,phi) returns an IRS set which only contains -%data for one azimuth -% -% Usage: irs = irs_with_particular_azimuth(irs,[phi]) -% -% Input parameters: -% irs - IR data set -% phi - azimuth angle for the desired IR / rad -% default: 0 -% -% Output parameters: -% irs - IRS for the given azimuth -% -% IRS_WITH_PARTICULAR_ELEVATION(irs,phi) returns a IRS set for the given angle -% phi, or by default the medial plane. Input should be an IRS-set with -% diffrent values for the azimuth -% -% See also: slice_irs, new_irs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 2; -narginchk(nargmin,nargmax) -check_irs(irs); -if nargin==nargmax - isargscalar(phi); -else - phi = 0; -end - - -%% ===== Computation ==================================================== - -% Finding the entries belonging to phi and slice the irs -idx = (( round(irs.apparent_azimuth*10)==round(10*phi) )); -irs = slice_irs(irs,idx); diff --git a/SFS_ir/irs_with_particular_elevation.m b/SFS_ir/irs_with_particular_elevation.m deleted file mode 100644 index 3f9d83b6..00000000 --- a/SFS_ir/irs_with_particular_elevation.m +++ /dev/null @@ -1,69 +0,0 @@ -function irs = irs_with_particular_elevation(irs,delta) -%IRS_WITH_PARTICULAR_ELEVATION(irs,delta) returns an IRS set which only contains -%data for one elevation -% -% Usage: irs = irs_with_particular_elevation(irs,[delta]) -% -% Input parameters: -% irs - IR data set -% delta - elevation angle for the desired IR / rad -% default: 0 -% -% Output parameters: -% irs - IRS for the given elevation -% -% IRS_WITH_PARTICULAR_ELEVATION(irs,delta) returns a IRS set for the given -% angle delta, or by default the horizontal plane. Input should be an IRS-set -% with diffrent values for the elevation -% -% See also: slice_irs, new_irs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 2; -narginchk(nargmin,nargmax) -check_irs(irs); -if nargin==nargmax - isargscalar(delta); -else - delta = 0; -end - - -%% ===== Computation ==================================================== -% Finding the entries belonging to delta and slice the irs -idx = (( round(irs.apparent_elevation*10)==round(10*delta) )); -irs = slice_irs(irs,idx); diff --git a/SFS_ir/new_irs.m b/SFS_ir/new_irs.m deleted file mode 100644 index 5d74b300..00000000 --- a/SFS_ir/new_irs.m +++ /dev/null @@ -1,87 +0,0 @@ -function [irs,opt_fields] = new_irs() -%NEW_IRS creates an empty irs struct in the right format -% -% Usage: irs = new_irs() -% -% Output options -% irs - irs struct in the desired format -% opt_fields - cell array containing which of the fields in the returning -% irs struct are optional -% -% NEW_IRS() creates a irs struct in the format we have defined for the IR data -% sets. This function creates a reference implementation of the format. So -% don't change this function! -% -% See also: check_irs, IR_format.txt - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 0; -nargmax = 0; -narginchk(nargmin,nargmax); - - -%% ===== Computation ===================================================== -% The following fields are only optional -opt_fields = {'room_corners'}; -% Create our reference irs struct -irs = struct; -irs.description = 'Reference implementation of the irs struct.'; -irs.head = 'dummy'; % Used dummy head -irs.ears = 'dummy'; % Used dummy head ears -irs.room = 'dummy'; % Used room -irs.room_corners = [0 0 0]'; % corners of the used room -irs.source = 'dummy'; % Used loudsoeaker -irs.distance = 1; % Distance between head and source. NOTE: this - %>has to be norm(head_position-source_position) -irs.fs = 44100; % Sampling rate -irs.head_position = [0 0 0]'; % Position of head -irs.head_reference = [0 1 0]'; % Position to which the head is pointing. - %>head_direction = head_reference-head_position -irs.source_position = [0 1 0]'; % Position of loudspeaker source -irs.source_reference = [0 0 0]';% Position to which the source is pointing. - %>source_direction = - %>source_reference-source_position -irs.head_azimuth = NaN; % Head azimuth (NaN if no rotation took place) -irs.head_elevation = NaN; % Head elevation (NaN if no rotation took place) -irs.torso_azimuth = NaN; % Torso azimuth (NaN if no rotation took place) -irs.torso_elevation = NaN; % Torso elevation (NaN if no rotation took - %>place) -irs.apparent_azimuth = []; % Apparent azimuth of source in relation to - %>head direction -irs.apparent_elevation = []; % Apparent elevation of source in relation to - %>head direction -irs.left = []; % Left ear signal -irs.right = []; % Right ear signal diff --git a/SFS_ir/order_irs_fields.m b/SFS_ir/order_irs_fields.m deleted file mode 100644 index a8b4b37c..00000000 --- a/SFS_ir/order_irs_fields.m +++ /dev/null @@ -1,100 +0,0 @@ -function irs = order_irs_fields(irs) -%ORDER_IRS_FIELDS orders the fields in irs according to the new_irs reference -% -% Usage: irs = order_irs_fields(irs) -% -% Input options: -% irs - irs struct -% -% Output options -% irs - irs struct with the fields in the order as in new_irs() -% -% ORDER_IRS_FIELDS(irs) reorders the fields in the given irs according to the -% order given in the new_irs function, which is our reference implementation -% for the irs format. If the given irs struct contains more fields, the -% additional fields will be appended at the end of the struct in the order -% given in the original struct. -% -% See also: new_irs, check_irs, IR_format.txt - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 1; -narginchk(nargmin,nargmax); -% Disable the ordering warning, becuase we wanted to reorder the entries -warning('off','SFS:irs_fields_order'); -check_irs(irs); -warning('on','SFS:irs_fields_order'); - - -%% ===== Computation ===================================================== -% Get the reference implementation of the irs format and reorder the fields of -% the given irs according to the reference implementation. -[ref_irs,opt_fields] = new_irs(); -% Get fields -ref_fields = fieldnames(ref_irs); -% Get the fields for the given irs -fields = fieldnames(irs); -% If the number of fields is identical sort directly -if length(ref_fields)==length(fields) - irs = orderfields(irs,ref_fields); -else - % Remove unneeded optional fields from the reference - idx = []; - for ii = 1:length(ref_fields) - if ~isfield(irs,ref_fields{ii}) && strcmp(opt_fields,ref_fields{ii}) - idx = [idx ii]; - end - end - ref_fields(idx) = []; - % Get the indices of the positions of the ref_fields in the given irs - idx = []; - for ii = 1:length(ref_fields) - for jj = 1:length(fields) - if strcmp(fields{jj},ref_fields{ii}) - idx = [idx,jj]; - end - end - end - % Get the indices for additional fields - for jj = 1:length(fields) - if ~any(idx==jj) - idx = [idx,jj]; - end - end - sorted_fields = fields(idx); - irs = orderfields(irs,sorted_fields); -end diff --git a/SFS_ir/read_irs.m b/SFS_ir/read_irs.m deleted file mode 100644 index 977d2a5d..00000000 --- a/SFS_ir/read_irs.m +++ /dev/null @@ -1,76 +0,0 @@ -function irs = read_irs(irsfile,conf) -%READ_IRS Read a HRIR/BRIR dataset -% -% Usage: irs = read_irs(irsfile,[conf]) -% -% Input parameters: -% irsfile - filename of irs mat file -% -% Output paramteres: -% irs - irs struct. For details on the containing fields have a look at -% the IR_format.txt file. -% conf - optional configuration struct (see SFS_config) -% -% READ_IRS(irsfile) loads a IR dataset as a struct containing the format -% specific fields. For a description of the mat format for the IR datasets, -% see IR_format.txt. -% -% See also: get_ir, intpol_ir, dummy_irs, new_irs, ir_point_source - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 2; -narginchk(nargmin,nargmax); -if nargin==nargmax-1 - conf = SFS_config; -end -isargfile(irsfile); -isargstruct(conf); - - -%% ===== Configuration ================================================ -useoriglength = conf.ir.useoriglength; - - -%% ===== Read IR files ================================================ -% Load the mat file -load(irsfile); -% Check irs format -check_irs(irs); -if ~useoriglength - % Correct beginning zeros and length of impulse response - irs = fix_irs_length(irs,conf); -end diff --git a/SFS_ir/reduce_ir.m b/SFS_ir/reduce_ir.m index b3aaa183..e18959d0 100644 --- a/SFS_ir/reduce_ir.m +++ b/SFS_ir/reduce_ir.m @@ -1,109 +1,99 @@ -function ir = reduce_ir(ir,fs,nsamples,conf) -%REDUCE_IR resamples and shortens a IR -% -% Usage: ir = reduce_ir(ir,fs,nsamples,[conf]) -% -% Input parameters: -% ir - two channel IR signal -% fs - sampling rate of the target IR / Hz -% nsamples - length of the target IR -% conf - optional configuration struct (see SFS_config) -% -% Output paramteres: -% ir - two channel IR signal -% -% REDUCE_IR(ir,fs,nsamples,conf) shortens and resamples a given IR. -% This can be useful for mobile phones. -% -% See also: SFS_config, read_irs, intpol_ir, shorten_ir - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargpositivescalar(fs,nsamples); -if ~isnumeric(ir) || size(ir,2)~=2 - error('%s: ir has to be an IR with samples x 2 size.',upper(mfilename)); -end -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 2; -nargmax = 2; -narginchk(nargmin,nargmax); -check_irs(irs); -isargchar(outfile); - - -%% ===== Save IR file =================================================== - -% Save as mat file -% If -v7 doesn't work use -v6, but note this won't use any compression of your -% data -save('-v7',outfile,'irs'); diff --git a/SFS_ir/shorten_ir.m b/SFS_ir/shorten_ir.m index a027edda..809e7a13 100644 --- a/SFS_ir/shorten_ir.m +++ b/SFS_ir/shorten_ir.m @@ -1,62 +1,58 @@ -function ir = shorten_ir(ir,nsamples) -%SHORTEN_IR shortens a IR -% -% Usage: ir = shorten_ir(ir,nsamples) -% -% Input parameters: -% ir - IR signal with length x channels -% nsamples - length of the target IR -% -% Output paramteres: -% ir - IR signal with nsamples x n -% -% SHORTEN_HRIR(ir,nsamples) shortens a given IR to the given number of samples -% nsamples and applying a 5% long hanning window. -% -% See also: SFS_config, read_irs, intpol_ir, reduce_ir - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 2; -nargmax = 2; -narginchk(nargmin,nargmax); -isargpositivescalar(nsamples); - - -%% ===== Computation ==================================================== -% Window IR -win = hann_window(0,ceil(0.05*nsamples),nsamples); - -ir = ir(1:nsamples,:) .* repmat(win,[1 size(ir,2)]); +function ir = shorten_ir(ir,nsamples) +%SHORTEN_IR shortens an impulse response +% +% Usage: ir = shorten_ir(ir,nsamples) +% +% Input parameters: +% ir - impulse response with length x channels +% nsamples - length of the target impulse response +% +% Output paramteres: +% ir - impulse response signal with nsamples x n +% +% SHORTEN_IR(ir,nsamples) shortens a given impulse response to the given +% number of samples nsamples and applying a 5% long hanning window. +% +% See also: get_ir, reduce_ir + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 2; +nargmax = 2; +narginchk(nargmin,nargmax); +isargpositivescalar(nsamples); + + +%% ===== Computation ==================================================== +% Window impulse response +win = hann_window(0,ceil(0.05*nsamples),nsamples); +ir = ir(1:nsamples,:) .* repmat(win,[1 size(ir,2)]); diff --git a/SFS_ir/slice_irs.m b/SFS_ir/slice_irs.m deleted file mode 100644 index 081c1a0f..00000000 --- a/SFS_ir/slice_irs.m +++ /dev/null @@ -1,85 +0,0 @@ -function irspart = slice_irs(irs,idx) -%SLICE_IRS returns a part of an IRs set given by idx -% -% Usage: irspart = slice_irs(irs,idx) -% -% Input parameters: -% irs - IR data set -% idx - idx to slice out of the IR set -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% irspart - HRIR/BRIR containing only the part of the original IR set -% given by idx -% -% SLICE_IRS(irs,idx) returns a part of the IR set irs given by idx. The new -% part is a full IR set containing all the necessary struct elements. -% -% See also: get_ir, read_irs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 2; -nargmax = 2; -narginchk(nargmin,nargmax); - - -%% ===== Slicing the IR set ============================================== -irspart = irs; -irspart.left = irs.left(:,idx); -irspart.right = irs.right(:,idx); -irspart.apparent_azimuth = irs.apparent_azimuth(idx); -irspart.apparent_elevation = irs.apparent_elevation(idx); -if ~all(size(irs.head_azimuth)==[1 1]) - irspart.head_azimuth = irs.head_azimuth(idx); -end -if ~all(size(irs.head_elevation)==[1 1]) - irspart.head_elevation = irs.head_elevation(idx); -end -if ~all(size(irs.torso_azimuth)==[1 1]) - irspart.torso_azimuth = irs.torso_azimuth(idx); -end -if ~all(size(irs.torso_elevation)==[1 1]) - irspart.torso_elevation = irs.torso_elevation(idx); -end -if ~all(size(irs.distance)==[1 1]) - irspart.distance = irs.distance(idx); -end -if ~all(size(irs.source_position)==[3 1]) - irspart.source_position = irs.source_position(idx); -end -if ~all(size(irs.source_reference)==[3 1]) - irspart.source_reference = irs.source_reference(idx); -end diff --git a/SFS_ir/sofa2brs.m b/SFS_ir/sofa2brs.m new file mode 100644 index 00000000..5e1945ac --- /dev/null +++ b/SFS_ir/sofa2brs.m @@ -0,0 +1,78 @@ +function brs = sofa2brs(sofa) +%SOFA2BRS converts a sofa file/struct to a brs set suitable for the SSR +% +% Usage: brs = sofa2brs(sofa) +% +% Input parameters: +% sofa - sofa struct or file name +% +% Output parameters: +% brs - brs data set +% +% SOFA2BRS(sofa) converts a the given sofa file or struct into a brs set +% suitable for th SoundScape Renderer. The brs data set is a matrix containing +% the channels for all directions. As the SoundScape Renderer is currently +% only working in the horizontal plane, only impulse responses from the sofa +% data set are used with an elevation of 0. +% +% See also: sofa_get_header, sofa_get_data, SOFAcalculateAPV + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax) + + +%% ===== Main =========================================================== +header = sofa_get_header(sofa); +if ~strcmp('SimpleFreeFieldHRIR',header.GLOBAL_SOFAConventions) + error('%s: this SOFA Convention is currently not supported.'); +end +% Get available source positions relative to listener view +x0 = SOFAcalculateAPV(header); % / [deg deg m] +% Find elevation = 0 +idx = find(abs(x0(:,2))<=eps); +if length(idx)==0 + error(['%s: Your sofa file has no data for an elevation angle of 0deg.' ... + ' Other angles are not supported by the SoundScape Renderer.'], ... + upper(mfilename)); +end +% Sort azimuth angle in ascending order +[~,sort_idx] = sort(correct_azimuth(rad(x0(idx,1)))); +% Get corresponding impulse responses +ir = sofa_get_data(sofa,idx(sort_idx)); +% Generate brs set +brs = zeros(sofa.API.N,2*size(ir,1)); +for ii = 1:size(ir,1) + brs(:,ii*2-1:ii*2) = squeeze(ir(ii,:,:))'; +end diff --git a/SFS_ir/sofa_get_data_fir.m b/SFS_ir/sofa_get_data_fir.m new file mode 100644 index 00000000..fd66ff05 --- /dev/null +++ b/SFS_ir/sofa_get_data_fir.m @@ -0,0 +1,85 @@ +function ir = sofa_get_data_fir(sofa,idx) +%SOFA_GET_DATA_FIR returns a FIR data matrix from a SOFA file or struct +% +% Usage: ir = sofa_get_data_fir(sofa,[idx]) +% +% Input parameters: +% sofa - impulse response data set (SOFA struct/file) +% idx - index of the single impulse responses that should be returned. +% idx could be a single value, then only one impulse response +% will be returned, or it can be a vector then all impulse +% responses for the corresponding index positions will be +% returned (default: return all impulse responses) +% +% Output parameters: +% ir - impulse response (M,2,N), where +% M ... number of impulse responses +% N ... samples +% +% SOFA_GET_DATA_FIR(sofa,idx) returns impulse response of the given +% SOFA file or struct, specified by idx. If no idx is specified all data +% contained in sofa is returned. +% For the struct the SOFA file has to loaded before with SOFAload(). +% For a description of the SOFA file format see: https://sofaconventions.org +% +% See also: sofa_get_data_fire, sofa_get_header, get_ir, SOFAload + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 2; +narginchk(nargmin,nargmax) +if nargin==nargmax-1 + idx = []; +else + isargvector(idx); +end + + +%% ===== Computation ==================================================== +if length(idx)==0 + if sofa_is_file(sofa) + sofa = SOFAload(sofa); + end + ir = sofa.Data.IR; +else + header = sofa_get_header(sofa); + if sofa_is_file(sofa) + ir = zeros(length(idx),2,header.API.N); + for ii=1:length(idx) + tmp = SOFAload(sofa,[idx(ii) 1]); + ir(ii,:,:) = tmp.Data.IR; + end + else + ir = sofa.Data.IR(idx,:,:); + end +end diff --git a/SFS_ir/sofa_get_data_fire.m b/SFS_ir/sofa_get_data_fire.m new file mode 100644 index 00000000..4e5586d3 --- /dev/null +++ b/SFS_ir/sofa_get_data_fire.m @@ -0,0 +1,103 @@ +function ir = sofa_get_data_fire(sofa,idxM,idxE) +%SOFA_GET_DATA_FIRE returns a FIRE data matrix from a SOFA file or struct +% +% Usage: ir = sofa_get_data_fire(sofa,[idxM],[idxE]) +% +% Input parameters: +% sofa - impulse response data set (SOFA struct/file) +% idxM - index of the measurements for which the single impulse +% responses should be returned. +% idxM could be a single value, then only one impulse response +% will be returned, or it can be a vector then all impulse +% responses for the corresponding index positions will be +% returned (default: all measurements). +% idxE - index of the emitter for which the single impulse +% responses should be returned (default: all measurements). +% +% Output parameters: +% ir - impulse response (M,2,E,N), where +% M ... number of impulse responses +% E ... number of emitters (loudspeakers) +% N ... samples +% +% SOFA_GET_DATA_FIRE(sofa,idxM,idxE) returns impulse response of the given +% SOFA file or struct, specified by idxM and idxE, where idxM defines the +% measurements and idxE the emitters for which impulse responses should be +% returned. If no index is specified all data contained in sofa is returned. +% For the struct the SOFA file has to loaded before with SOFAload(). +% For a description of the SOFA file format see: https://sofaconventions.org +% +% see also: sofa_get_data_fir, sofa_get_header, get_ir, SOFAload + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 3; +narginchk(nargmin,nargmax) +if nargin==nargmax-1 + idxE = ':'; +elseif nargin==nargmax-2 + idxE = ':'; + idxM = ':'; +end + + +%% ===== Computation ==================================================== +if sofa_is_file(sofa) + header = sofa_get_header(sofa); + if isnumeric(idxE) && isnumeric(idxM) + ir = zeros(length(idxM),header.API.R,length(idxE),header.API.N); + for ii=1:length(idxM) + for jj=1:length(idxE) + tmp = SOFAload(sofa,[idxM(ii) 1],'M',[idxE(jj) 1],'E'); + ir(ii,:,jj,:) = tmp.Data.IR; + end + end + elseif isnumeric(idxE) + ir = zeros(header.API.M,header.API.R,length(idxE),header.API.N); + for jj=1:length(idxE) + tmp = SOFAload(sofa,[idxE(jj) 1],'E'); + ir(:,:,jj,:) = tmp.Data.IR; + end + elseif isnumeric(idxM) + ir = zeros(length(idxM),header.API.R,header.API.E,header.API.N); + for ii=1:length(idxM) + tmp = SOFAload(sofa,[idxM(ii) 1],'M'); + ir(ii,:,:,:) = tmp.Data.IR; + end + else + tmp = SOFAload(sofa); + ir = tmp.Data.IR; + end +else + ir = sofa.Data.IR(idxM,:,idxE,:); +end diff --git a/SFS_ir/sofa_get_head_orientations.m b/SFS_ir/sofa_get_head_orientations.m new file mode 100644 index 00000000..4e45e69f --- /dev/null +++ b/SFS_ir/sofa_get_head_orientations.m @@ -0,0 +1,69 @@ +function [phi,theta,r] = sofa_get_head_orientations(sofa,idx) +%SOFA_GET_HEAD_ORIENTATIONS returns phi, theta and r from the given SOFA data set +% +% Usage: [phi,theta,r] = sofa_get_head_orientations(sofa,[idx]) +% +% Input parameters: +% sofa - impulse response data set (SOFA struct/file) +% idx - index of measurement for which head orientation should be +% returned (default: return all head orientations) +% +% Output parameters: +% phi - head orientations in the horizontal plane / rad +% theta - head orientations in the median plane / rad +% r - head orientations radii / m +% +% SOFA_GET_HEAD_ORIENTATIONS(sofa,idx) returns head orientation [phi,theta,r] +% as defined in the given SOFA file or struct, specified by idx. If no idx is +% specified, all head orientations are returned. +% +% See also: get_ir, sofa_get_header, sofa_get_secondary_sources + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 2; +narginchk(nargmin,nargmax) +if nargin==nargmax-1 + idx = ':'; +else + isargvector(idx); +end + + +%% ===== Computation ==================================================== +header = sofa_get_header(sofa); +listener_view = SOFAconvertCoordinates(header.ListenerView, ... + header.ListenerView_Type,'spherical'); +phi = correct_azimuth(rad(listener_view(idx,1))); +theta = correct_elevation(rad(listener_view(idx,2))); +r = listener_view(idx,3); diff --git a/SFS_ir/sofa_get_header.m b/SFS_ir/sofa_get_header.m new file mode 100644 index 00000000..01b90c26 --- /dev/null +++ b/SFS_ir/sofa_get_header.m @@ -0,0 +1,63 @@ +function header = sofa_get_header(sofa) +%SOFA_GET_HEADER returns the header of a SOFA file or struct +% +% Usage: header = sofa_get_header(sofa) +% +% Input parameters: +% sofa - impulse response data set (SOFA struct/file) +% +% Output parameters: +% header - SOFA header +% +% SOFA_GET_HEADER(sofa) returns the header of the given SOFA file or struct. +% For the struct the SOFA file has to loaded before with SOFAload(). +% For a description of the SOFA file format see: https://sofaconventions.org +% +% See also: sofa_get_data, sofa_is_file, get_ir, SOFAload + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax) + + +%% ===== Computation ==================================================== +% Get only the metadata of the SOFA data set +if sofa_is_file(sofa) + header = SOFAload(sofa,'nodata'); +else + header = sofa; + if isfield(sofa.Data,'IR') + header.Data = rmfield(sofa.Data,'IR'); + end +end diff --git a/SFS_ir/sofa_get_listener_position.m b/SFS_ir/sofa_get_listener_position.m new file mode 100644 index 00000000..b360e046 --- /dev/null +++ b/SFS_ir/sofa_get_listener_position.m @@ -0,0 +1,76 @@ +function X = sofa_get_listener_position(sofa,coordinate_system) +%SOFA_GET_LISTENER_POSITION returns the listener position from the given SOFA +%data set +% +% Usage: X = sofa_get_listener_position(sofa,[coordinate_system]) +% +% Input parameters: +% sofa - impulse response data set (SOFA struct/file) +% coordinate_system - coordinate system the listener position should be +% specified in: +% 'cartesian' (default) +% 'spherical' +% +% Output parameters: +% X - listener position +% +% SOFA_GET_LISTENER_POSITION(sofa,coordinate_system) returns listener position +% X as defined in the given SOFA file or struct. +% +% See also: get_ir, sofa_get_header, sofa_get_listener_view + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 2; +narginchk(nargmin,nargmax) +if nargin==nargmax-1 + coordinate_system = 'cartesian'; +else + isargchar(coordinate_system); +end + + +%% ===== Computation ==================================================== +header = sofa_get_header(sofa); +X = SOFAconvertCoordinates(header.ListenerPosition, ... + header.ListenerPosition_Type, ... + coordinate_system); +if size(X,1)>1 + error(['%s: you have %i different listener positions, but only one is ', ... + 'currently supported by the SFS Toolbox.'],upper(mfilename), ... + size(X,1)); +end +if strcmp('spherical',coordinate_system) + X(1) = correct_azimuth(rad(X(1))); + X(2) = correct_elevation(rad(X(2))); +end diff --git a/SFS_ir/sofa_get_secondary_sources.m b/SFS_ir/sofa_get_secondary_sources.m new file mode 100644 index 00000000..205100bb --- /dev/null +++ b/SFS_ir/sofa_get_secondary_sources.m @@ -0,0 +1,122 @@ +function [x0,nss] = sofa_get_secondary_sources(sofa,idx,coordinate_system) +%SOFA_GET_SECONDARY_SOURCES returns x0 from the given SOFA data set +% +% Usage: [x0,nss] = sofa_get_secondary_sources(sofa,[idx],[coordinate_system]) +% +% Input parameters: +% sofa - impulse response data set (SOFA struct/file) +% idx - index of secondary sources that should be returned +% (default: return all secondary sources). +% coordinate_system - coordinate system the position and direction of the +% secondary sources should be specified in: +% 'cartesian' (default) +% 'spherical' +% +% Output parameters: +% x0 - secondary source matrix [n 7] +% nss - number of secondary sources +% +% SOFA_GET_SECONDARY_SOURCES(sofa,idx,coordinate_system) returns secondary +% sources as defined in the given SOFA file or struct, specified by idx. If +% no idx is specified all secondary sources are returned. The coordinate +% system the position and direction of the secondary sources are specified in +% can be given by the string 'coordinate_system', 'cartesian' is assumed as +% default. +% +% see also: sofa_get_header, secondary_source_positions + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 3; +narginchk(nargmin,nargmax) +if nargin==nargmax-2 + idx = ':'; + coordinate_system = 'cartesian'; +elseif nargin==nargmax-1 + if ischar(idx) + coordinate_system = idx; + idx = ':'; + else + coordinate_system = 'cartesian'; + end +else + isargvector(idx); + isargchar(coordinate_system); +end + + +%% ===== Computation ==================================================== +header = sofa_get_header(sofa); + +if strcmp('SimpleFreeFieldHRIR',header.GLOBAL_SOFAConventions) + % For free field HRTFs the source positions are equivalent to the apparent + % positons of the sources + apparent_directions = SOFAcalculateAPV(header); + [apparent_positions(:,1) apparent_positions(:,2) apparent_positions(:,3)] = ... + sph2cart(rad(apparent_directions(:,1)), ... + rad(apparent_directions(:,2)), ... + apparent_directions(:,3)); + x0 = [apparent_positions(idx,:) ... + direction_vector(apparent_positions(idx,:), ... + zeros(size(apparent_positions,1),3)) ... + ones(size(apparent_positions(idx,1)))]; + +elseif strcmp('SingleRoomDRIR',header.GLOBAL_SOFAConventions) + to_be_implemented; + +elseif strcmp('MultiSpeakerBRIR',header.GLOBAL_SOFAConventions) + source_position = SOFAconvertCoordinates( ... + header.SourcePosition,header.SourcePosition_Type,'cartesian'); + emitter_positions = SOFAconvertCoordinates( ... + header.EmitterPosition,header.EmitterPosition_Type,'cartesian'); + emitter_directions = SOFAconvertCoordinates( ... + header.EmitterView,header.EmitterView_Type,'cartesian'); + x0 = [bsxfun(@minus,emitter_positions(idx,:),source_position) ... + emitter_directions(idx,:) ... + ones(size(emitter_positions(idx,1)))]; + +else + error('%s: %s convention currently not supported.', ... + upper(mfilename),header.GLOBAL_SOFAConventions); +end + +nss = size(x0,1); + +if strcmp('cartesian',coordinate_system) + return; +elseif strcmp('spherical',coordinate_system) + [x0(:,1) x0(:,2) x0(:,3)] = cart2sph(x0(:,1),x0(:,2),x0(:,3)); +else + error('%s: %s is not a supported coordinate system.', ... + upper(mfilename),coordinate_system); +end diff --git a/SFS_ir/sofa_is_file.m b/SFS_ir/sofa_is_file.m new file mode 100644 index 00000000..eaf90417 --- /dev/null +++ b/SFS_ir/sofa_is_file.m @@ -0,0 +1,63 @@ +function boolean = sofa_is_file(sofa) +%SOFA_CHECK true for a sofa file, false for a sofa struct, throws an error else +% +% Usage: number = sofa_check(sofa) +% +% Input parameters: +% sofa - sofa struct or file name +% +% Output parameters: +% number - 1: sofa is a file +% 0: sofa is a struct +% +% SOFA_CHECK(sofa) checks if the given sofa is a file or a struct. In the +% first case a 1 is returned, in the second case a 0. If none of both is true +% an error will be thrown. +% +% See also: sofa_get_header, sofa_get_data + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax) + + +%% ===== Main =========================================================== +if ~isstruct(sofa) && exist(sofa,'file') + boolean = true; +elseif isstruct(sofa) && isfield(sofa,'GLOBAL_Conventions') && ... + strcmp('SOFA',sofa.GLOBAL_Conventions) + boolean = false; +else + error('%s: sofa has to be a file or a SOFA struct.',upper(mfilename)); +end diff --git a/SFS_monochromatic/circexp_mono/circexp_mono_ps.m b/SFS_monochromatic/circexp_mono/circexp_mono_ps.m new file mode 100644 index 00000000..4e0e7b68 --- /dev/null +++ b/SFS_monochromatic/circexp_mono/circexp_mono_ps.m @@ -0,0 +1,126 @@ +function Pm = circexp_mono_ps(xs,Nce,f,xq,fhp,conf) +%CIRCEXP_MONO_PS circular basis expansion of a mono-frequent point source +% +% Usage: Pm = circexp_mono_ps(xs,Nce,f,xq,[fhp],conf) +% +% Input parameters: +% xs - position of point source / m [1 x 3] +% Nce - maximum order of circular basis expansion +% f - frequency of the monochromatic source / Hz +% xq - expansion center / m [1 x 3] +% fhp - cut-off frequency of highpass for regularisation / Hz +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% Pm - regular circular expansion coefficients +% for m = 0:Nce, [1 x Nce+1] +% +% See also: circexp_mono_pw + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 5; +nargmax = 6; +narginchk(nargmin,nargmax); +isargcoord(xq,xs); +isargpositivescalar(Nce,f); +if nargin == nargmin + conf = fhp; +else + isargpositivescalar(fhp); +end + +%% ===== Configuration ================================================== +c = conf.c; + + +%% ===== Computation ===================================================== +xs = xs - xq; % shift coordinates +[phis, rs] = cart2pol(xs(1),xs(2)); +tau = rs/c; +omega = 2*pi*f; +omega_vec = [-omega.^2; 1i*omega; 1]; % vector for evaluation of SOS + +%------------------------------------------------------------------------------- +% Implementation of +% +% i^(|m|-m) +% P_m = -ik h_|m|(k rs) --------- e^(-im phis) +% 4pi +% +% The Laplace domain (s) respresentation of the spherical Hankel function: +% _____ +% exp(-s tau) | | (s - z_n/tau) +% h_|m|(s tau) = i^|m| ------------- | | ------------- +% -i s tau n (s - p_n/tau) +% +% z_n and p_n are the zeros and poles of the Hankel function. tau = r_s/c. +%------------------------------------------------------------------------------- + +% === Linkwitz-Riley (LR) filter for stabilisation === +zlr = []; +plr = []; +klr = 1; +if Nce > 0 + if nargin == nargmin + warning('without highpass filtering the implementation is not stable'); + else + % zero-pole-gain in s-domain of LR-Filter + Nlr = ceil(Nce/2)*2; + [zlr, plr, klr] = linkwitz_riley(Nlr, 2*pi*fhp, 'high', 's'); + end +end + +% Compute values for each mode m +Pm = zeros(1,2*Nce+1); +for m=0:Nce % Negative m can be inferred from symmetry relations + % === zero-pole-gain in s-domain of Spherical Hankel function === + kh=1; + if m==0 % not supported by octave + zh = []; ph = []; + else + [zh, ph] = sphbesselh_zeros(m); + zh = zh./tau; + ph = ph./tau; + end + % Zeros/poles remaining after compensating the poles of Hankel function + zlr_comp = zeros(length(zlr)-length(ph),1); % empty if negative + ph_comp = zeros(length(ph)-length(zlr),1); % empty if negative + % Generate second-order-sections + [sos, g] = zp2sos([zlr_comp; zh], [ph_comp; plr], klr*kh, 'down', 'none'); + % Compute value of sos at s = iw + Pm(m+Nce+1) = g.*prod( (sos(:,1:3)*omega_vec)./(sos(:,4:6)*omega_vec),1); +end + +Pm(1:Nce) = Pm(2*Nce+1:-1:Nce+2); % symmetry +Pm = Pm.*exp(+1i*(-Nce:Nce)*(pi/2-phis)); % apply terms only depending on m +Pm = Pm./(4*pi*rs).*exp(-1i*omega*tau); % scaling and delay diff --git a/SFS_monochromatic/circexp_mono/circexp_mono_pw.m b/SFS_monochromatic/circexp_mono/circexp_mono_pw.m new file mode 100644 index 00000000..573f2996 --- /dev/null +++ b/SFS_monochromatic/circexp_mono/circexp_mono_pw.m @@ -0,0 +1,67 @@ +function Pm = circexp_mono_pw(npw,Nce,f,xq,conf) +%CIRCEXP_MONO_PW circular basis expansion of a mono-freqeunt plane wave +% +% Usage: Pm = circexp_mono_pw(npw,Nce,xq,conf) +% +% Input parameters: +% npw - propagation direction of plane wave [1 x 3] +% Nce - maximum order of circular basis expansion +% f - frequency of the monochromatic source / Hz +% xq - optional expansion center / m [1 x 3] +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% Pm - regular circular expansion coefficients +% for m = 0:Nce, [1 x Nce+1] +% +% See also: circexp_mono_ps + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 5; +nargmax = 6; +narginchk(nargmin,nargmax); +isargcoord(xq,npw); +isargpositivescalar(Nce,f); +isargstruct(conf); + + +%% ===== Configuration ================================================== +c = conf.c; + + +%% ===== Computation ===================================================== +[phipw, ~] = cart2pol(npw(1),npw(2)); + +m = (-Nce:Nce); +Pm = (-1i).^m.*exp(-1i.*m.*phipw); +Pm = Pm.*exp(-1i*xq*npw.'*2*pi*f./c); diff --git a/SFS_monochromatic/driving_function_mono_localwfs_sbl.m b/SFS_monochromatic/driving_function_mono_localwfs_sbl.m new file mode 100644 index 00000000..0009a4c8 --- /dev/null +++ b/SFS_monochromatic/driving_function_mono_localwfs_sbl.m @@ -0,0 +1,72 @@ +function D = driving_function_mono_localwfs_sbl(x0,xs,src,f,conf) +%DRIVING_FUNCTION_MONO_LOCALWFS_SBL driving signal for local WFS using spatial +%bandwidth limitation +% +% Usage: D = driving_function_mono_localwfs_sbl(x0,xs,src,f,conf) +% +% Input parameters: +% x0 - position and direction of the secondary source / m [nx7] +% xs - position of point source or direction of plane +% wave / m [1x3] +% src - source type of the virtual source +% 'pw' - plane wave +% 'ps' - point source +% f - frequency of the monochromatic source / Hz +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% D - driving function [nx1] +% +% See also: sound_field_mono, sound_field_mono_localwfs_sbl + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 5; +nargmax = 5; +narginchk(nargmin,nargmax); +isargsecondarysource(x0); +isargxs(xs); +isargchar(src); +isargpositivescalar(f); +isargstruct(conf); + + +%% ===== Computation ========================================================== +switch src +case 'ps' + D = driving_function_mono_localwfs_sbl_ps(x0,xs,f,conf); +case 'pw' + xs = xs./norm(xs); + D = driving_function_mono_localwfs_sbl_pw(x0,xs,f,conf); +otherwise + error('%s: %s is not a known source type.',upper(mfilename),src); +end diff --git a/SFS_monochromatic/driving_function_mono_localwfs.m b/SFS_monochromatic/driving_function_mono_localwfs_vss.m similarity index 50% rename from SFS_monochromatic/driving_function_mono_localwfs.m rename to SFS_monochromatic/driving_function_mono_localwfs_vss.m index 0ef5f524..395480b1 100644 --- a/SFS_monochromatic/driving_function_mono_localwfs.m +++ b/SFS_monochromatic/driving_function_mono_localwfs_vss.m @@ -1,120 +1,118 @@ -function [D, x0, xv] = driving_function_mono_localwfs(x0,xs,src,f,conf) -%DRIVING_FUNCTION_MONO_LOCALWFS returns the driving signal D for local WFS -% -% Usage: [D, xv, x0] = driving_function_mono_localwfs(x0,xs,src,f,conf) -% -% Input parameters: -% x0 - position and direction of the secondary source / m [nx6] -% xs - position of virtual source or direction of plane -% wave / m [1x3] -% src - source type of the virtual source -% 'pw' - plane wave (xs is the direction of the -% plane wave in this case) -% 'ps' - point source -% 'ls' - line source -% 'fs' - focused source -% -% f - frequency of the monochromatic source / Hz -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% D - driving function signal [nx1] -% x0 - position, direction, and weights of the real secondary -% sources / m [nx7] -% xv - position, direction, and weights of the virtual secondary -% sources / m [mx7] -% -% References: -% S. Spors (2010) - "Local Sound Field Synthesis by Virtual Secondary -% Sources", 40th AES -% -% See also: plot_sound_field, sound_field_mono_wfs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - -%% ===== Checking of input parameters ================================== -nargmin = 4; -nargmax = 5; -narginchk(nargmin,nargmax); -isargsecondarysource(x0); -isargxs(xs); -isargpositivescalar(f); -isargchar(src); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 4; -nargmax = 5; -narginchk(nargmin,nargmax); -isargsecondarysource(x0); -isargxs(xs); -isargpositivescalar(f); -isargchar(src); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 4; -nargmax = 5; -narginchk(nargmin,nargmax); -isargsecondarysource(x0); -isargxs(xs); -isargpositivescalar(f); -isargchar(src); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 4; -nargmax = 5; -narginchk(nargmin,nargmax); -isargvector(kx); -isargxs(xs); -isargpositivescalar(f); -isargchar(src); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 4; -nargmax = 5; -narginchk(nargmin,nargmax); -isargsecondarysource(x0); -isargxs(xs); -isargpositivescalar(f); -isargchar(src); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 4; -nargmax = 5; -narginchk(nargmin,nargmax); -isargmatrix(x0,xs); -isargpositivescalar(f,N); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 4; -nargmax = 5; -narginchk(nargmin,nargmax); -isargmatrix(x0,xs); -isargpositivescalar(f,N); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 4; -nargmax = 5; -narginchk(nargmin,nargmax); -isargmatrix(x0,xs); -isargpositivescalar(f,N); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 4; -nargmax = 5; -narginchk(nargmin,nargmax); -isargmatrix(x0,nk); -isargpositivescalar(f,N); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargmatrix(x0,nk); -isargpositivescalar(f); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargmatrix(kx,xs); -isargpositivescalar(f); -if nargin (omega/c) )); -D = zeros(1,length(kx)); - -if strcmp('2D',dimension) - - % === 2-Dimensional ================================================== - - % Ensure 2D - xs = xs(:,1:2); - if strcmp('default',driving_functions) - % --- SFS Toolbox ------------------------------------------------ - to_be_implemented; - else - error(['%s: %s, this type of driving function is not implemented ', ... - 'for a 2D focused source.'],upper(mfilename),driving_functions); - end - - -elseif strcmp('2.5D',dimension) - - % === 2.5-Dimensional ================================================ - - % Reference point - if strcmp('default',driving_functions) - % --- SFS Toolbox ------------------------------------------------ - % D_25D(kx,w) = e^(i kx xs) ... - % ____________ - % H0^(2)( \|(w/c)^2-kx^2 |yref-ys| ) - % / - --------------_-_-_-_-_-_---------, |kx|<|w/c| - % | H0^(2)( \|(w/c)^2-kx^2 yref ) - % < ____________ - % | K0( \|kx^2-(w/c)^2 |yref-ys| ) - % \ ----------_-_-_-_-_-_---------, |kx|>|w/c| - % K0( \|kx^2-(w/c)^2 yref ) - % - % see Spors and Ahrens (2010), eq.(7) - % - D(idxpr) = exp(1i*kx(idxpr)*xs(1)) .* ... - besselh(0,2,sqrt( (omega/c)^2 - kx(idxpr).^2 )*abs(xref(2)-xs(2))) ./ ... - besselh(0,2,sqrt( (omega/c)^2 - kx(idxpr).^2 )*abs(xref(2)-x0(2))); - if(withev) - D(idxev) = exp(1i*kx(idxev)*xs(1)) .* ... - besselk(0,sqrt(kx(idxev).^2 - (omega/c).^2)*abs(xref(2)-xs(2))) ./ ... - besselk(0,sqrt(kx(idxev).^2 - (omega/c).^2)*abs(xref(2)-x0(2))); - end - - else - error(['%s: %s, this type of driving function is not implemented ', ... - 'for a 2.5D focused source.'],upper(mfilename),driving_functions); - end - - -elseif strcmp('3D',dimension) - - % === 3-Dimensional ================================================== - - if strcmp('default',driving_functions) - % --- SFS Toolbox ------------------------------------------------ - to_be_implemented; - else - error(['%s: %s, this type of driving function is not implemented ', ... - 'for a 3D focused source.'],upper(mfilename),driving_functions); - end - -else - error('%s: the dimension %s is unknown.',upper(mfilename),dimension); -end +function D = driving_function_mono_sdm_kx_fs(kx,xs,f,conf) +%DRIVING_FUNCTION_MONO_SDM_KX_FS driving signal for a focused source SDM in +%the kx-domain +% +% Usage: D = driving_function_mono_sdm_kx_fs(kx,xs,f,conf) +% +% Input parameters: +% kx - kx dimension [nx1] +% nk - position of focused source / m [1x3] +% f - frequency of the monochromatic source / Hz +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% D - driving function signal [nx1] +% +% See also: driving_function_mono_wfs, driving_function_imp_wfs_ps +% +% References: +% Spors and Ahrens (2010) - "Reproduction of Focused Sources by the +% Spectral Division Method", in 4th International Symposium on +% Communications, Control and Signal Processing (ISCCSP), +% https://doi.org/10.1109/ISCCSP.2010.5463335 + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 4; +nargmax = 4; +narginchk(nargmin,nargmax); +isargmatrix(kx,xs); +isargpositivescalar(f); +isargstruct(conf); + + +%% ===== Configuration ================================================== +xref = conf.xref; +c = conf.c; +dimension = conf.dimension; +driving_functions = conf.driving_functions; +x0 = conf.secondary_sources.center; +withev = conf.sdm.withev; + + +%% ===== Computation ==================================================== +% Calculate the driving function in time-frequency domain + +% Frequency +omega = 2*pi*f; +% Indexes for evanescent contributions and propagating part of the wave field +idxpr = (( abs(kx) <= (omega/c) )); +idxev = (( abs(kx) > (omega/c) )); +D = zeros(1,length(kx)); + +if strcmp('2D',dimension) + + % === 2-Dimensional ================================================== + + % Ensure 2D + xs = xs(:,1:2); + + switch driving_functions + case 'default' + % --- SFS Toolbox ------------------------------------------------ + to_be_implemented; + otherwise + error(['%s: %s, this type of driving function is not implemented ', ... + 'for a 2D focused source.'],upper(mfilename),driving_functions); + end + + +elseif strcmp('2.5D',dimension) + + % === 2.5-Dimensional ================================================ + + switch driving_functions + case 'default' + % --- SFS Toolbox ------------------------------------------------ + % D_25D(kx,w) = e^(i kx xs) ... + % ____________ + % H0^(2)( \|(w/c)^2-kx^2 |yref-ys| ) + % / - --------------_-_-_-_-_-_---------, |kx|<|w/c| + % | H0^(2)( \|(w/c)^2-kx^2 yref ) + % < ____________ + % | K0( \|kx^2-(w/c)^2 |yref-ys| ) + % \ ----------_-_-_-_-_-_---------, |kx|>|w/c| + % K0( \|kx^2-(w/c)^2 yref ) + % + % See Spors and Ahrens (2010), eq.(7) + % + D(idxpr) = exp(1i*kx(idxpr)*xs(1)) .* ... + besselh(0,2,sqrt( (omega/c)^2 - kx(idxpr).^2 )*abs(xref(2)-xs(2))) ./ ... + besselh(0,2,sqrt( (omega/c)^2 - kx(idxpr).^2 )*abs(xref(2)-x0(2))); + if(withev) + D(idxev) = exp(1i*kx(idxev)*xs(1)) .* ... + besselk(0,sqrt(kx(idxev).^2 - (omega/c).^2)*abs(xref(2)-xs(2))) ./ ... + besselk(0,sqrt(kx(idxev).^2 - (omega/c).^2)*abs(xref(2)-x0(2))); + end + + otherwise + error(['%s: %s, this type of driving function is not implemented ', ... + 'for a 2.5D focused source.'],upper(mfilename),driving_functions); + end + + +elseif strcmp('3D',dimension) + + % === 3-Dimensional ================================================== + + switch driving_functions + case 'default' + % --- SFS Toolbox ------------------------------------------------ + to_be_implemented; + otherwise + error(['%s: %s, this type of driving function is not implemented ', ... + 'for a 3D focused source.'],upper(mfilename),driving_functions); + end + +else + error('%s: the dimension %s is unknown.',upper(mfilename),dimension); +end diff --git a/SFS_monochromatic/driving_functions_mono/driving_function_mono_sdm_kx_ls.m b/SFS_monochromatic/driving_functions_mono/driving_function_mono_sdm_kx_ls.m index 0f170026..0c118ec9 100644 --- a/SFS_monochromatic/driving_functions_mono/driving_function_mono_sdm_kx_ls.m +++ b/SFS_monochromatic/driving_functions_mono/driving_function_mono_sdm_kx_ls.m @@ -1,133 +1,124 @@ -function D = driving_function_mono_sdm_kx_ls(kx,xs,f,conf) -%DRIVING_FUNCTION_MONO_SDM_KX_LS returns the driving signal D for a line source in -%SDM in the kx domain -% -% Usage: D = driving_function_mono_sdm_kx_ps(kx,xs,f,[conf]) -% -% Input parameters: -% kx - kx dimension [nx1] -% xs - position of line source / m [1x3] -% f - frequency of the monochromatic source / Hz -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% D - driving function signal [nx1] -% -% DRIVING_FUNCTION_MONO_SDM_KX_LS(kx,xs,f,conf) returns SDM driving signals -% for the given secondary sources, the virtual line source position and the -% frequency f. The driving signal is calculated in the kx domain. -% -% See also: driving_function_mono_sdm_kx - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargmatrix(kx); -isargxs(xs); -isargpositivescalar(f); -if nargin (omega/c) )); -D = zeros(1,length(kx)); - - -if strcmp('2D',dimension) - - % === 2-Dimensional ================================================== - - % Ensure 2D - xs = xs(1:2); - if strcmp('default',driving_functions) - % --- SFS Toolbox ------------------------------------------------ - to_be_implemented; - else - error(['%s: %s, this type of driving function is not implemented ', ... - 'for a 2D line source.'],upper(mfilename),driving_functions); - end - - -elseif strcmp('2.5D',dimension) - - % === 2.5-Dimensional ================================================ - - % Reference point - if strcmp('default',driving_functions) - % --- SFS Toolbox ------------------------------------------------ - to_be_implemented; - - else - error(['%s: %s, this type of driving function is not implemented ', ... - 'for a 2.5D line source.'],upper(mfilename),driving_functions); - end - - -elseif strcmp('3D',dimension) - - % === 3-Dimensional ================================================== - - if strcmp('default',driving_functions) - % --- SFS Toolbox ------------------------------------------------ - to_be_implemented; - else - error(['%s: %s, this type of driving function is not implemented ', ... - 'for a 3D line source.'],upper(mfilename),driving_functions); - end - -else - error('%s: the dimension %s is unknown.',upper(mfilename),dimension); -end +function D = driving_function_mono_sdm_kx_ls(kx,xs,f,conf) +%DRIVING_FUNCTION_MONO_SDM_KX_LS driving signal for a line source in SDM in +%the kx-domain +% +% Usage: D = driving_function_mono_sdm_kx_ps(kx,xs,f,conf) +% +% Input parameters: +% kx - kx dimension [nx1] +% xs - position of line source / m [1x3] +% f - frequency of the monochromatic source / Hz +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% D - driving function signal [nx1] +% +% See also: driving_function_mono_sdm_kx + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 4; +nargmax = 4; +narginchk(nargmin,nargmax); +isargmatrix(kx); +isargxs(xs); +isargpositivescalar(f); +isargstruct(conf); + + +%% ===== Configuration ================================================== +xref = conf.xref; +c = conf.c; +dimension = conf.dimension; +driving_functions = conf.driving_functions; +x0 = conf.secondary_sources.center; +withev = conf.sdm.withev; + + +%% ===== Computation ==================================================== +% Calculate the driving function in time-frequency domain + +% Frequency +omega = 2*pi*f; +% Indexes for evanescent contributions and propagating part of the wave field +idxpr = (( abs(kx) <= (omega/c) )); +idxev = (( abs(kx) > (omega/c) )); +D = zeros(1,length(kx)); + + +if strcmp('2D',dimension) + + % === 2-Dimensional ================================================== + + % Ensure 2D + xs = xs(1:2); + + switch driving_functions + case 'default' + % --- SFS Toolbox ------------------------------------------------ + to_be_implemented; + otherwise + error(['%s: %s, this type of driving function is not implemented ', ... + 'for a 2D line source.'],upper(mfilename),driving_functions); + end + + +elseif strcmp('2.5D',dimension) + + % === 2.5-Dimensional ================================================ + + switch driving_functions + case 'default' + % --- SFS Toolbox ------------------------------------------------ + to_be_implemented; + otherwise + error(['%s: %s, this type of driving function is not implemented ', ... + 'for a 2.5D line source.'],upper(mfilename),driving_functions); + end + + +elseif strcmp('3D',dimension) + + % === 3-Dimensional ================================================== + + switch driving_functions + case 'default' + % --- SFS Toolbox ------------------------------------------------ + to_be_implemented; + otherwise + error(['%s: %s, this type of driving function is not implemented ', ... + 'for a 3D line source.'],upper(mfilename),driving_functions); + end + +else + error('%s: the dimension %s is unknown.',upper(mfilename),dimension); +end diff --git a/SFS_monochromatic/driving_functions_mono/driving_function_mono_sdm_kx_ps.m b/SFS_monochromatic/driving_functions_mono/driving_function_mono_sdm_kx_ps.m index 57a524a9..0bbe0832 100644 --- a/SFS_monochromatic/driving_functions_mono/driving_function_mono_sdm_kx_ps.m +++ b/SFS_monochromatic/driving_functions_mono/driving_function_mono_sdm_kx_ps.m @@ -1,159 +1,143 @@ -function D = driving_function_mono_sdm_kx_ps(kx,xs,f,conf) -%DRIVING_FUNCTION_MONO_SDM_KX_PS returns the driving signal D for a point source in -%SDM in the kx domain -% -% Usage: D = driving_function_mono_sdm_kx_ps(kx,xs,f,[conf]) -% -% Input parameters: -% kx - kx dimension [nx1] -% xs - position of point source / m [1x3] -% f - frequency of the monochromatic source / Hz -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% D - driving function signal [nx1] -% -% DRIVING_FUNCTION_MONO_SDM_KX_PS(kx,xs,f,conf) returns SDM driving signals -% for the given secondary sources, the virtual point source position and the -% frequency f. The driving signal is calculated in the kx domain. -% -% References: -% H. Wierstorf, J. Ahrens, F. Winter, F. Schultz, S. Spors (2015) - -% "Theory of Sound Field Synthesis" -% S. Spors and J. Ahrens (2010) - "Reproduction of Focused Sources by the -% Spectral Division Method", ISCCSP -% -% See also: driving_function_mono_sdm_kx - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargmatrix(kx); -isargxs(xs); -isargpositivescalar(f); -if nargin (omega/c) )); -D = zeros(1,length(kx)); - -if strcmp('2D',dimension) - - % === 2-Dimensional ================================================== - - % Ensure 2D - xs = xs(1:2); - if strcmp('default',driving_functions) - % --- SFS Toolbox ------------------------------------------------ - to_be_implemented; - else - error(['%s: %s, this type of driving function is not implemented ', ... - 'for a 2D point source.'],upper(mfilename),driving_functions); - end - - -elseif strcmp('2.5D',dimension) - - % === 2.5-Dimensional ================================================ - - % Reference point - if strcmp('default',driving_functions) - % --- SFS Toolbox ------------------------------------------------ - % D_25D(kx,w) = e^(i kx xs) ... - % ____________ - % H1^(2)( \|(w/c)^2-kx^2 |yref-ys| ) - % / - --------------_-_-_-_-_-_---------, |kx|<|w/c| - % | H1^(2)( \|(w/c)^2-kx^2 yref ) - % < ____________ - % | K1( \|kx^2-(w/c)^2 |yref-ys| ) - % \ ----------_-_-_-_-_-_---------, |kx|>|w/c| - % K1( \|kx^2-(w/c)^2 yref ) - % - % see Wierstorf et al. (2015), eq.(#D:sdm:ps:2.5D) - % A time reversed version of this driving function for focused sources - % is given in Spors and Ahrens (2010), eq.(7). - % - D(idxpr) = exp(1i*kx(idxpr)*xs(1)) .* ... - besselh(1,2,sqrt( (omega/c)^2 - kx(idxpr).^2 )*abs(xref(2)-xs(2))) ./ ... - besselh(1,2,sqrt( (omega/c)^2 - kx(idxpr).^2 )*abs(xref(2)-x0(2))); - if(withev) - D(idxev) = exp(1i*kx(idxev)*xs(1)) .* ... - besselk(1,sqrt(kx(idxev).^2 - (omega/c).^2)*abs(xref(2)-xs(2))) ./ ... - besselk(1,sqrt(kx(idxev).^2 - (omega/c).^2)*abs(xref(2)-x0(2))); - end - - else - error(['%s: %s, this type of driving function is not implemented ', ... - 'for a 2.5D point source.'],upper(mfilename),driving_functions); - end - - -elseif strcmp('3D',dimension) - - % === 3-Dimensional ================================================== - - if strcmp('default',driving_functions) - % --- SFS Toolbox ------------------------------------------------ - to_be_implemented; - else - error(['%s: %s, this type of driving function is not implemented ', ... - 'for a 3D point source.'],upper(mfilename),driving_functions); - end - -else - error('%s: the dimension %s is unknown.',upper(mfilename),dimension); -end +function D = driving_function_mono_sdm_kx_ps(kx,xs,f,conf) +%DRIVING_FUNCTION_MONO_SDM_KX_PS driving signal for a point source in SDM in +%the kx-domain +% +% Usage: D = driving_function_mono_sdm_kx_ps(kx,xs,f,conf) +% +% Input parameters: +% kx - kx dimension [nx1] +% xs - position of point source / m [1x3] +% f - frequency of the monochromatic source / Hz +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% D - driving function signal [nx1] +% +% See also: driving_function_mono_sdm_kx + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 4; +nargmax = 4; +narginchk(nargmin,nargmax); +isargmatrix(kx); +isargxs(xs); +isargpositivescalar(f); +isargstruct(conf); + + +%% ===== Configuration ================================================== +xref = conf.xref; +c = conf.c; +dimension = conf.dimension; +driving_functions = conf.driving_functions; +x0 = conf.secondary_sources.center; +withev = conf.sdm.withev; + + +%% ===== Computation ==================================================== +% Calculate the driving function in time-frequency domain + +% Frequency +omega = 2*pi*f; +% Indexes for evanescent contributions and propagating part of the wave field +idxpr = (( abs(kx) <= (omega/c) )); +idxev = (( abs(kx) > (omega/c) )); +D = zeros(1,length(kx)); + +if strcmp('2D',dimension) + + % === 2-Dimensional ================================================== + + % Ensure 2D + xs = xs(1:2); + + switch driving_functions + case 'default' + % --- SFS Toolbox ------------------------------------------------ + to_be_implemented; + otherwise + error(['%s: %s, this type of driving function is not implemented ', ... + 'for a 2D point source.'],upper(mfilename),driving_functions); + end + + +elseif strcmp('2.5D',dimension) + + % === 2.5-Dimensional ================================================ + + switch driving_functions + case 'default' + % --- SFS Toolbox ------------------------------------------------ + % D_25D(kx,w) = e^(i kx xs) ... + % ____________ + % H1^(2)( \|(w/c)^2-kx^2 |yref-ys| ) + % / - --------------_-_-_-_-_-_---------, |kx|<|w/c| + % | H1^(2)( \|(w/c)^2-kx^2 yref ) + % < ____________ + % | K1( \|kx^2-(w/c)^2 |yref-ys| ) + % \ ----------_-_-_-_-_-_---------, |kx|>|w/c| + % K1( \|kx^2-(w/c)^2 yref ) + % + % https://sfs.rtfd.io/en/3.2/d_nfchoa/#equation-fd-sdm-point-25d + % + D(idxpr) = exp(1i*kx(idxpr)*xs(1)) .* ... + besselh(1,2,sqrt( (omega/c)^2 - kx(idxpr).^2 )*abs(xref(2)-xs(2))) ./ ... + besselh(1,2,sqrt( (omega/c)^2 - kx(idxpr).^2 )*abs(xref(2)-x0(2))); + if(withev) + D(idxev) = exp(1i*kx(idxev)*xs(1)) .* ... + besselk(1,sqrt(kx(idxev).^2 - (omega/c).^2)*abs(xref(2)-xs(2))) ./ ... + besselk(1,sqrt(kx(idxev).^2 - (omega/c).^2)*abs(xref(2)-x0(2))); + end + % + otherwise + error(['%s: %s, this type of driving function is not implemented ', ... + 'for a 2.5D point source.'],upper(mfilename),driving_functions); + end + + +elseif strcmp('3D',dimension) + + % === 3-Dimensional ================================================== + + switch driving_functions + case 'default' + % --- SFS Toolbox ------------------------------------------------ + to_be_implemented; + otherwise + error(['%s: %s, this type of driving function is not implemented ', ... + 'for a 3D point source.'],upper(mfilename),driving_functions); + end + +else + error('%s: the dimension %s is unknown.',upper(mfilename),dimension); +end diff --git a/SFS_monochromatic/driving_functions_mono/driving_function_mono_sdm_kx_pw.m b/SFS_monochromatic/driving_functions_mono/driving_function_mono_sdm_kx_pw.m index 820e81c8..a84d6b86 100644 --- a/SFS_monochromatic/driving_functions_mono/driving_function_mono_sdm_kx_pw.m +++ b/SFS_monochromatic/driving_functions_mono/driving_function_mono_sdm_kx_pw.m @@ -1,146 +1,130 @@ -function D = driving_function_mono_sdm_kx_pw(kx,nk,f,conf) -%DRIVING_FUNCTION_MONO_SDM_KX_PW returns the driving signal D for a plane wave in -%SDM in the kx domain -% -% Usage: D = driving_function_mono_sdm_kx_pw(kx,nk,f,[conf]) -% -% Input parameters: -% kx - kx dimension [nx1] -% nk - direction of plane wave / m [1x3] -% f - frequency of the monochromatic source / Hz -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% D - driving function signal [nx1] -% -% DRIVING_FUNCTION_MONO_SDM_KX_PW(kx,nk,f,conf) returns SDM driving signals -% for the given secondary sources, the virtual plane wave direction and the -% frequency f. The driving signal is calculated in the kx domain. -% -% References: -% H. Wierstorf, J. Ahrens, F. Winter, F. Schultz, S. Spors (2015) - -% "Theory of Sound Field Synthesis" -% J. Ahrens and S. Spors (2010) - "Sound Field Reproduction Using Planar -% and Linear Arrays of Loudspeakers", Transactions on Audio, Speech and -% Language Processing, Volume 18(8), p. 2038-2050 -% -% See also: driving_function_mono_sdm_kx, sound_field_mono_sdm_kx - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargmatrix(kx,nk); -isargpositivescalar(f); -if nargin=omega/c*nk(:,1),1,'first'); - D(idx) = 4*1i*exp(-1i*omega/c*nk(2).*xref(2)) / ... - besselh(0,2,omega/c.*nk(2).*xref(2)); - % - else - error(['%s: %s, this type of driving function is not implemented ', ... - 'for a 2.5D plane wave.'],upper(mfilename),driving_functions); - end - - -elseif strcmp('3D',dimension) - - % === 3-Dimensional ================================================== - - if strcmp('default',driving_functions) - % --- SFS Toolbox ------------------------------------------------ - to_be_implemented; - else - error(['%s: %s, this type of driving function is not implemented ', ... - 'for a 3D plane wave.'],upper(mfilename),driving_functions); - end - -else - error('%s: the dimension %s is unknown.',upper(mfilename),dimension); -end +function D = driving_function_mono_sdm_kx_pw(kx,nk,f,conf) +%DRIVING_FUNCTION_MONO_SDM_KX_PW driving signal for a plane wave in SDM in +%the kx-domain +% +% Usage: D = driving_function_mono_sdm_kx_pw(kx,nk,f,conf) +% +% Input parameters: +% kx - kx dimension [nx1] +% nk - direction of plane wave / m [1x3] +% f - frequency of the monochromatic source / Hz +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% D - driving function signal [nx1] +% +% See also: driving_function_mono_sdm_kx, sound_field_mono_sdm_kx + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 4; +nargmax = 4; +narginchk(nargmin,nargmax); +isargmatrix(kx,nk); +isargpositivescalar(f); +isargstruct(conf); + + +%% ===== Configuration ================================================== +xref = conf.xref; +c = conf.c; +dimension = conf.dimension; +driving_functions = conf.driving_functions; + + +%% ===== Computation ==================================================== +% Calculate the driving function in time-frequency domain + +% Frequency +omega = 2*pi*f; +D = zeros(1,length(kx)); + +if strcmp('2D',dimension) + + % === 2-Dimensional ================================================== + + % Ensure 2D + nk = nk(:,1:2); + + switch driving_functions + case 'default' + % --- SFS Toolbox ------------------------------------------------ + to_be_implemented; + otherwise + error(['%s: %s, this type of driving function is not implemented ', ... + 'for a 2D plane wave.'],upper(mfilename),driving_functions); + end + + +elseif strcmp('2.5D',dimension) + + % === 2.5-Dimensional ================================================ + + switch driving_functions + case 'default' + % --- SFS Toolbox ------------------------------------------------ + % D_2.5D using a plane wave as source model + % + % e^(-i w/c nky*xrefy) + % D_2.5D(x0,w) = 4i ---------------------- + % (2) /w \ + % H0 | - nky*xrefy | + % \c / + % + % https://sfs.rtfd.io/en/3.2/d_nfchoa/#equation-fd-sdm-plane-25d + % + idx = find(kx>=omega/c*nk(:,1),1,'first'); + D(idx) = 4*1i*exp(-1i*omega/c*nk(2).*xref(2)) / ... + besselh(0,2,omega/c.*nk(2).*xref(2)); + % + otherwise + error(['%s: %s, this type of driving function is not implemented ', ... + 'for a 2.5D plane wave.'],upper(mfilename),driving_functions); + end + + +elseif strcmp('3D',dimension) + + % === 3-Dimensional ================================================== + + switch driving_functions + case 'default' + % --- SFS Toolbox ------------------------------------------------ + to_be_implemented; + otherwise + error(['%s: %s, this type of driving function is not implemented ', ... + 'for a 3D plane wave.'],upper(mfilename),driving_functions); + end + +else + error('%s: the dimension %s is unknown.',upper(mfilename),dimension); +end diff --git a/SFS_monochromatic/driving_functions_mono/driving_function_mono_sdm_ls.m b/SFS_monochromatic/driving_functions_mono/driving_function_mono_sdm_ls.m index b6c149a6..c10a05ea 100644 --- a/SFS_monochromatic/driving_functions_mono/driving_function_mono_sdm_ls.m +++ b/SFS_monochromatic/driving_functions_mono/driving_function_mono_sdm_ls.m @@ -1,128 +1,120 @@ -function D = driving_function_mono_sdm_ls(x0,nk,f,conf) -%DRIVING_FUNCTION_MONO_SDM_LS returns the driving signal D for a line source in -%SDM -% -% Usage: D = driving_function_mono_sdm_ls(x0,nk,f,[conf]) -% -% Input parameters: -% x0 - position of the secondary sources / m [nx3] -% nk - position of virtual line source / m [nx3] -% f - frequency of the monochromatic source / Hz -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% D - driving function signal [nx1] -% -% DRIVING_FUNCTION_MONO_SDM_LS(x0,nk,f,conf) returns SDM driving signals -% for the given secondary sources, the virtual line source position and the -% frequency f. -% -% See also: driving_function_mono_sdm - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargmatrix(x0,nk); -isargpositivescalar(f); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargmatrix(x0,nk); -isargpositivescalar(f); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargmatrix(x0,nk); -isargpositivescalar(f); -if nargin. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 4; +nargmin = 5; nargmax = 5; narginchk(nargmin,nargmax); isargmatrix(x0,nx0,xs); isargpositivescalar(f); -if nargin>1 % % 1 i w (x0-xs) nx0 - % D(x0,w) = --- --- ------------- e^(i w/c |x0-xs|) - % 2pi c |x0-xs|^(3/2) + % D(x0,w) = --- --- ----------- e^(i w/c |x0-xs|) + % 2pi c |x0-xs|^2 % - % see Wierstorf et al. (2015), eq.(#D:wfs:fs) + % https://sfs.rtfd.io/en/3.2/d_wfs/#equation-fd-wfs-focused-3d % % r = |x0-xs| r = vector_norm(x0-xs,2); % Driving signal - D = 1/(2*pi) * 1i*omega/c .* ... - vector_product(x0-xs,nx0,2) ./ r.^(3/2) .* exp(1i*omega/c.*r); + D = 1./(2.*pi) .* (1i.*omega)./c ... + .* vector_product(x0-xs,nx0,2) ./ r.^2 ... + .* exp(+1i.*omega./c.*r); % - elseif strcmp('point_sink',driving_functions) + case 'point_sink' % D using a point sink as source model % % D(x0,w) = @@ -116,47 +125,142 @@ % --- |--- + ------- | ----------- e^(i w/c |x0-xs|) % 2pi \ c |x0-xs| / |x0-xs|^2 % - % see Wierstorf et al. (2015), eq.(#D:wfs:fs:woapprox) + % See Wierstorf (2014), eq.(2.71) % % r = |x0-xs| r = vector_norm(x0-xs,2); % Driving signal - D = 1/(2*pi) * ( -1i.*omega/c + 1./r ) .* ... - vector_product(x0-xs,nx0,2) ./ r.^2 .* exp(1i*omega./c.*r); + D = 1./(2.*pi) .* ( -1i.*omega./c + 1./r ) ... + .* vector_product(x0-xs,nx0,2) ./ r.^2 ... + .* exp(+1i.*omega./c.*r); % - elseif strcmp('line_sink',driving_functions) + case 'line_sink' % D using a line sink as source model % % iw (x0-xs)nk (1)/ w \ % D(x0,w) = - -- --------- H1 | - |x0-xs| | % 2c |x0-xs| \ c / % - % compare Wierstorf et al. (2015), eq.(#D:wfs:fs:ls) - % % r = |x0-xs| r = vector_norm(x0-xs,2); % Driving signal - D = -1i*omega/(2*c) .* vector_product(x0-xs,nx0,2) ./ r .* ... - besselh(1,1,omega/c.*r); + D = -1i.*omega./(2.*c) ... + .* vector_product(x0-xs,nx0,2) ./ r ... + .* besselh(1,1,omega./c.*r); % - elseif strcmp('delft1988',driving_functions) - % --- Delft 1988 ------------------------------------------------- - to_be_implemented; + case 'legacy' + % --- Old SFS Toolbox default ------------------------------------ + % D using an approximated point sink as source model % - else + % 1 i w (x0-xs) nx0 + % D(x0,w) = --- --- ------------- e^(i w/c |x0-xs|) + % 2pi c |x0-xs|^(3/2) + % + % See Wierstorf (2014), eq.(2.73) + % + % r = |x0-xs| + r = vector_norm(x0-xs,2); + % Driving signal + D = 1./(2.*pi) .* 1i.*omega./c ... + .* vector_product(x0-xs,nx0,2) ./ r.^(3./2) ... + .* exp(+1i.*omega./c.*r); + % + otherwise error(['%s: %s, this type of driving function is not implemented ', ... 'for a focused source.'],upper(mfilename),driving_functions); end - elseif strcmp('2.5D',dimension) % === 2.5-Dimensional ================================================ - + % Reference point xref = repmat(xref,[size(x0,1) 1]); - if strcmp('default',driving_functions) - % --- SFS Toolbox ------------------------------------------------ + + switch driving_functions + case {'default', 'reference_circle'} + % Driving function with two stationary phase approximations, + % reference to circle around the focused source with radius |xref-xs| + % + % r = |x0-xs| + r = vector_norm(x0-xs,2); + % + % 2.5D correction factor + % _____________ + % | r + % g0 = _ |1 + --------- + % \| |xref-xs| + % + g0 = sqrt( 1 + r./vector_norm(xref-xs,2) ); + % ___ ___ + % | 1 |-iw (xs-x0) nx0 + % D_2.5D(x0,w) = g0 _ |--- _ |--- ------------- e^(i w/c |x0-xs|) + % \|2pi \| c |x0-xs|^(3/2) + % + % https://sfs.rtfd.io/en/3.2/d_wfs/#equation-fd-wfs-focused-25d + % + % Driving signal + D = 1./sqrt(2.*pi) .* sqrt(-1i.*omega./c) .* g0 ... + .* vector_product(xs-x0,nx0,2) ./ r.^(3./2) ... + .* exp(+1i.*omega./c.*r); + % + case 'reference_point' + % Driving function with only one stationary phase approximation, + % reference to one point in field + % + % r = |x0-xs| + r = vector_norm(x0-xs,2); + % 2.5D correction factor + % _____________________ + % | |xref-x0| + % g0 = _ |--------------------- + % \|||xref-x0| - |xs-x0|| + % + % Verheijen (1997), eq. (A.14) + % + g0 = sqrt( vector_norm(xref-x0,2) ./ abs(vector_norm(x0-xref,2) - r) ); + % ___ ___ + % | 1 |-iw (xs-x0) nx0 + % D_2.5D(x0,w) = g0 _ |--- _ |--- ------------- e^(i w/c |x0-xs|) + % \|2pi \| c |x0-xs|^(3/2) + % + % Driving signal + D = 1./sqrt(2.*pi) .* sqrt(-1i.*omega./c) .* g0 ... + .* vector_product(xs-x0,nx0,2) ./ r.^(3./2) ... + .* exp(+1i.*omega./c.*r); + % + case {'reference_line', 'delft1988'} + % Driving function with two stationary phase approximations, + % reference to a line parallel to a LINEAR secondary source distribution + % + % Distance ref-line to linear ssd + dref = abs( vector_product(xref-x0,nx0,2) ); + % Distance source and linear ssd + ds = abs( vector_product(xs-x0,nx0,2) ); + % + % 2.5D correction factor + % ______________________ + % g0 = \| d_ref / (d_ref - d_s) + % + % See Start (1997), eq. (3.16) + % + g0 = sqrt( dref ./ (dref - ds) ); + % ___ ___ + % | 1 |-iw (xs-x0) nx0 + % D_2.5D(x0,w) = g0 _ |--- _ |--- ------------- e^(i w/c |x0-xs|) + % \|2pi \| c |x0-xs|^(3/2) + % + % See Verheijen (1997), eq. (2.29b) + % + % r = |x0-xs| + r = vector_norm(x0-xs,2); + % Driving signal + D = 1./sqrt(2.*pi) .* sqrt(-1i.*omega./c) .* g0 ... + .* vector_product(xs-x0,nx0,2) ./ r.^(3./2) ... + .* exp(+1i.*omega./c.*r); + % + case 'legacy' + % --- Old SFS Toolbox default ------------------------------------ % 2.5D correction factor % ______________ % g0 = \| 2pi |xref-x0| @@ -165,19 +269,20 @@ % % D_2.5D using an approximated point sink as source model % ___ - % g0 |i w (x0-xs) nx0 + % g0 |iw (x0-xs) nx0 % D_2.5D(x0,w) = --- _ |--- ------------- e^(i w/c |x0-xs|) % 2pi \| c |x0-xs|^(3/2) % - % see Wierstorf et al. (2015), eq.(#D:wfs:fs:2.5D) + % See Wierstorf (2014), eq.(2.74) % % r = |x0-xs| r = vector_norm(x0-xs,2); % Driving signal - D = g0/(2*pi) * sqrt( 1i*omega/c ) .* ... - vector_product(x0-xs,nx0,2) ./ r.^(3/2) .* exp(1i*omega/c.*r); + D = 1./(2.*pi) .* sqrt(1i.*omega./c) .* g0 ... + .* vector_product(x0-xs,nx0,2) ./ r.^(3./2) ... + .* exp(+1i*omega./c.*r); % - elseif strcmp('spors2009eq7',driving_functions) + case 'spors2009eq7' % --- SFS Toolbox ------------------------------------------------ % 2.5D correction factor % ______________ @@ -194,15 +299,16 @@ % D_2.5D(x0,w) = -g0 _ |------ ------------- e^(i w/c |x0-xs|) % \|2pi ic |x0-xs|^(3/2) % - % see Spors (2009), eq.(7) + % See Spors et al. (2009), eq.(7) % % r = |x0-xs| r = vector_norm(x0-xs,2); % Driving signal - D = -g0 * sqrt( omega/(2*pi*c*1i) ) .* ... - vector_product(x0-xs,nx0,2) ./ r.^(3/2) .* exp(1i*omega/c.*r); + D = -g0 .* sqrt( omega./(2.*pi.*c.*1i) ) ... + .* vector_product(x0-xs,nx0,2) ./ r.^(3./2) ... + .* exp(+1i*omega./c.*r); % - elseif strcmp('spors2009eq6',driving_functions) + case 'spors2009eq6' % --- Spors 2009 ------------------------------------------------- % 2.5D correction factor % ______________ @@ -217,15 +323,16 @@ % D_2.5D(x0,w) = -g0 -- ----------- H1 | - |x0-xs| | % 2c |x0-xs| \ c / % - % see Spors et al. (2009), eq.(6) + % See Spors et al. (2009), eq.(6) % % r = |x0-xs| r = vector_norm(x0-xs,2); % Driving signal - D = -g0 * 1i*omega/(2*c) .* ... - vector_product(x0-xs,nx0,2) ./ r .* besselh(1,1,omega/c.*r); + D = -g0 .* 1i.*omega./(2.*c) ... + .* vector_product(x0-xs,nx0,2) ./ r ... + .* besselh(1,1,omega./c.*r); % - elseif strcmp('point_sink',driving_functions) + case 'point_sink' % --- Point Sink ------------------------------------------------- % 2.5D correction factor % ______________ @@ -241,23 +348,19 @@ % --- | _ |--- + _ |--- ------- | ----------- e^(i w/c |x0-xs|) % 2pi \ \| c \|i w |x0-xs| / |x0-xs|^2 % - % see Wierstorf et al. (2015), eq.(#D:wfs:fs:woapprox:2.5D) + % See ... % % r = |x0-xs| r = vector_norm(x0-xs,2); % Driving signal - D = g0/(2*pi) .* ( sqrt(1i*omega/c) + sqrt(c/(1i*omega)) ./ r ) .* ... - vector_product(x0-xs,nx0,2) ./ r.^2 .* exp(1i*omega/c.*r); - % - elseif strcmp('delft1988',driving_functions) - % --- Delft 1988 ------------------------------------------------- - to_be_implemented; + D = g0./(2.*pi) .* (sqrt(1i.*omega./c) + sqrt(c./(1i.*omega)) ./ r) ... + .* vector_product(x0-xs,nx0,2) ./ r.^2 ... + .* exp(+1i*omega./c.*r); % - else + otherwise error(['%s: %s, this type of driving function is not implemented ', ... 'for a 2.5D focused source.'],upper(mfilename),driving_functions); end - else error('%s: the dimension %s is unknown.',upper(mfilename),dimension); end diff --git a/SFS_monochromatic/driving_functions_mono/driving_function_mono_wfs_ls.m b/SFS_monochromatic/driving_functions_mono/driving_function_mono_wfs_ls.m index e23ff106..540e0b0f 100644 --- a/SFS_monochromatic/driving_functions_mono/driving_function_mono_wfs_ls.m +++ b/SFS_monochromatic/driving_functions_mono/driving_function_mono_wfs_ls.m @@ -1,156 +1,173 @@ -function D = driving_function_mono_wfs_ls(x0,nx0,xs,f,conf) -%DRIVING_FUNCTION_MONO_WFS_LS returns the driving signal D for a line source in -%WFS -% -% Usage: D = driving_function_mono_wfs_ls(x0,nx0,xs,f,[conf]) -% -% Input parameters: -% x0 - position of the secondary sources / m [nx3] -% nx0 - directions of the secondary sources / m [nx3] -% xs - position of virtual line source / m [nx3] -% f - frequency of the monochromatic source / Hz -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% D - driving function signal [nx1] -% -% DRIVING_FUNCTION_MONO_WFS_LS(x0,xs,f,src,conf) returns WFS driving signals -% for the given secondary sources, the virtual line source position and the -% frequency f. -% -% References: -% H. Wierstorf, J. Ahrens, F. Winter, F. Schultz, S. Spors (2015) - -% "Theory of Sound Field Synthesis" -% -% See also: driving_function_mono_wfs, driving_function_imp_wfs_ps - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 4; -nargmax = 5; -narginchk(nargmin,nargmax); -isargmatrix(x0,nx0,xs); -isargpositivescalar(f); -if nargin nxs, + % and |nxs| = 1. + % + % https://sfs.rtfd.io/en/3.2/d_wfs/#equation-fd-wfs-line + % + % v = (I - nxs'nxs)(x0-xs) + % r = |v| + nxs = nxs(1,:); + v = (x0 - xs)*(eye(3) - nxs'*nxs); + r = vector_norm(v,2); + % Driving signal + D = -1i*omega/(2*c) .* vector_product(v,nx0,2) ./ r .* ... + besselh(1,2,omega/c.*r); + % + otherwise + error(['%s: %s, this type of driving function is not implemented ', ... + 'for a line source.'],upper(mfilename),driving_functions); + end + +else + error('%s: the dimension %s is unknown.',upper(mfilename),dimension); +end diff --git a/SFS_monochromatic/driving_functions_mono/driving_function_mono_wfs_ps.m b/SFS_monochromatic/driving_functions_mono/driving_function_mono_wfs_ps.m index 39f5fe30..b7a7ce9f 100644 --- a/SFS_monochromatic/driving_functions_mono/driving_function_mono_wfs_ps.m +++ b/SFS_monochromatic/driving_functions_mono/driving_function_mono_wfs_ps.m @@ -1,84 +1,70 @@ function D = driving_function_mono_wfs_ps(x0,nx0,xs,f,conf) -%DRIVING_FUNCTION_MONO_WFS_PS returns the driving signal D for a point source in -%WFS +%DRIVING_FUNCTION_MONO_WFS_PS driving signal for a point source in WFS % -% Usage: D = driving_function_mono_wfs_ps(x0,nx0,xs,f,[conf]) +% Usage: D = driving_function_mono_wfs_ps(x0,nx0,xs,f,conf) % % Input parameters: % x0 - position of the secondary sources / m [nx3] % nx0 - directions of the secondary sources / m [nx3] % xs - position of virtual point source / m [nx3] % f - frequency of the monochromatic source / Hz -% conf - optional configuration struct (see SFS_config) +% conf - configuration struct (see SFS_config) % % Output parameters: % D - driving function signal [nx1] % -% DRIVING_FUNCTION_MONO_WFS_PS(x0,xs,f,src,conf) returns WFS driving signals -% for the given secondary sources, the virtual point source position and the -% frequency f. +% See also: driving_function_mono_wfs, driving_function_imp_wfs_ps % % References: -% H. Wierstorf, J. Ahrens, F. Winter, F. Schultz, S. Spors (2015) - -% "Theory of Sound Field Synthesis" -% S. Spors, R. Rabenstein, J. Ahrens (2008) - "The Theory of Wave Field -% Synthesis Revisited", AES124 -% E. Verheijen (1997) - "Sound Reproduction by Wave Field Synthesis", PhD -% thesis, TU Delft -% D. Opperschall (2002) - "Realisierung eines Demonstrators für -% Punktquellen und ebene Wellen für ein Wellenfeldsynthese-System", -% Master thesis, Universität Erlangen-Nürnberg -% F. Völk (2010) - "Psychoakustische Experimente zur Distanz mittels -% Wellenfeldsynthese erzeugter Hörereignisse", DAGA, p.1065-66 -% S. Spors, J. Ahrens (2010) - "Analysis and Improvement of -% Pre-equalization in 2.5-Dimensional Wave Field Synthesis", AES128 +% Spors and Ahrens (2010) - "Analysis and Improvement of Pre-equalization +% in 2.5-Dimensional Wave Field Synthesis", 128th Convention of the Audio +% Engineering Society, Paper 8121, +% http://www.aes.org/e-lib/browse.cfm?elib=15418 % -% See also: driving_function_mono_wfs, driving_function_imp_wfs_ps +% Spors, Rabenstein, Ahrens (2008) - "The Theory of Wave Field Synthesis +% Revisited", 124th Convention of the Audio Engineering Society, Paper +% 7358, http://www.aes.org/e-lib/browse.cfm?elib=14488 +% +% Wierstorf (2014) - "Perceptual Assessment of Sound Field Synthesis", +% PhD thesis, TU Berlin, https://doi.org/10.14279/depositonce-4310 %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 4; +nargmin = 5; nargmax = 5; narginchk(nargmin,nargmax); isargmatrix(x0,nx0,xs); isargpositivescalar(f); -if nargin>1 % - % 1 i w (x0-xs) nx0 - % D(x0,w) = --- --- ------------- e^(-i w/c |x0-xs|) - % 2pi c |x0-xs|^(3/2) + % 1 i w (x0-xs) nx0 + % D(x0,w) = --- --- ----------- e^(-i w/c |x0-xs|) + % 2pi c |x0-xs|^2 % - % see Wierstorf et al. (2015), eq.(#D:wfs:ps) + % https://sfs.rtfd.io/en/3.2/d_wfs/#equation-fd-wfs-point % % r = |x0-xs| r = vector_norm(x0-xs,2); % Driving signal - D = 1/(2*pi) .* (1i*omega)/c .* ... - vector_product(x0-xs,nx0,2) ./ r.^(3/2) .* exp(-1i*omega/c.*r); + D = 1./(2.*pi) .* (1i.*omega)./c ... + .* vector_product(x0-xs,nx0,2) ./ r.^2 ... + .* exp(-1i.*omega./c.*r); % - elseif strcmp('point_source',driving_functions) + case 'point_source' % D using a point source as source model % % 1 / i w 1 \ (x0-xs) nx0 % D(x0,w) = --- | --- - ------- | ----------- e^(-i w/c |x0-xs|) % 2pi \ c |x0-xs| / |x0-xs|^2 % - % see Wierstorf et al. (2015), eq.(#D:wfs:ps:woapprox) + % https://sfs.rtfd.io/en/3.2/d_wfs/#equation-fd-wfs-point-woapprox % % r = |x0-xs| r = vector_norm(x0-xs,2); % Driving signal - D = 1/(2*pi) .* ( (1i*omega)/c - 1./r ) .* ... - vector_product(x0-xs,nx0,2) ./ r.^2 .* exp(-1i*omega/c.*r); + D = 1./(2.*pi) .* ( (1i.*omega)./c - 1./r ) ... + .* vector_product(x0-xs,nx0,2) ./ r.^2 ... + .* exp(-1i.*omega./c.*r); % - elseif strcmp('line_source',driving_functions) + case 'line_source' % D using a line source as source model (truly 2D model) % % 1 i w (x0-xs) nx0 (2)/ w \ % D(x0,x) = - -- --- ----------- H1 | - |x0-xs| | % 2c c |x0-xs| \ c / % - % see Spors et al. (2008), eq.(23) + % See Spors et al. (2008), eq.(23) % % r = |x0-xs| r = vector_norm(x0-xs,2); % Driving signal - D = -1/(2*c) .* 1i*omega/c * vector_product(x0-xs,nx0,2) ./ r .* besselh(1,2,omega/c*r); + D = -1./(2.*c) .* 1i.*omega./c ... + .* vector_product(x0-xs,nx0,2) ./ r ... + .* besselh(1,2,omega./c.*r); + % + case 'legacy' + % --- Old SFS Toolbox default ------------------------------------ + % D using a point sink and large distance approximation % + % 1 i w (x0-xs) nx0 + % D(x0,w) = --- --- ------------- e^(-i w/c |x0-xs|) + % 2pi c |x0-xs|^(3/2) % - elseif strcmp('delft1988',driving_functions) - % --- Delft 1988 ------------------------------------------------- - to_be_implemented; + % See Wierstorf (2014), eq.(2.61) + % + % r = |x0-xs| + r = vector_norm(x0-xs,2); + % Driving signal + D = 1./(2.*pi) .* (1i.*omega)./c ... + .* vector_product(x0-xs,nx0,2) ./ r.^(3./2) ... + .* exp(-1i.*omega./c.*r); % - else + otherwise error(['%s: %s, this type of driving function is not implemented ', ... 'for a point source.'],upper(mfilename),driving_functions); end @@ -161,118 +164,114 @@ % Reference point xref = repmat(xref,[size(x0,1) 1]); - if strcmp('default',driving_functions) - % --- SFS Toolbox ------------------------------------------------ - % 2.5D correction factor - % _____________ - % g0 = \| 2pi |xref-x0| - % - g0 = sqrt(2*pi*vector_norm(xref-x0,2)); - % - % D_2.5D using a point source and large distance approximation - % ___ - % g0 |i w (x0-xs) nx0 - % D_2.5D(x0,w) = --- _ |--- ------------- e^(-i w/c |x0-xs|) - % 2pi \| c |x0-xs|^(3/2) - % - % see Wierstorf et al. (2015), eq.(#D:wfs:ps:2.5D) + + switch driving_functions + case {'default', 'reference_point', 'opperschall', 'volk2010'} + % Driving function with only one stationary phase approximation, + % reference to one point in field % % r = |x0-xs| r = vector_norm(x0-xs,2); - % Driving signal - D = g0/(2*pi) .* sqrt(1i*omega/c) .* ... - vector_product(x0-xs,nx0,2) ./ r.^(3/2) .* exp(-1i*omega/c.*r); - % - elseif strcmp('point_source',driving_functions) % 2.5D correction factor - % ______________ - % g0 = \| 2pi |xref-x0| + % _____________________ + % | |xref-x0| + % g0 = _ |--------------------- + % \| |xref-x0| + |x0-xs| % - g0 = sqrt(2*pi*vector_norm(xref-x0,2)); - % - % D_2.5D using a point source as source model + g0 = sqrt( vector_norm(xref-x0,2) ./ (vector_norm(xref-x0,2) + r) ); % % D_2.5D(x0,w) = - % ___ ___ - % g0 / |i w | c 1 \ (x0-xs) nx0 - % --- | _ |--- - _ |--- ------- | ----------- e^(-i w/c |x0-xs|) - % 2pi \ \| c \|i w |x0-xs| / |x0-xs|^2 + % ___ ___ + % | 1 |i w (x0-xs) nx0 + % g0 _ |--- _ |--- ------------- e^(-i w/c |x0-xs|) + % \|2pi \| c |x0-xs|^(3/2) % - % see Wierstorf et al. (2015), eq.(#D:wfs:ps:woapprox:2.5D) + % https://sfs.rtfd.io/en/3.2/d_wfs/#equation-fd-wfs-point-25d % - % r = |x0-xs| - r = vector_norm(x0-xs,2); % Driving signal - D = g0/(2*pi) .* ( sqrt(1i*omega/c) - sqrt(c/(1i*omega) ./ r ) ) .* ... - vector_product(x0-xs,nx0,2) ./ r.^2 .* exp(-1i*omega/c .* r); + D = 1./sqrt(2*pi) .* sqrt(1i.*omega./c) .* g0 ... + .* vector_product(x0-xs,nx0,2) ./ r.^(3./2) ... + .* exp(-1i.*omega./c.*r); % - elseif strcmp('delft1988',driving_functions) - % --- Delft 1988 ------------------------------------------------- - % D_2.5 using a point source as source model (after Delft) + case {'reference_line', 'delft1988'} + % Driving function with two stationary phase approximations, + % reference to a line parallel to a LINEAR secondary source distribution + % + % Distance ref-line to linear ssd + dref = abs( vector_product(xref-x0,nx0,2) ); + % Distance source and linear ssd + ds = abs( vector_product(xs-x0,nx0,2) ); % % 2.5D correction factor % _______________________ - % g0 = \| -y_ref / (y_s - y_ref) + % g0 = \| d_ref / (d_ref + d_s) % - g0 = sqrt(- xref(1,2) / (xs(1,2) - xref(1,2))); - % _____ - % |i w (x0-xs) nx0 - % D_2.5D(x0,w) = g0 _ |----- ------------ e^(-i w/c |x0-xs|) - % \|2pi c |x0-xs|^(3/2) + g0 = sqrt( dref ./ (dref + ds) ); + % + % D_2.5D(x0,w) = + % ___ ___ + % | 1 |i w (x0-xs) nx0 + % g0 _ |--- _ |--- ------------- e^(-i w/c |x0-xs|) + % \|2pi \| c |x0-xs|^(3/2) % - % see Verheijen (1997), p.41 eq.(2.27) + % https://sfs.rtfd.io/en/3.2/d_wfs/#equation-fd-wfs-point-25d-refline % % r = |x0-xs| r = vector_norm(x0-xs,2); % Driving signal - D = sqrt(1i*omega/(2*pi*c)) * g0 * vector_product(x0-xs,nx0,2) ./ r.^(3/2) .* exp(-1i*omega/c .* r); - % - elseif strcmp('opperschall',driving_functions) - % --- Opperschall ------------------------------------------------- - % Driving function with only one stationary phase - % approximation, reference to one point in field + D = 1./sqrt(2*pi) .* sqrt(1i.*omega./c) .* g0 ... + .* vector_product(x0-xs,nx0,2) ./ r.^(3./2) ... + .* exp(-1i.*omega./c.*r); % + case 'legacy' + % --- Old SFS Toolbox default ------------------------------------ % 2.5D correction factor - % _____________________ - % | |xref-x0| - % g0 = _ |--------------------- - % \| |x0-xs| + |xref-x0| + % _____________ + % g0 = \| 2pi |xref-x0| % - g0 = sqrt( vector_norm(x0-xref,2) ./ (vector_norm(xs-x0,2) + vector_norm(x0-xref,2)) ); - % ______ - % | i w (x0-xs) nx0 - % D_2.5D(x0,w) = g0 _ |------ ------------- e^(-i w/c |x0-xs|) - % \|2pi c |x0-xs|^(3/2) + g0 = sqrt(2*pi*vector_norm(xref-x0,2)); % - % see Opperschall (2002), p.14 eq.(3.1), eq.(3.14), eq.(3.15) + % D_2.5D using a point source and large distance approximation + % ___ + % g0 |i w (x0-xs) nx0 + % D_2.5D(x0,w) = --- _ |--- ------------- e^(-i w/c |x0-xs|) + % 2pi \| c |x0-xs|^(3/2) + % + % See Wierstorf (2014), eq.(2.62) % % r = |x0-xs| r = vector_norm(x0-xs,2); % Driving signal - D = sqrt(1i*omega/(2*pi*c)) * g0 .* vector_product(x0-xs,nx0,2) ./ r.^(3/2) .* exp(-1i*omega/c .* r); + D = g0./(2.*pi) .* sqrt(1i.*omega./c) ... + .* vector_product(x0-xs,nx0,2) ./ r.^(3./2) ... + .* exp(-1i.*omega./c.*r); % - elseif strcmp('volk2010',driving_functions) - % --- Voelk 2010 -------------------------------------------------- - % _____________________ - % | |xref-x0| - % g0 = _ |--------------------- - % \| |x0-xs| + |xref-x0| + case 'point_source' + % --- Wierstorf 2014, without approximation ---------------------- + % 2.5D correction factor + % ______________ + % g0 = \| 2pi |xref-x0| % - g0 = sqrt( vector_norm(xref-x0,2) ./ (vector_norm(xs-x0,2) + vector_norm(x0-xref,2)) ); + g0 = sqrt(2*pi*vector_norm(xref-x0,2)); + % + % D_2.5D using a point source as source model % % D_2.5D(x0,w) = - % ___ ___ - % | 1 |i w (x0-xs) nx0 - % g0 _ |--- _ |--- ------------- e^(-i w/c |x0-xs|) - % \|2pi \| c |x0-xs|^(3/2) + % ___ ___ + % g0 / |i w | c 1 \ (x0-xs) nx0 + % --- | _ |--- - _ |--- ------- | ----------- e^(-i w/c |x0-xs|) + % 2pi \ \| c \|i w |x0-xs| / |x0-xs|^2 % - % see Völk (2010), eq.(3) + % See Wierstorf (2014), eq.(2.60) % + % r = |x0-xs| r = vector_norm(x0-xs,2); - D = g0/sqrt(2*pi) * sqrt(1i*omega/c) * ... - vector_product(x0-xs,nx0,2)./r.^(3/2) .* exp(-1i*omega/c.*r); + % Driving signal + D = g0./(2.*pi) .* ( sqrt(1i.*omega./c) - sqrt(c./(1i.*omega) ./ r ) ) ... + .* vector_product(x0-xs,nx0,2) ./ r.^2 ... + .* exp(-1i.*omega./c .* r); % - elseif strcmp('SDMapprox',driving_functions) + case 'SDMapprox' % --- Spors 2010 -------------------------------------------------- % Driving function derived by approximation of the SDM % @@ -286,12 +285,14 @@ % D_2.5D(x0,w) = - --- g0 ------- H1 | -|x0-xs| | % 2 c |x0-xs| \c / % - % see Spors and Ahrens (2010), eq.(24) + % See Spors and Ahrens (2010), eq.(24) % r = vector_norm(x0-xs,2); - D = 1/2 * 1i*omega/c * g0 * xs(1,2)./r .* besselh(1,2,omega/c*r); + D = 1./2 .* 1i.*omega./c .* g0 ... + .* xs(1,2)./r ... + .* besselh(1,2,omega./c.*r); % - else + otherwise error(['%s: %s, this type of driving function is not implemented ', ... 'for a 2.5D point source.'],upper(mfilename),driving_functions); end diff --git a/SFS_monochromatic/driving_functions_mono/driving_function_mono_wfs_pw.m b/SFS_monochromatic/driving_functions_mono/driving_function_mono_wfs_pw.m index 9b76cbf4..896ae1a5 100644 --- a/SFS_monochromatic/driving_functions_mono/driving_function_mono_wfs_pw.m +++ b/SFS_monochromatic/driving_functions_mono/driving_function_mono_wfs_pw.m @@ -1,150 +1,157 @@ -function D = driving_function_mono_wfs_pw(x0,nx0,nk,f,conf) -%DRIVING_FUNCTION_MONO_WFS_PW returns the driving signal D for a plane wave in -%WFS -% -% Usage: D = driving_function_mono_wfs_pw(x0,nx0,nk,f,[conf]) -% -% Input parameters: -% x0 - position of the secondary sources / m [nx3] -% nx0 - directions of the secondary sources / m [nx3] -% nk - direction of plane wave / m [nx3] -% f - frequency of the monochromatic source / Hz -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% D - driving function signal [nx1] -% -% DRIVING_FUNCTION_MONO_WFS_PW(x0,nx0,nk,f,conf) returns WFS driving signals -% for the given secondary sources, the virtual plane wave direction and the -% frequency f. -% -% References: -% H. Wierstorf, J. Ahrens, F. Winter, F. Schultz, S. Spors (2015) - -% "Theory of Sound Field Synthesis" -% -% See also: driving_function_mono_wfs, driving_function_imp_wfs_ps - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 4; -nargmax = 5; -narginchk(nargmin,nargmax); -isargmatrix(x0,nx0,nk); -isargpositivescalar(f); -if nargin. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 4; -nargmax = 5; +nargmin = 6; +nargmax = 6; narginchk(nargmin,nargmax); isargvector(Dv); isargpositivescalar(f); +isargchar(srcv); isargsecondarysource(x0,xv); -if nargin. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== % Disabled checking for performance reasons -nargmax = 7; -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 7; -nargmax = 8; -narginchk(nargmin,nargmax); -isargvector(X,Y,Z); -isargxs(xs); -isargpositivescalar(f); -isargchar(src,outfile); -if nargin. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 7; +nargmin = 8; nargmax = 8; narginchk(nargmin,nargmax); -isargvector(X,Y,Z,D); +isargnumeric(X,Y,Z); +isargvector(D); isargsecondarysource(x0); isargpositivescalar(f); isargchar(src); -if nargin0, varargout{1}=P; end -if nargout>1, varargout{2}=x; end -if nargout>2, varargout{3}=y; end -if nargout>3, varargout{4}=z; end +if nargout>1, varargout{2}=xx; end +if nargout>2, varargout{3}=yy; end +if nargout>3, varargout{4}=zz; end % ===== Plotting ========================================================= -if nargout==0 || useplot - plot_sound_field(P,x,y,z,x0,conf); +if (nargout==0 || useplot) + plot_sound_field(P,X,Y,Z,x0,conf); end diff --git a/SFS_monochromatic/sound_field_mono_line_source.m b/SFS_monochromatic/sound_field_mono_line_source.m index 6a089df4..a49c6a34 100644 --- a/SFS_monochromatic/sound_field_mono_line_source.m +++ b/SFS_monochromatic/sound_field_mono_line_source.m @@ -1,67 +1,68 @@ -function varargout = sound_field_mono_line_source(X,Y,Z,xs,varargin) -%SOUND_FIELD_MONO_LINE_SOURCE simulates a sound field for a line source -% -% Usage: [P,x,y,z] = sound_field_mono_line_source(X,Y,Z,xs,f,[conf]) -% -% Input parameters: -% X - x-axis / m; single value or [xmin,xmax] -% Y - y-axis / m; single value or [ymin,ymax] -% Z - z-axis / m; single value or [zmin,zmax] -% xs - position of line source / m -% f - monochromatic frequency / Hz -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% P - Simulated sound field -% x - corresponding x axis / m -% y - corresponding y axis / m -% z - corresponding z axis / m -% -% SOUND_FIELD_MONO_LINE_SOURCE(X,Y,Z,xs,f,conf) simulates a sound -% field of a line source positioned at xs. -% To plot the result use plot_sound_field(P,x,y,z). -% -% See also: sound_field_mono, plot_sound_field, sound_field_imp_point_source - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 5; -nargmax = 6; -narginchk(nargmin,nargmax); -isargxs(xs); - - -%% ===== Computation ==================================================== -[varargout{1:nargout}] = sound_field_mono(X,Y,Z,[xs 0 -1 0 1],'ls',1,varargin{:}); +function varargout = sound_field_mono_line_source(X,Y,Z,xs,f,conf) +%SOUND_FIELD_MONO_LINE_SOURCE sound field for a line source +% +% Usage: [P,x,y,z] = sound_field_mono_line_source(X,Y,Z,xs,f,conf) +% +% Input parameters: +% X - x-axis / m; single value or [xmin,xmax] or nD-array +% Y - y-axis / m; single value or [ymin,ymax] or nD-array +% Z - z-axis / m; single value or [zmin,zmax] or nD-array +% xs - position of line source / m +% f - monochromatic frequency / Hz +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% P - Simulated sound field +% x - corresponding x values / m +% y - corresponding y values / m +% z - corresponding z values / m +% +% SOUND_FIELD_MONO_LINE_SOURCE(X,Y,Z,xs,f,conf) simulates a monochromatic +% sound field of a line source positioned at xs. +% +% To plot the result use: +% plot_sound_field(P,X,Y,Z,conf); +% or simple call the function without output argument: +% sound_field_mono_line_source(X,Y,Z,xs,f,conf) +% +% See also: sound_field_mono, plot_sound_field, sound_field_imp_point_source + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 6; +nargmax = 6; +narginchk(nargmin,nargmax); +isargxs(xs); + + +%% ===== Computation ==================================================== +[varargout{1:nargout}] = sound_field_mono(X,Y,Z,[xs 0 -1 0 1],'ls',1,f,conf); diff --git a/SFS_monochromatic/sound_field_mono_localwfs.m b/SFS_monochromatic/sound_field_mono_localwfs.m deleted file mode 100644 index 53ada7d3..00000000 --- a/SFS_monochromatic/sound_field_mono_localwfs.m +++ /dev/null @@ -1,112 +0,0 @@ -function varargout = sound_field_mono_localwfs(X,Y,Z,xs,src,f,conf) -%SOUND_FIELD_MONO_LOCALWFS simulates a sound field for local WFS -% -% Usage: [P,x,y,z,x0] = sound_field_mono_localwfs(X,Y,Z,xs,src,f,[conf]) -% -% Input parameters: -% X - x-axis / m; single value or [xmin,xmax] -% Y - y-axis / m; single value or [ymin,ymax] -% Z - z-axis / m; single value or [zmin,zmax] -% xs - position of virtual source / m -% src - source type of the virtual source -% 'pw' - plane wave (xs is the direction of the -% plane wave in this case) -% 'ps' - point source -% 'fs' - focused source -% f - monochromatic frequency / Hz -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% P - simulated sound field -% x - corresponding x axis / m -% y - corresponding y axis / m -% z - corresponding z axis / m -% x0 - active secondary sources / m -% -% SOUND_FIELD_MONO_WFS(X,Y,Z,xs,src,f,conf) simulates a sound field for the -% given source type (src) using WFS driving functions in the temporal domain. -% This means by calculating the integral for P with a summation. -% To plot the result use plot_sound_field(P,x,y,z,x0,win). -% -% See also: plot_sound_field, sound_field_imp_wfs, driving_function_mono_wfs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 6; -nargmax = 7; -narginchk(nargmin,nargmax); -isargvector(X,Y,Z); -isargxs(xs); -isargpositivescalar(f); -isargchar(src); -if nargin=5, varargout{5}=x0; end -if nargout==6, varargout{6}=xv; end - - -% ===== Plotting ======================================================== -% Add the virtual loudspeaker positions -if (nargout==0 || useplot) && loudspeakers - hold on; - tmp = conf.plot.realloudspeakers; % cache option for loudspeaker plotting - conf.plot.realloudspeakers = false; - draw_loudspeakers(xv,[1 1 0],conf); - conf.plot.realloudspeakers = tmp; - hold off; -end diff --git a/SFS_monochromatic/sound_field_mono_localwfs_sbl.m b/SFS_monochromatic/sound_field_mono_localwfs_sbl.m new file mode 100644 index 00000000..91b90fda --- /dev/null +++ b/SFS_monochromatic/sound_field_mono_localwfs_sbl.m @@ -0,0 +1,98 @@ +function varargout = sound_field_mono_localwfs_sbl(X,Y,Z,xs,src,f,conf) +%SOUND_FIELD_MONO_LOCALWFS_SBL sound field of local WFS using spatial bandwith +%limitation +% +% Usage: [P,x,y,z,x0] = sound_field_mono_localwfs_sbl(X,Y,Z,xs,src,f,conf) +% +% Input options: +% X - x-axis / m; single value or [xmin,xmax] or nD-array +% Y - y-axis / m; single value or [ymin,ymax] or nD-array +% Z - z-axis / m; single value or [zmin,zmax] or nD-array +% xs - position of point source or direction of plane +% wave / m [1x3] +% src - source type of the virtual source +% 'pw' - plane wave +% 'ps' - point source +% f - frequency of the monochromatic source / Hz +% conf - configuration struct (see SFS_config) +% +% Output options: +% P - simulated sound field +% x - corresponding x values / m +% y - corresponding y values / m +% z - corresponding z values / m +% x0 - secondary sources / m +% +% SOUND_FIELD_MONO_LOCALWFS_SBL(X,Y,Z,xs,src,f,conf) simulates a monochromatic +% sound field of the given source type (src) synthesized with local wave field +% synthesis using spatial bandwidth limitation for the frequency f. +% +% To plot the result use: +% plot_sound_field(P,X,Y,Z,x0,conf); +% or simple call the function without output argument: +% sound_field_mono_localwfs_sbl(X,Y,Z,xs,src,f,conf) +% For plotting you may also consider to display the result in dB, by setting +% the following configuration option before: +% conf.plot.usedB = true; +% +% See also: plot_sound_field, driving_function_mono_localwfs_sbl + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 7; +nargmax = 7; +narginchk(nargmin,nargmax); +isargnumeric(X,Y,Z); +isargxs(xs); +isargchar(src); +isargscalar(f); +isargstruct(conf); + + +%% ===== Configuration ================================================== +if strcmp('2D',conf.dimension) + greens_function = 'ls'; +else + greens_function = 'ps'; +end + + +%% ===== Computation ===================================================== +% Get secondary sources +x0 = secondary_source_positions(conf); +% Get driving signals +D = driving_function_mono_localwfs_sbl(x0,xs,src,f,conf); +% Calculate sound field +[varargout{1:min(nargout,4)}] = ... + sound_field_mono(X,Y,Z,x0,greens_function,D,f,conf); +% Return secondary sources if desired +if nargout==5, varargout{5}=x0; end diff --git a/SFS_monochromatic/sound_field_mono_localwfs_vss.m b/SFS_monochromatic/sound_field_mono_localwfs_vss.m new file mode 100644 index 00000000..be619209 --- /dev/null +++ b/SFS_monochromatic/sound_field_mono_localwfs_vss.m @@ -0,0 +1,111 @@ +function varargout = sound_field_mono_localwfs_vss(X,Y,Z,xs,src,f,conf) +%SOUND_FIELD_MONO_LOCALWFS_VSS sound field of local WFS using virtual secondary +%sources +% +% Usage: [P,x,y,z,x0] = sound_field_mono_localwfs_vss(X,Y,Z,xs,src,f,conf) +% +% Input parameters: +% X - x-axis / m; single value or [xmin,xmax] or nD-array +% Y - y-axis / m; single value or [ymin,ymax] or nD-array +% Z - z-axis / m; single value or [zmin,zmax] or nD-array +% xs - position of virtual source or direction of plane +% wave / m [1x3] +% src - source type of the virtual source +% 'pw' - plane wave +% 'ps' - point source +% 'fs' - focused source +% f - monochromatic frequency / Hz +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% P - simulated sound field +% x - corresponding x values / m +% y - corresponding y values / m +% z - corresponding z values / m +% x0 - active secondary sources / m +% +% SOUND_FIELD_MONO_LOCALWFS_VSS(X,Y,Z,xs,src,f,conf) simulates a monochromatic +% sound field of the given source type (src) synthesized with local wave field +% synthesis using virtual secondary sources for the frequency f. +% +% To plot the result use: +% plot_sound_field(P,X,Y,Z,x0,conf); +% or simple call the function without output argument: +% sound_field_mono_localwfs_vss(X,Y,Z,xs,src,f,conf) +% +% See also: plot_sound_field, driving_function_mono_localwfs_vss + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 7; +nargmax = 7; +narginchk(nargmin,nargmax); +isargxs(xs); +isargpositivescalar(f); +isargchar(src); +isargstruct(conf); + + +%% ===== Configuration ================================================== +useplot = conf.plot.useplot; +loudspeakers = conf.plot.loudspeakers; +dimension = conf.dimension; +if strcmp('2D',dimension) + greens_function = 'ls'; +else + greens_function = 'ps'; +end + + +%% ===== Computation ==================================================== +% Get the position of the loudspeakers and its activity +x0 = secondary_source_positions(conf); +% Driving function +[D,x0,xv] = driving_function_mono_localwfs_vss(x0,xs,src,f,conf); +% Wave field +[varargout{1:min(nargout,4)}] = ... + sound_field_mono(X,Y,Z,x0,greens_function,D,f,conf); +% Return secondary sources if desired +if nargout>=5, varargout{5}=x0; end +if nargout==6, varargout{6}=xv; end + + +% ===== Plotting ======================================================== +% Add the virtual loudspeaker positions +if (nargout==0 || useplot) && loudspeakers + hold on; + tmp = conf.plot.realloudspeakers; % cache option for loudspeaker plotting + conf.plot.realloudspeakers = false; + draw_loudspeakers(xv,[1 1 0],conf); + conf.plot.realloudspeakers = tmp; + hold off; +end diff --git a/SFS_monochromatic/sound_field_mono_nfchoa.m b/SFS_monochromatic/sound_field_mono_nfchoa.m index 891a9d19..7ce31025 100644 --- a/SFS_monochromatic/sound_field_mono_nfchoa.m +++ b/SFS_monochromatic/sound_field_mono_nfchoa.m @@ -1,98 +1,93 @@ -function varargout = sound_field_mono_nfchoa(X,Y,Z,xs,src,f,conf) -%SOUND_FIELD_MONO_NFCHOA simulates a sound field for NFC-HOA -% -% Usage: [P,x,y,z,x0] = sound_field_mono_nfchoa(X,Y,Z,xs,src,f,[conf]) -% -% Input parameters: -% X - x-axis / m; single value or [xmin,xmax] -% Y - y-axis / m; single value or [ymin,ymax] -% Z - z-axis / m; single value or [zmin,zmax] -% xs - position of point source / m -% src - source type of the virtual source -% 'pw' - plane wave (xs is the direction of the -% plane wave in this case) -% 'ps' - point source -% f - monochromatic frequency / Hz -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% P - Simulated sound field -% x - corresponding x axis / m -% y - corresponding y axis / m -% z - corresponding z axis / m -% x0 - secondary sources / m -% -% SOUND_FIELD_MONO_NFCHOA(X,Y,Z,xs,src,f,conf) simulates a sound -% field of the given source type (src) using a NFC-HOA driving -% function in the frequency domain. This means by calculating the integral for -% P with a summation. -% To plot the result use plot_sound_field(P,x,y,z,x0). -% -% See also: plot_sound_field, sound_field_imp_nfchoa - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 6; -nargmax = 7; -narginchk(nargmin,nargmax); -isargvector(X,Y,Z); -isargxs(xs); -isargpositivescalar(f); -isargchar(src); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 5; -nargmax = 6; -narginchk(nargmin,nargmax); -isargxs(xs); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 5; -nargmax = 6; -narginchk(nargmin,nargmax); -isargxs(xs); - - -%% ===== Computation ==================================================== -[varargout{1:nargout}] = sound_field_mono(X,Y,Z,[xs 0 -1 0 1],'ps',1,varargin{:}); +function varargout = sound_field_mono_point_source(X,Y,Z,xs,f,conf) +%SOUND_FIELD_MONO_POINT_SOURCE sound field for a point source +% +% Usage: [P,x,y,z] = sound_field_mono_point_source(X,Y,Z,xs,f,conf) +% +% Input parameters: +% X - x-axis / m; single value or [xmin,xmax] or nD-array +% Y - y-axis / m; single value or [ymin,ymax] or nD-array +% Z - z-axis / m; single value or [zmin,zmax] or nD-array +% xs - position of point source / m +% f - monochromatic frequency / Hz +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% P - Simulated wave field +% x - corresponding x values / m +% y - corresponding y values / m +% z - corresponding z values / m +% +% SOUND_FIELD_MONO_POINT_SOURCE(X,Y,Z,xs,f,conf) simulates a monochromatic sound +% field of a point source positioned at xs for the frequency f. +% +% To plot the result use: +% plot_sound_field(P,X,Y,Z,conf); +% or simple call the function without output argument: +% sound_field_mono_point_source(X,Y,Z,xs,f,conf) +% +% See also: sound_field_mono, plot_sound_field, sound_field_imp_point_source + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 6; +nargmax = 6; +narginchk(nargmin,nargmax); +isargxs(xs); + + +%% ===== Computation ==================================================== +[varargout{1:nargout}] = sound_field_mono(X,Y,Z,[xs 0 -1 0 1],'ps',1,f,conf); diff --git a/SFS_monochromatic/sound_field_mono_sdm.m b/SFS_monochromatic/sound_field_mono_sdm.m index 4d669e28..c2af1f12 100644 --- a/SFS_monochromatic/sound_field_mono_sdm.m +++ b/SFS_monochromatic/sound_field_mono_sdm.m @@ -1,12 +1,12 @@ function varargout = sound_field_mono_sdm(X,Y,Z,xs,src,f,conf) -%SOUND_FIELD_MONO_SDM simulates a sound field for WFS +%SOUND_FIELD_MONO_SDM sound field for SDM % -% Usage: [P,x,y,z,x0] = sound_field_mono_sdm(X,Y,Z,xs,src,f,[conf]) +% Usage: [P,x,y,z,x0] = sound_field_mono_sdm(X,Y,Z,xs,src,f,conf) % % Input parameters: -% X - x-axis / m; single value or [xmin,xmax] -% Y - y-axis / m; single value or [ymin,ymax] -% Z - z-axis / m; single value or [zmin,zmax] +% X - x-axis / m; single value or [xmin,xmax] or nD-array +% Y - y-axis / m; single value or [ymin,ymax] or nD-array +% Z - z-axis / m; single value or [zmin,zmax] or nD-array % xs - position of virtual source / m % src - source type of the virtual source % 'pw' - plane wave (xs is the direction of the @@ -14,68 +14,64 @@ % 'ps' - point source % 'fs' - focused source % f - monochromatic frequency / Hz -% conf - optional configuration struct (see SFS_config) +% conf - configuration struct (see SFS_config) % % Output parameters: % P - simulated sound field -% x - corresponding x axis / m -% y - corresponding y axis / m -% z - corresponding z axis / m +% x - corresponding x values / m +% y - corresponding y values / m +% z - corresponding z values / m % x0 - active secondary sources / m % -% SOUND_FIELD_MONO_SDM(X,Y,Z,xs,src,f,conf) simulates a sound field for the -% given source type (src) using SDM driving functions in the temporal domain. -% This means by calculating the integral for P with a summation. -% To plot the result use plot_sound_field(P,x,y,z,x0,win). +% SOUND_FIELD_MONO_SDM(X,Y,Z,xs,src,f,conf) simulates a monochromatic sound +% field for the given source type (src) synthesized with the spectral devision +% method (SDM) for the frequency f. % -% See also: plot_sound_field, sound_field_imp_wfs, driving_function_mono_wfs +% To plot the result use: +% plot_sound_field(P,X,Y,Z,x0,conf); +% or simple call the function without output argument: +% sound_field_mono_sdm(X,Y,Z,xs,src,f,conf) +% +% See also: plot_sound_field, sound_field_mono_sdm_kx %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 6; +nargmin = 7; nargmax = 7; narginchk(nargmin,nargmax); -isargvector(X,Y,Z); isargxs(xs); isargpositivescalar(f); isargchar(src); -if nargin. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 6; +nargmin = 7; nargmax = 7; narginchk(nargmin,nargmax); isargvector(X,Y,Z); @@ -91,11 +92,7 @@ isargxs(xs); isargpositivescalar(f); isargchar(src); -if nargin (omega/c) )); @@ -133,11 +133,11 @@ % G_3D(kx,y,w) = < ____________ % \ 1/(2pi) K0( \|kx^2-(w/c)^2 y ) % -[K,Y] = meshgrid(kx(idxpr),abs(y-X0(2))); -Gkx(idxpr,:) = -1j/4 .* besselh(0,2,sqrt( (omega/c)^2 - K.^2 ).* Y).'; +[kk,yy] = meshgrid(kx(idxpr),abs(y-X0(2))); +Gkx(idxpr,:) = -1i/4 .* besselh(0,2,sqrt( (omega/c)^2 - kk.^2 ).* yy).'; if(withev) - [K,Y] = meshgrid(kx(idxev),abs(y-X0(2))); - Gkx(idxev,:) = 1/(2*pi) .* besselk(0,sqrt( K.^2 - (omega/c)^2).* Y).'; + [kk,yy] = meshgrid(kx(idxev),abs(y-X0(2))); + Gkx(idxev,:) = 1/(2*pi) .* besselk(0,sqrt( kk.^2 - (omega/c)^2).* yy).'; end % ======================================================================== @@ -156,7 +156,7 @@ %% ===== Inverse spatial Fourier transformation ========================= -% +% % / % P(x,y,w) = | Pkx(kx,y,w) * e^(-i kx x) dkx % / @@ -165,15 +165,19 @@ for n=1:length(x) % The following loop can be done faster by using the line below with repmat %for m=1:length(y) - % P(m,n) = sum ( Pkx(:,m) .* exp(-1j*kx*x(n))' )'; + % P(m,n) = sum ( Pkx(:,m) .* exp(-1i*kx*x(n))' )'; %end - P(:,n) = sum ( Pkx .* repmat(exp(-1j*kx*x(n))',1,resolution),1 )'; + P(:,n) = sum ( Pkx .* repmat(exp(-1i*kx*x(n))',1,resolution),1 )'; end -% === Scale signal (at xref) === -P = norm_sound_field_at_xref(P,x,y,z,conf); +% return parameter +if nargout>0, varargout{1}=P; end +if nargout>1, varargout{2}=x; end +if nargout>2, varargout{3}=y; end +if nargout>3, varargout{4}=z; end + %% ===== Plotting ======================================================== if nargout==0 || useplot - plot_sound_field(P,x,y,z,conf); + plot_sound_field(P,X,Y,Z,conf); end diff --git a/SFS_monochromatic/sound_field_mono_wfs.m b/SFS_monochromatic/sound_field_mono_wfs.m index 5d8514bb..a456bc7f 100644 --- a/SFS_monochromatic/sound_field_mono_wfs.m +++ b/SFS_monochromatic/sound_field_mono_wfs.m @@ -1,12 +1,12 @@ function varargout = sound_field_mono_wfs(X,Y,Z,xs,src,f,conf) -%SOUND_FIELD_MONO_WFS simulates a sound field for WFS +%SOUND_FIELD_MONO_WFS sound field for WFS % -% Usage: [P,x,y,z,x0] = sound_field_mono_wfs(X,Y,Z,xs,src,f,[conf]) +% Usage: [P,x,y,z,x0] = sound_field_mono_wfs(X,Y,Z,xs,src,f,conf) % % Input parameters: -% X - x-axis / m; single value or [xmin,xmax] -% Y - y-axis / m; single value or [ymin,ymax] -% Z - z-axis / m; single value or [zmin,zmax] +% X - x-axis / m; single value or [xmin,xmax] or nD-array +% Y - y-axis / m; single value or [ymin,ymax] or nD-array +% Z - z-axis / m; single value or [zmin,zmax] or nD-array % xs - position of virtual source / m % src - source type of the virtual source % 'pw' - plane wave (xs is the direction of the @@ -14,68 +14,64 @@ % 'ps' - point source % 'fs' - focused source % f - monochromatic frequency / Hz -% conf - optional configuration struct (see SFS_config) +% conf - configuration struct (see SFS_config) % % Output parameters: % P - simulated sound field -% x - corresponding x axis / m -% y - corresponding y axis / m -% z - corresponding z axis / m +% x - corresponding x values / m +% y - corresponding y values / m +% z - corresponding z values / m % x0 - active secondary sources / m % -% SOUND_FIELD_MONO_WFS(X,Y,Z,xs,src,f,conf) simulates a sound field for the -% given source type (src) using WFS driving functions in the temporal domain. -% This means by calculating the integral for P with a summation. -% To plot the result use plot_sound_field(P,x,y,z,x0,win). +% SOUND_FIELD_MONO_WFS(X,Y,Z,xs,src,f,conf) simulates a monochromatic sound +% field for the given source type (src) synthesized with wave field synthesis +% for the frequency f. +% +% To plot the result use: +% plot_sound_field(P,X,Y,Z,x0,conf); +% or simple call the function without output argument: +% sound_field_mono_wfs(X,Y,Z,xs,src,f,conf) % % See also: plot_sound_field, sound_field_imp_wfs, driving_function_mono_wfs %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 6; +nargmin = 7; nargmax = 7; narginchk(nargmin,nargmax); -isargvector(X,Y,Z); isargxs(xs); isargpositivescalar(f); isargchar(src); -if nargin. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_octave/rms.m b/SFS_octave/rms.m new file mode 100644 index 00000000..e4e5a9fa --- /dev/null +++ b/SFS_octave/rms.m @@ -0,0 +1,54 @@ +function level = rms(sig,dim) +%RMS root-mean square level +% +% Usage: level = rms(sig,[dim]) +% +% Input parameters: +% sig - signal +% dim - dimension for rms levels (default: 1) +% +% Output parameters: +% level - rms level +% +% See also: db + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ==================================== +nargmin = 1; +nargmax = 2; +narginchk(nargmin,nargmax); +isargmatrix(sig); +if nargin<2, dim=1; end + + +%% ===== Calculation ===================================================== +level = sqrt(mean(sig.*conj(sig),dim)); diff --git a/SFS_plotting/chromajs.m b/SFS_plotting/chromajs.m deleted file mode 100644 index 548ede40..00000000 --- a/SFS_plotting/chromajs.m +++ /dev/null @@ -1,74 +0,0 @@ -function map = chromajs(n) -%CHROMAJS returns a divergent lightyellow-red color map -% -% Usage: map = chromajs([n]) -% -% Input parameters: -% n - optional length of colormap (default uses the figure default -% length) -% -% Output parameters: -% map - colormap [n 3] -% -% CHROMAJS(N) returns an N-by-3 matrix containing a divergent colormap. -% For details on the colormap have a look at: -% http://gka.github.io/palettes/#colors=lightyellow,orangered,deeppink,darkred|steps=7|bez=1|coL=1 -% -% For example, to reset the colormap of the current figure: -% colormap(chromajs) -% -% See also: generate_colormap, moreland, plot_sound_field - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input parameters ======================================= -nargmin = 0; -nargmax = 1; -narginchk(nargmin,nargmax); -if nargin < nargmax - n = size(get(gcf,'colormap'),1); -end - - -%% ===== Computation ===================================================== -table = [ 255, 255, 224 -255, 223, 184 -255, 188, 148 -255, 151, 119 -255, 105, 98 -238, 66, 86 -210, 31, 71 -176, 6, 44 -139, 0, 0]; -map = generate_colormap(table,n); diff --git a/SFS_plotting/colormaps/inferno.m b/SFS_plotting/colormaps/inferno.m new file mode 100644 index 00000000..724f8df3 --- /dev/null +++ b/SFS_plotting/colormaps/inferno.m @@ -0,0 +1,317 @@ +function m = inferno(n) +%INFERNO Blue-red-yellow color map from matplotlib +% +% Usage: m = inferno([n]) +% +% Input parameters: +% n - optional length of colormap (default uses the figure default length) +% +% Output parameters: +% m - colormap [n 3] +% +% INFERNO(N) returns an N-by-3 matrix containing a divergent colormap. +% Without a given N the same length as the current figure's colormap is used. +% For details on the colormap have a look at: https://bids.github.io/colormap/ +% +% To change the colormap current figure run: colormap(inferno) +% +% See also: generate_colormap, yellowred, moreland, plot_sound_field + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking input parameters ======================================= +nargmin = 0; +nargmax = 1; +narginchk(nargmin,nargmax); +if nargin < nargmax + n = size(get(gcf,'colormap'),1); +end + + +%% ===== Computation ===================================================== +table = 256 * [0.001462, 0.000466, 0.013866 + 0.002267, 0.001270, 0.018570 + 0.003299, 0.002249, 0.024239 + 0.004547, 0.003392, 0.030909 + 0.006006, 0.004692, 0.038558 + 0.007676, 0.006136, 0.046836 + 0.009561, 0.007713, 0.055143 + 0.011663, 0.009417, 0.063460 + 0.013995, 0.011225, 0.071862 + 0.016561, 0.013136, 0.080282 + 0.019373, 0.015133, 0.088767 + 0.022447, 0.017199, 0.097327 + 0.025793, 0.019331, 0.105930 + 0.029432, 0.021503, 0.114621 + 0.033385, 0.023702, 0.123397 + 0.037668, 0.025921, 0.132232 + 0.042253, 0.028139, 0.141141 + 0.046915, 0.030324, 0.150164 + 0.051644, 0.032474, 0.159254 + 0.056449, 0.034569, 0.168414 + 0.061340, 0.036590, 0.177642 + 0.066331, 0.038504, 0.186962 + 0.071429, 0.040294, 0.196354 + 0.076637, 0.041905, 0.205799 + 0.081962, 0.043328, 0.215289 + 0.087411, 0.044556, 0.224813 + 0.092990, 0.045583, 0.234358 + 0.098702, 0.046402, 0.243904 + 0.104551, 0.047008, 0.253430 + 0.110536, 0.047399, 0.262912 + 0.116656, 0.047574, 0.272321 + 0.122908, 0.047536, 0.281624 + 0.129285, 0.047293, 0.290788 + 0.135778, 0.046856, 0.299776 + 0.142378, 0.046242, 0.308553 + 0.149073, 0.045468, 0.317085 + 0.155850, 0.044559, 0.325338 + 0.162689, 0.043554, 0.333277 + 0.169575, 0.042489, 0.340874 + 0.176493, 0.041402, 0.348111 + 0.183429, 0.040329, 0.354971 + 0.190367, 0.039309, 0.361447 + 0.197297, 0.038400, 0.367535 + 0.204209, 0.037632, 0.373238 + 0.211095, 0.037030, 0.378563 + 0.217949, 0.036615, 0.383522 + 0.224763, 0.036405, 0.388129 + 0.231538, 0.036405, 0.392400 + 0.238273, 0.036621, 0.396353 + 0.244967, 0.037055, 0.400007 + 0.251620, 0.037705, 0.403378 + 0.258234, 0.038571, 0.406485 + 0.264810, 0.039647, 0.409345 + 0.271347, 0.040922, 0.411976 + 0.277850, 0.042353, 0.414392 + 0.284321, 0.043933, 0.416608 + 0.290763, 0.045644, 0.418637 + 0.297178, 0.047470, 0.420491 + 0.303568, 0.049396, 0.422182 + 0.309935, 0.051407, 0.423721 + 0.316282, 0.053490, 0.425116 + 0.322610, 0.055634, 0.426377 + 0.328921, 0.057827, 0.427511 + 0.335217, 0.060060, 0.428524 + 0.341500, 0.062325, 0.429425 + 0.347771, 0.064616, 0.430217 + 0.354032, 0.066925, 0.430906 + 0.360284, 0.069247, 0.431497 + 0.366529, 0.071579, 0.431994 + 0.372768, 0.073915, 0.432400 + 0.379001, 0.076253, 0.432719 + 0.385228, 0.078591, 0.432955 + 0.391453, 0.080927, 0.433109 + 0.397674, 0.083257, 0.433183 + 0.403894, 0.085580, 0.433179 + 0.410113, 0.087896, 0.433098 + 0.416331, 0.090203, 0.432943 + 0.422549, 0.092501, 0.432714 + 0.428768, 0.094790, 0.432412 + 0.434987, 0.097069, 0.432039 + 0.441207, 0.099338, 0.431594 + 0.447428, 0.101597, 0.431080 + 0.453651, 0.103848, 0.430498 + 0.459875, 0.106089, 0.429846 + 0.466100, 0.108322, 0.429125 + 0.472328, 0.110547, 0.428334 + 0.478558, 0.112764, 0.427475 + 0.484789, 0.114974, 0.426548 + 0.491022, 0.117179, 0.425552 + 0.497257, 0.119379, 0.424488 + 0.503493, 0.121575, 0.423356 + 0.509730, 0.123769, 0.422156 + 0.515967, 0.125960, 0.420887 + 0.522206, 0.128150, 0.419549 + 0.528444, 0.130341, 0.418142 + 0.534683, 0.132534, 0.416667 + 0.540920, 0.134729, 0.415123 + 0.547157, 0.136929, 0.413511 + 0.553392, 0.139134, 0.411829 + 0.559624, 0.141346, 0.410078 + 0.565854, 0.143567, 0.408258 + 0.572081, 0.145797, 0.406369 + 0.578304, 0.148039, 0.404411 + 0.584521, 0.150294, 0.402385 + 0.590734, 0.152563, 0.400290 + 0.596940, 0.154848, 0.398125 + 0.603139, 0.157151, 0.395891 + 0.609330, 0.159474, 0.393589 + 0.615513, 0.161817, 0.391219 + 0.621685, 0.164184, 0.388781 + 0.627847, 0.166575, 0.386276 + 0.633998, 0.168992, 0.383704 + 0.640135, 0.171438, 0.381065 + 0.646260, 0.173914, 0.378359 + 0.652369, 0.176421, 0.375586 + 0.658463, 0.178962, 0.372748 + 0.664540, 0.181539, 0.369846 + 0.670599, 0.184153, 0.366879 + 0.676638, 0.186807, 0.363849 + 0.682656, 0.189501, 0.360757 + 0.688653, 0.192239, 0.357603 + 0.694627, 0.195021, 0.354388 + 0.700576, 0.197851, 0.351113 + 0.706500, 0.200728, 0.347777 + 0.712396, 0.203656, 0.344383 + 0.718264, 0.206636, 0.340931 + 0.724103, 0.209670, 0.337424 + 0.729909, 0.212759, 0.333861 + 0.735683, 0.215906, 0.330245 + 0.741423, 0.219112, 0.326576 + 0.747127, 0.222378, 0.322856 + 0.752794, 0.225706, 0.319085 + 0.758422, 0.229097, 0.315266 + 0.764010, 0.232554, 0.311399 + 0.769556, 0.236077, 0.307485 + 0.775059, 0.239667, 0.303526 + 0.780517, 0.243327, 0.299523 + 0.785929, 0.247056, 0.295477 + 0.791293, 0.250856, 0.291390 + 0.796607, 0.254728, 0.287264 + 0.801871, 0.258674, 0.283099 + 0.807082, 0.262692, 0.278898 + 0.812239, 0.266786, 0.274661 + 0.817341, 0.270954, 0.270390 + 0.822386, 0.275197, 0.266085 + 0.827372, 0.279517, 0.261750 + 0.832299, 0.283913, 0.257383 + 0.837165, 0.288385, 0.252988 + 0.841969, 0.292933, 0.248564 + 0.846709, 0.297559, 0.244113 + 0.851384, 0.302260, 0.239636 + 0.855992, 0.307038, 0.235133 + 0.860533, 0.311892, 0.230606 + 0.865006, 0.316822, 0.226055 + 0.869409, 0.321827, 0.221482 + 0.873741, 0.326906, 0.216886 + 0.878001, 0.332060, 0.212268 + 0.882188, 0.337287, 0.207628 + 0.886302, 0.342586, 0.202968 + 0.890341, 0.347957, 0.198286 + 0.894305, 0.353399, 0.193584 + 0.898192, 0.358911, 0.188860 + 0.902003, 0.364492, 0.184116 + 0.905735, 0.370140, 0.179350 + 0.909390, 0.375856, 0.174563 + 0.912966, 0.381636, 0.169755 + 0.916462, 0.387481, 0.164924 + 0.919879, 0.393389, 0.160070 + 0.923215, 0.399359, 0.155193 + 0.926470, 0.405389, 0.150292 + 0.929644, 0.411479, 0.145367 + 0.932737, 0.417627, 0.140417 + 0.935747, 0.423831, 0.135440 + 0.938675, 0.430091, 0.130438 + 0.941521, 0.436405, 0.125409 + 0.944285, 0.442772, 0.120354 + 0.946965, 0.449191, 0.115272 + 0.949562, 0.455660, 0.110164 + 0.952075, 0.462178, 0.105031 + 0.954506, 0.468744, 0.099874 + 0.956852, 0.475356, 0.094695 + 0.959114, 0.482014, 0.089499 + 0.961293, 0.488716, 0.084289 + 0.963387, 0.495462, 0.079073 + 0.965397, 0.502249, 0.073859 + 0.967322, 0.509078, 0.068659 + 0.969163, 0.515946, 0.063488 + 0.970919, 0.522853, 0.058367 + 0.972590, 0.529798, 0.053324 + 0.974176, 0.536780, 0.048392 + 0.975677, 0.543798, 0.043618 + 0.977092, 0.550850, 0.039050 + 0.978422, 0.557937, 0.034931 + 0.979666, 0.565057, 0.031409 + 0.980824, 0.572209, 0.028508 + 0.981895, 0.579392, 0.026250 + 0.982881, 0.586606, 0.024661 + 0.983779, 0.593849, 0.023770 + 0.984591, 0.601122, 0.023606 + 0.985315, 0.608422, 0.024202 + 0.985952, 0.615750, 0.025592 + 0.986502, 0.623105, 0.027814 + 0.986964, 0.630485, 0.030908 + 0.987337, 0.637890, 0.034916 + 0.987622, 0.645320, 0.039886 + 0.987819, 0.652773, 0.045581 + 0.987926, 0.660250, 0.051750 + 0.987945, 0.667748, 0.058329 + 0.987874, 0.675267, 0.065257 + 0.987714, 0.682807, 0.072489 + 0.987464, 0.690366, 0.079990 + 0.987124, 0.697944, 0.087731 + 0.986694, 0.705540, 0.095694 + 0.986175, 0.713153, 0.103863 + 0.985566, 0.720782, 0.112229 + 0.984865, 0.728427, 0.120785 + 0.984075, 0.736087, 0.129527 + 0.983196, 0.743758, 0.138453 + 0.982228, 0.751442, 0.147565 + 0.981173, 0.759135, 0.156863 + 0.980032, 0.766837, 0.166353 + 0.978806, 0.774545, 0.176037 + 0.977497, 0.782258, 0.185923 + 0.976108, 0.789974, 0.196018 + 0.974638, 0.797692, 0.206332 + 0.973088, 0.805409, 0.216877 + 0.971468, 0.813122, 0.227658 + 0.969783, 0.820825, 0.238686 + 0.968041, 0.828515, 0.249972 + 0.966243, 0.836191, 0.261534 + 0.964394, 0.843848, 0.273391 + 0.962517, 0.851476, 0.285546 + 0.960626, 0.859069, 0.298010 + 0.958720, 0.866624, 0.310820 + 0.956834, 0.874129, 0.323974 + 0.954997, 0.881569, 0.337475 + 0.953215, 0.888942, 0.351369 + 0.951546, 0.896226, 0.365627 + 0.950018, 0.903409, 0.380271 + 0.948683, 0.910473, 0.395289 + 0.947594, 0.917399, 0.410665 + 0.946809, 0.924168, 0.426373 + 0.946392, 0.930761, 0.442367 + 0.946403, 0.937159, 0.458592 + 0.946903, 0.943348, 0.474970 + 0.947937, 0.949318, 0.491426 + 0.949545, 0.955063, 0.507860 + 0.951740, 0.960587, 0.524203 + 0.954529, 0.965896, 0.540361 + 0.957896, 0.971003, 0.556275 + 0.961812, 0.975924, 0.571925 + 0.966249, 0.980678, 0.587206 + 0.971162, 0.985282, 0.602154 + 0.976511, 0.989753, 0.616760 + 0.982257, 0.994109, 0.631017 + 0.988362, 0.998364, 0.644924]; + +m = generate_colormap(table,n); diff --git a/SFS_plotting/colormaps/magma.m b/SFS_plotting/colormaps/magma.m new file mode 100644 index 00000000..bb837a74 --- /dev/null +++ b/SFS_plotting/colormaps/magma.m @@ -0,0 +1,317 @@ +function m = magma(n) +%MAGMA Blue-red-yellow color map from matplotlib +% +% Usage: m = magma([n]) +% +% Input parameters: +% n - optional length of colormap (default uses the figure default length) +% +% Output parameters: +% m - colormap [n 3] +% +% MAGMA(N) returns an N-by-3 matrix containing a divergent colormap. +% Without a given N the same length as the current figure's colormap is used. +% For details on the colormap have a look at: https://bids.github.io/colormap/ +% +% To change the colormap current figure run: colormap(magma) +% +% See also: generate_colormap, yellowred, moreland, plot_sound_field + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking input parameters ======================================= +nargmin = 0; +nargmax = 1; +narginchk(nargmin,nargmax); +if nargin < nargmax + n = size(get(gcf,'colormap'),1); +end + + +%% ===== Computation ===================================================== +table = 256 * [0.001462, 0.000466, 0.013866 + 0.002258, 0.001295, 0.018331 + 0.003279, 0.002305, 0.023708 + 0.004512, 0.003490, 0.029965 + 0.005950, 0.004843, 0.037130 + 0.007588, 0.006356, 0.044973 + 0.009426, 0.008022, 0.052844 + 0.011465, 0.009828, 0.060750 + 0.013708, 0.011771, 0.068667 + 0.016156, 0.013840, 0.076603 + 0.018815, 0.016026, 0.084584 + 0.021692, 0.018320, 0.092610 + 0.024792, 0.020715, 0.100676 + 0.028123, 0.023201, 0.108787 + 0.031696, 0.025765, 0.116965 + 0.035520, 0.028397, 0.125209 + 0.039608, 0.031090, 0.133515 + 0.043830, 0.033830, 0.141886 + 0.048062, 0.036607, 0.150327 + 0.052320, 0.039407, 0.158841 + 0.056615, 0.042160, 0.167446 + 0.060949, 0.044794, 0.176129 + 0.065330, 0.047318, 0.184892 + 0.069764, 0.049726, 0.193735 + 0.074257, 0.052017, 0.202660 + 0.078815, 0.054184, 0.211667 + 0.083446, 0.056225, 0.220755 + 0.088155, 0.058133, 0.229922 + 0.092949, 0.059904, 0.239164 + 0.097833, 0.061531, 0.248477 + 0.102815, 0.063010, 0.257854 + 0.107899, 0.064335, 0.267289 + 0.113094, 0.065492, 0.276784 + 0.118405, 0.066479, 0.286321 + 0.123833, 0.067295, 0.295879 + 0.129380, 0.067935, 0.305443 + 0.135053, 0.068391, 0.315000 + 0.140858, 0.068654, 0.324538 + 0.146785, 0.068738, 0.334011 + 0.152839, 0.068637, 0.343404 + 0.159018, 0.068354, 0.352688 + 0.165308, 0.067911, 0.361816 + 0.171713, 0.067305, 0.370771 + 0.178212, 0.066576, 0.379497 + 0.184801, 0.065732, 0.387973 + 0.191460, 0.064818, 0.396152 + 0.198177, 0.063862, 0.404009 + 0.204935, 0.062907, 0.411514 + 0.211718, 0.061992, 0.418647 + 0.218512, 0.061158, 0.425392 + 0.225302, 0.060445, 0.431742 + 0.232077, 0.059889, 0.437695 + 0.238826, 0.059517, 0.443256 + 0.245543, 0.059352, 0.448436 + 0.252220, 0.059415, 0.453248 + 0.258857, 0.059706, 0.457710 + 0.265447, 0.060237, 0.461840 + 0.271994, 0.060994, 0.465660 + 0.278493, 0.061978, 0.469190 + 0.284951, 0.063168, 0.472451 + 0.291366, 0.064553, 0.475462 + 0.297740, 0.066117, 0.478243 + 0.304081, 0.067835, 0.480812 + 0.310382, 0.069702, 0.483186 + 0.316654, 0.071690, 0.485380 + 0.322899, 0.073782, 0.487408 + 0.329114, 0.075972, 0.489287 + 0.335308, 0.078236, 0.491024 + 0.341482, 0.080564, 0.492631 + 0.347636, 0.082946, 0.494121 + 0.353773, 0.085373, 0.495501 + 0.359898, 0.087831, 0.496778 + 0.366012, 0.090314, 0.497960 + 0.372116, 0.092816, 0.499053 + 0.378211, 0.095332, 0.500067 + 0.384299, 0.097855, 0.501002 + 0.390384, 0.100379, 0.501864 + 0.396467, 0.102902, 0.502658 + 0.402548, 0.105420, 0.503386 + 0.408629, 0.107930, 0.504052 + 0.414709, 0.110431, 0.504662 + 0.420791, 0.112920, 0.505215 + 0.426877, 0.115395, 0.505714 + 0.432967, 0.117855, 0.506160 + 0.439062, 0.120298, 0.506555 + 0.445163, 0.122724, 0.506901 + 0.451271, 0.125132, 0.507198 + 0.457386, 0.127522, 0.507448 + 0.463508, 0.129893, 0.507652 + 0.469640, 0.132245, 0.507809 + 0.475780, 0.134577, 0.507921 + 0.481929, 0.136891, 0.507989 + 0.488088, 0.139186, 0.508011 + 0.494258, 0.141462, 0.507988 + 0.500438, 0.143719, 0.507920 + 0.506629, 0.145958, 0.507806 + 0.512831, 0.148179, 0.507648 + 0.519045, 0.150383, 0.507443 + 0.525270, 0.152569, 0.507192 + 0.531507, 0.154739, 0.506895 + 0.537755, 0.156894, 0.506551 + 0.544015, 0.159033, 0.506159 + 0.550287, 0.161158, 0.505719 + 0.556571, 0.163269, 0.505230 + 0.562866, 0.165368, 0.504692 + 0.569172, 0.167454, 0.504105 + 0.575490, 0.169530, 0.503466 + 0.581819, 0.171596, 0.502777 + 0.588158, 0.173652, 0.502035 + 0.594508, 0.175701, 0.501241 + 0.600868, 0.177743, 0.500394 + 0.607238, 0.179779, 0.499492 + 0.613617, 0.181811, 0.498536 + 0.620005, 0.183840, 0.497524 + 0.626401, 0.185867, 0.496456 + 0.632805, 0.187893, 0.495332 + 0.639216, 0.189921, 0.494150 + 0.645633, 0.191952, 0.492910 + 0.652056, 0.193986, 0.491611 + 0.658483, 0.196027, 0.490253 + 0.664915, 0.198075, 0.488836 + 0.671349, 0.200133, 0.487358 + 0.677786, 0.202203, 0.485819 + 0.684224, 0.204286, 0.484219 + 0.690661, 0.206384, 0.482558 + 0.697098, 0.208501, 0.480835 + 0.703532, 0.210638, 0.479049 + 0.709962, 0.212797, 0.477201 + 0.716387, 0.214982, 0.475290 + 0.722805, 0.217194, 0.473316 + 0.729216, 0.219437, 0.471279 + 0.735616, 0.221713, 0.469180 + 0.742004, 0.224025, 0.467018 + 0.748378, 0.226377, 0.464794 + 0.754737, 0.228772, 0.462509 + 0.761077, 0.231214, 0.460162 + 0.767398, 0.233705, 0.457755 + 0.773695, 0.236249, 0.455289 + 0.779968, 0.238851, 0.452765 + 0.786212, 0.241514, 0.450184 + 0.792427, 0.244242, 0.447543 + 0.798608, 0.247040, 0.444848 + 0.804752, 0.249911, 0.442102 + 0.810855, 0.252861, 0.439305 + 0.816914, 0.255895, 0.436461 + 0.822926, 0.259016, 0.433573 + 0.828886, 0.262229, 0.430644 + 0.834791, 0.265540, 0.427671 + 0.840636, 0.268953, 0.424666 + 0.846416, 0.272473, 0.421631 + 0.852126, 0.276106, 0.418573 + 0.857763, 0.279857, 0.415496 + 0.863320, 0.283729, 0.412403 + 0.868793, 0.287728, 0.409303 + 0.874176, 0.291859, 0.406205 + 0.879464, 0.296125, 0.403118 + 0.884651, 0.300530, 0.400047 + 0.889731, 0.305079, 0.397002 + 0.894700, 0.309773, 0.393995 + 0.899552, 0.314616, 0.391037 + 0.904281, 0.319610, 0.388137 + 0.908884, 0.324755, 0.385308 + 0.913354, 0.330052, 0.382563 + 0.917689, 0.335500, 0.379915 + 0.921884, 0.341098, 0.377376 + 0.925937, 0.346844, 0.374959 + 0.929845, 0.352734, 0.372677 + 0.933606, 0.358764, 0.370541 + 0.937221, 0.364929, 0.368567 + 0.940687, 0.371224, 0.366762 + 0.944006, 0.377643, 0.365136 + 0.947180, 0.384178, 0.363701 + 0.950210, 0.390820, 0.362468 + 0.953099, 0.397563, 0.361438 + 0.955849, 0.404400, 0.360619 + 0.958464, 0.411324, 0.360014 + 0.960949, 0.418323, 0.359630 + 0.963310, 0.425390, 0.359469 + 0.965549, 0.432519, 0.359529 + 0.967671, 0.439703, 0.359810 + 0.969680, 0.446936, 0.360311 + 0.971582, 0.454210, 0.361030 + 0.973381, 0.461520, 0.361965 + 0.975082, 0.468861, 0.363111 + 0.976690, 0.476226, 0.364466 + 0.978210, 0.483612, 0.366025 + 0.979645, 0.491014, 0.367783 + 0.981000, 0.498428, 0.369734 + 0.982279, 0.505851, 0.371874 + 0.983485, 0.513280, 0.374198 + 0.984622, 0.520713, 0.376698 + 0.985693, 0.528148, 0.379371 + 0.986700, 0.535582, 0.382210 + 0.987646, 0.543015, 0.385210 + 0.988533, 0.550446, 0.388365 + 0.989363, 0.557873, 0.391671 + 0.990138, 0.565296, 0.395122 + 0.990871, 0.572706, 0.398714 + 0.991558, 0.580107, 0.402441 + 0.992196, 0.587502, 0.406299 + 0.992785, 0.594891, 0.410283 + 0.993326, 0.602275, 0.414390 + 0.993834, 0.609644, 0.418613 + 0.994309, 0.616999, 0.422950 + 0.994738, 0.624350, 0.427397 + 0.995122, 0.631696, 0.431951 + 0.995480, 0.639027, 0.436607 + 0.995810, 0.646344, 0.441361 + 0.996096, 0.653659, 0.446213 + 0.996341, 0.660969, 0.451160 + 0.996580, 0.668256, 0.456192 + 0.996775, 0.675541, 0.461314 + 0.996925, 0.682828, 0.466526 + 0.997077, 0.690088, 0.471811 + 0.997186, 0.697349, 0.477182 + 0.997254, 0.704611, 0.482635 + 0.997325, 0.711848, 0.488154 + 0.997351, 0.719089, 0.493755 + 0.997351, 0.726324, 0.499428 + 0.997341, 0.733545, 0.505167 + 0.997285, 0.740772, 0.510983 + 0.997228, 0.747981, 0.516859 + 0.997138, 0.755190, 0.522806 + 0.997019, 0.762398, 0.528821 + 0.996898, 0.769591, 0.534892 + 0.996727, 0.776795, 0.541039 + 0.996571, 0.783977, 0.547233 + 0.996369, 0.791167, 0.553499 + 0.996162, 0.798348, 0.559820 + 0.995932, 0.805527, 0.566202 + 0.995680, 0.812706, 0.572645 + 0.995424, 0.819875, 0.579140 + 0.995131, 0.827052, 0.585701 + 0.994851, 0.834213, 0.592307 + 0.994524, 0.841387, 0.598983 + 0.994222, 0.848540, 0.605696 + 0.993866, 0.855711, 0.612482 + 0.993545, 0.862859, 0.619299 + 0.993170, 0.870024, 0.626189 + 0.992831, 0.877168, 0.633109 + 0.992440, 0.884330, 0.640099 + 0.992089, 0.891470, 0.647116 + 0.991688, 0.898627, 0.654202 + 0.991332, 0.905763, 0.661309 + 0.990930, 0.912915, 0.668481 + 0.990570, 0.920049, 0.675675 + 0.990175, 0.927196, 0.682926 + 0.989815, 0.934329, 0.690198 + 0.989434, 0.941470, 0.697519 + 0.989077, 0.948604, 0.704863 + 0.988717, 0.955742, 0.712242 + 0.988367, 0.962878, 0.719649 + 0.988033, 0.970012, 0.727077 + 0.987691, 0.977154, 0.734536 + 0.987387, 0.984288, 0.742002 + 0.987053, 0.991438, 0.749504]; + +m = generate_colormap(table,n); diff --git a/SFS_plotting/moreland.m b/SFS_plotting/colormaps/moreland.m similarity index 66% rename from SFS_plotting/moreland.m rename to SFS_plotting/colormaps/moreland.m index 55b5e0c1..aa9c772e 100644 --- a/SFS_plotting/moreland.m +++ b/SFS_plotting/colormaps/moreland.m @@ -1,58 +1,52 @@ function m = moreland(n) %MORELAND Divergent red-white-blue color map % -% Usage: m = moreland(n) +% Usage: m = moreland([n]) % % Input parameters: % n - optional length of colormap (default uses the figure default length) % % Output parameters: -% m - colormap +% m - colormap [n 3] % % MORELAND(N) returns an N-by-3 matrix containing a divergent colormap. +% Without a given N the same length as the current figure's colormap is used. % For details on the colormap have a look at: -% Without a given N the same length as the current figure's -% colormap is used. -% For details on the colormap have a look at: -% http://www.sandia.gov/~kmorel/documents/ColorMaps/ +% http://www.kennethmoreland.com/color-advice/ % -% For example, to reset the colormap of the current figure: -% colormap(moreland) +% To change the colormap current figure run: colormap(moreland) % -% Original written by Lewis Marshall +% Original written by Lewis Marshall. % -% See also: generate_colormap, chromjs, plot_sound_field +% See also: generate_colormap, yellowred, plot_sound_field %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_plotting/colormaps/yellowred.m b/SFS_plotting/colormaps/yellowred.m new file mode 100644 index 00000000..19a781c1 --- /dev/null +++ b/SFS_plotting/colormaps/yellowred.m @@ -0,0 +1,69 @@ +function map = yellowred(n) +%CHROMAJS returns a divergent lightyellow-red color map +% +% Usage: m = yellowred([n]) +% +% Input parameters: +% n - optional length of colormap (default uses the figure default length) +% +% Output parameters: +% m - colormap [n 3] +% +% YELLOWRED(N) returns an N-by-3 matrix containing a divergent colormap. +% Without a given N the same length as the current figure's colormap is used. +% For details on the colormap have a look at: https://bit.ly/2vC3Ogr +% +% To change the colormap current figure run: colormap(yellowred) +% +% See also: generate_colormap, moreland, plot_sound_field + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking input parameters ======================================= +nargmin = 0; +nargmax = 1; +narginchk(nargmin,nargmax); +if nargin < nargmax + n = size(get(gcf,'colormap'),1); +end + + +%% ===== Computation ===================================================== +table = [ 255, 255, 224 +255, 223, 184 +255, 188, 148 +255, 151, 119 +255, 105, 98 +238, 66, 86 +210, 31, 71 +176, 6, 44 +139, 0, 0]; +map = generate_colormap(table,n); diff --git a/SFS_plotting/cubehelix.m b/SFS_plotting/cubehelix.m deleted file mode 100644 index 970b4282..00000000 --- a/SFS_plotting/cubehelix.m +++ /dev/null @@ -1,98 +0,0 @@ -function map = cubehelix(nlev,start,rots,hue,gamma) -%CUBEHELIX returns the cubehelix colormap -% -% Usage: cubehelix([[n],start,rots,hue,gamma]) -% -% Input parameters: -% n - optional length of colormap (default uses the figure default -% length) -% start - colour to begin at (1=red, 2=green, 3=red; e.g. 0.5=purple), -% default: 0.5 -% rots - number of rotations, default: -1.5 -% hue - hue intensity scaling, default: 1.2 -% gamma - intensity correction, default: 1.0 -% -% Output parameters: -% map - colormap [n 3] -% -% CUBEHELIX(nlev,start,rots,hue,gamma) calculates a "cube helix" color map. -% The colors are a tapered helix around the diagonal of the RGB colour cube, -% from black [0,0,0] to white [1,1,1]. Deviations away from the diagonal vary -% quadratically, increasing from zero at black to a maximum and then -% decreasing to zero at white, all the time rotating in color. -% The routine returns an n-by-3 matrix. -% -% For example, to reset the colormap of the current figure: -% colormap(cubehelix) -% -% See arXiv:1108.5083 and https://www.mrao.cam.ac.uk/~dag/CUBEHELIX/ for more -% details. -% -% Original written by Dave Green and Philip Graff -% -% See also: chromajs, moreland, plot_sound_field - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input parameters ======================================= -nargmin = 0; -nargmax = 5; -narginchk(nargmin,nargmax); -if nargin==0 - n = size(get(gcf,'colormap'),1); -end -if nargin==0 | nargin==1 - start = 0.5; - rots = -1.5; - hue = 1.2; - gamma = 1.0; -else - error('%s: you have to use 0, 1, or 5 input args.',upper(mfilename)); -end -map = zeros(n,3); -A = [-0.14861,1.78277;-0.29227,-0.90649;1.97294,0]; -for ii=1:n - fract = (ii-1)/(n-1); - angle = 2*pi*(start/3+1+rots*fract); - fract = fract^gamma; - amp = hue*fract*(1-fract)/2; - map(ii,:) = fract+amp*(A*[cos(angle);sin(angle)])'; - for jj=1:3 - if map(ii,jj)<0 - map(ii,jj) = 0; - elseif map(ii,jj)>1 - map(ii,jj) = 1; - end - end -end diff --git a/SFS_plotting/draw_loudspeakers.m b/SFS_plotting/draw_loudspeakers.m index 512b6658..e2dda2fb 100644 --- a/SFS_plotting/draw_loudspeakers.m +++ b/SFS_plotting/draw_loudspeakers.m @@ -1,159 +1,146 @@ -function draw_loudspeakers(x0,dimensions,conf) -%DRAW_LOUDSPEAKERS draws loudspeaker symbols or "o" at the given positions -% -% Usage: draw_loudspeakers(x0,[dimensions],[conf]) -% -% Input options: -% x0 - positions and directions of the loudspeakers / m -% dimensions - dimension defining the plane in which the loudspeaker -% symbol should be plotted. For example [1 1 0] corresponds -% to the xy-plane. Default: [1 1 0] -% conf - optional configuration struct (see SFS_config) -% -% DRAW_LOUDSPEAKERS(x0,dimensions) draws loudspeaker symbols or filled points -% at the given secondary source positions. This can be controlled by the -% conf.plot.realloudspeakers setting. The loudspeaker symbols are pointing in -% their given direction. -% -% See also: plot_sound_field - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameter ===================================== -nargmin = 1; -nargmax = 3; -narginchk(nargmin,nargmax); -isargsecondarysource(x0) -nls = size(x0,1); -if nargin==nargmax-1 - if isstruct(dimensions) - conf = dimensions; - dimensions = [1 1 0]; - else - conf = SFS_config; - end -elseif nargin==nargmax-2 - conf = SFS_config; - dimensions = [1 1 0]; -end - - -%% ===== Configuration =================================================== -p.realloudspeakers = conf.plot.realloudspeakers; -p.lssize = conf.plot.lssize; - - -%% ===== Plotting ======================================================== -% Check in which plane we should plot the secondary sources and shift them -% around accordingly -if ~any(dimensions) - return; -elseif ~dimensions(1) - x0(:,1:2) = x0(:,2:3); -elseif ~dimensions(2) - x0(:,2) = x0(:,3); -end - -% Weightings of the single sources -win = x0(:,7); - -% Plot only "x" at the loudspeaker positions, use this as default for all cases -% that are not the x-y-plane -if ~p.realloudspeakers || ~(dimensions(1)&&dimensions(2)) - if p.realloudspeakers && ~(dimensions(1)&&dimensions(2)) - warning('%s: Real loudspeaker can only be drawn in the x-y-plane', ... - upper(mfilename)); - end - % plot all secondary sources with the same color + symbol - plot(x0(:,1),x0(:,2),'o', ... - 'MarkerFaceColor','k', ... - 'MarkerEdgeColor','k', ... - 'MarkerSize',4); -else - % Set fill color for active loudspeakers - % Scale the color. sc = 1 => black. sc = 0.5 => gray. - sc = 0.6; - fc = [(1-sc.*win), ... - (1-sc.*win), ... - (1-sc.*win)]; - - w = p.lssize; - h = p.lssize; - - % Plot a real speaker symbol at the desired position - % vertex coordinates - %v1 = [-h/2 -h/2 0 0 -h/2 ; -w/2 w/2 w/2 -w/2 -w/2]; - %v2 = [0 h/2 h/2 0 ; -w/6 -w/2 w/2 w/6]; - v1 = [-h -h -h/2 -h/2 -h ; -w/2 w/2 w/2 -w/2 -w/2 ; 0 0 0 0 0]; - v2 = [-h/2 0 0 -h/2 ; -w/6 -w/2 w/2 w/6 ; 0 0 0 0 ]; - - hold on; - - % draw loudspeakers - for n=1:nls - - % Get the azimuth direction of the secondary sources - [phi,~] = cart2pol(x0(n,4),x0(n,5)); - - % Rotation matrix (orientation of the speakers) - % R = [cos(phi(n)) -sin(phi(n));sin(phi(n)) cos(phi(n))]; - R = rotation_matrix(phi); - - for k=1:length(v1) - vr1(:,k) = R * v1(:,k); - end - - for k=1:length(v2) - vr2(:,k) = R * v2(:,k); - end - - % shift - v01(1,:) = vr1(1,:) + x0(n,1); - v01(2,:) = vr1(2,:) + x0(n,2); - v02(1,:) = vr2(1,:) + x0(n,1); - v02(2,:) = vr2(2,:) + x0(n,2); - - - % Draw speakers - fill(v01(1,:),v01(2,:),fc(n,:)); - fill(v02(1,:),v02(2,:),fc(n,:)); - - end - - hold off; - -end - -% Set equal axis ratio -axis image +function draw_loudspeakers(x0,dimensions,conf) +%DRAW_LOUDSPEAKERS draws loudspeaker symbols or "o" at the given positions +% +% Usage: draw_loudspeakers(x0,[dimensions],conf) +% +% Input parameters: +% x0 - positions and directions of the loudspeakers / m +% dimensions - dimension defining the plane in which the loudspeaker +% symbol should be plotted. For example [1 1 0] corresponds +% to the xy-plane. Default: [1 1 0] +% conf - configuration struct (see SFS_config) +% +% DRAW_LOUDSPEAKERS(x0,dimensions,conf) draws loudspeaker symbols or filled +% points at the given secondary source positions. This can be controlled by +% the conf.plot.realloudspeakers setting. The loudspeaker symbols are pointing +% in their given direction and are colored accordingly to their weights, +% whereby the weights are scaled to an absolute maximum of 1 before. +% +% See also: plot_sound_field + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameter ===================================== +nargmin = 2; +nargmax = 3; +narginchk(nargmin,nargmax); +isargsecondarysource(x0) +nls = size(x0,1); +if nargin black, sc = 0.5 => gray. + sc = 0.6; + fc = [(1-sc.*weights), ... + (1-sc.*weights), ... + (1-sc.*weights)]; + + % Plot a real speaker symbol at the desired position + % vertex coordinates with height and width after lssize + w = p.lssize; + h = p.lssize; + v1 = [-h -h -h/2 -h/2 -h ; -w/2 w/2 w/2 -w/2 -w/2 ; 0 0 0 0 0]; + v2 = [-h/2 0 0 -h/2 ; -w/6 -w/2 w/2 w/6 ; 0 0 0 0 ]; + + hold on; + + % Draw loudspeakers + for n=1:nls + + % Get the azimuth direction of the secondary sources + [phi,~] = cart2pol(x0(n,4),x0(n,5)); + + % Rotation matrix (orientation of the speakers) + % R = [cos(phi(n)) -sin(phi(n));sin(phi(n)) cos(phi(n))]; + R = rotation_matrix(phi); + for k=1:length(v1) + vr1(:,k) = R * v1(:,k); + end + for k=1:length(v2) + vr2(:,k) = R * v2(:,k); + end + + % Shift + v01(1,:) = vr1(1,:) + x0(n,1); + v01(2,:) = vr1(2,:) + x0(n,2); + v02(1,:) = vr2(1,:) + x0(n,1); + v02(2,:) = vr2(2,:) + x0(n,2); + + % Draw loudspeakers + fill(v01(1,:),v01(2,:),fc(n,:)); + fill(v02(1,:),v02(2,:),fc(n,:)); + + end + + hold off; + +end + +% Set equal axis ratio +axis image diff --git a/SFS_plotting/figsize.m b/SFS_plotting/figsize.m index a647c86e..6d7c001f 100644 --- a/SFS_plotting/figsize.m +++ b/SFS_plotting/figsize.m @@ -1,77 +1,74 @@ -function figsize(x,y,unit) -%FIGSIZE changes the size of a figure -% -% Usage: figsize(x,y,unit) -% -% Input options: -% x,y - x,y size of the figure -% unit - unit in which the size is given, can be one of the -% following: 'cm', 'px' -% -% FIGSIZE(x,y,unit) sets the size of the last figure to x,y in the given unit. -% -% See also: plot_sound_field - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameter ===================================== -nargmin = 0; -nargmax = 3; -narginchk(nargmin,nargmax); -if nargin==0 - x = 10; - y = 10; - unit = 'cm'; -end -isargpositivescalar(x,y) -isargchar(unit) - - -%% ===== Main ============================================================ -% Convert to centimeters -if strcmp('px',unit) || strcmp('pixel',unit) - x = px2cm(x); - y = px2cm(y); -elseif strcmp('inches',unit) - x = in2cm(x); - y = in2cm(y); -end - -% Adjust the font size to match the figure size -%set_font_size(12); - -% Set the figure dimensions -set(gcf,'PaperUnits','centimeters'); -set(gcf,'PaperSize',[y,x]); -set(gcf,'PaperPosition',[0,0,x,y]); +function figsize(x,y,unit) +%FIGSIZE size of a figure +% +% Usage: figsize(x,y,unit) +% +% Input parameters: +% x,y - x,y size of the figure +% unit - unit in which the size is given, can be one of the +% following: 'cm', 'px' +% +% FIGSIZE(x,y,unit) sets the size of the last figure to x,y in the given unit. +% +% See also: plot_sound_field + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameter ===================================== +nargmin = 0; +nargmax = 3; +narginchk(nargmin,nargmax); +if nargin==0 + x = 10; + y = 10; + unit = 'cm'; +end +isargpositivescalar(x,y) +isargchar(unit) + + +%% ===== Main ============================================================ +% Convert to centimeters +if strcmp('px',unit) || strcmp('pixel',unit) + x = px2cm(x); + y = px2cm(y); +elseif strcmp('inches',unit) + x = in2cm(x); + y = in2cm(y); +end + +% Adjust the font size to match the figure size +%set_font_size(12); + +% Set the figure dimensions +set(gcf,'PaperUnits','centimeters'); +set(gcf,'PaperSize',[y,x]); +set(gcf,'PaperPosition',[0,0,x,y]); diff --git a/SFS_plotting/generate_colormap.m b/SFS_plotting/generate_colormap.m index af80e886..9fb4439a 100644 --- a/SFS_plotting/generate_colormap.m +++ b/SFS_plotting/generate_colormap.m @@ -15,38 +15,35 @@ % The color values are specified in table, which will be interpolated to the % desired number of entries n. % -% See also: moreland, chromajs +% See also: moreland, yellowred %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_plotting/generate_movie.m b/SFS_plotting/generate_movie.m index 15bc8a0c..0729b687 100644 --- a/SFS_plotting/generate_movie.m +++ b/SFS_plotting/generate_movie.m @@ -1,75 +1,81 @@ -function generate_movie(outfile,directory,pattern) -%GENERATE_MOVIE generates a movie from given png files -% -% Usage: generate_movie(outfile,[[directory],pattern]) -% -% Input parameters: -% outfile - file name for the movie -% directory - dir containing the png files -% pattern - starting pattern of the png files to use -% -% GENERATE_MOVIE(outfile,directory,pattern) generates a movie and stores it -% in outfile. To produce the movie all png files starting with pattern in the -% given directory are processed. If no pattern is given, all png files are -% used. -% -% See also: plot_sound_field, movie_sound_field_mono_wfs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 3; -narginchk(nargmin,nargmax); -if ~exist('directory','var') - directory = pwd; -end -if ~exist('pattern','var') - pattern = ''; -end -isargchar(outfile,pattern); -isargdir(directory); - - -%% ===== Movie =========================================================== -% Generate a movie from the png files with MEncoder -status = system('which mencoder'); -if status - error('%s: mencoder is needed to generate the movie.',upper(mfilename)); -else - cmd = sprintf(['mencoder mf://%s/%s*.png -mf fps=25:type=png', ... - ' -ovc lavc -lavcopts vcodec=mpeg4:mbd=2:trell -oac copy -o %s'],... - directory,pattern,outfile); - system(cmd); -end +function generate_movie(outfile,directory,pattern) +%GENERATE_MOVIE movie from given png files +% +% Usage: generate_movie(outfile,[[directory],pattern]) +% +% Input parameters: +% outfile - file name for the movie +% directory - dir containing the png files +% pattern - starting pattern of the png files to use +% +% GENERATE_MOVIE(outfile,directory,pattern) generates a movie and stores it +% in outfile. To produce the movie all png files starting with pattern in the +% given directory are processed. If no pattern is given, all png files are +% used. +% +% See also: plot_sound_field, movie_sound_field_mono_wfs + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 3; +narginchk(nargmin,nargmax); +if ~exist('directory','var') + directory = pwd; +end +if ~exist('pattern','var') + pattern = ''; +end +isargchar(outfile,pattern); +isargdir(directory); + + +%% ===== Movie =========================================================== +% Generate a movie from the png files with MEncoder +status1 = system('which mencoder > /dev/null'); +status2 = system('which avconv > /dev/null'); +if status1 & status2 + error('%s: mencoder or avconv is needed to generate the movie.', ... + upper(mfilename)); +else + if ~status1 + cmd = sprintf(['mencoder mf://%s/%s*.png -mf fps=25:type=png', ... + ' -ovc lavc -lavcopts vcodec=mpeg4:mbd=2:trell ', ... + '-oac copy -o %s'],... + directory,pattern,outfile); + else + cmd = sprintf(['avconv -f image2 -r 25 -i %s/%s_%%04d.png ', ... + '-c:v libx264 -crf 19 %s'], ... + directory,pattern,outfile); + end + system(cmd); +end diff --git a/SFS_plotting/gp_draw_loudspeakers.gnu b/SFS_plotting/gp_draw_loudspeakers.gnu index 8076fddc..242cbe21 100644 --- a/SFS_plotting/gp_draw_loudspeakers.gnu +++ b/SFS_plotting/gp_draw_loudspeakers.gnu @@ -16,35 +16,32 @@ # see also: gp_set_loudspeakers #***************************************************************************** -# Copyright (c) 2010-2015 Quality & Usability Lab, together with * -# Assessment of IP-based Applications * -# Telekom Innovation Laboratories, TU Berlin * -# Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +# The MIT License (MIT) * # * -# Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -# Universitaet Rostock * -# Richard-Wagner-Strasse 31, 18119 Rostock * +# Copyright (c) 2010-2019 SFS Toolbox Developers * # * -# This file is part of the Sound Field Synthesis-Toolbox (SFS). * +# Permission is hereby granted, free of charge, to any person obtaining a * +# copy of this software and associated documentation files (the "Software"), * +# to deal in the Software without restriction, including without limitation * +# the rights to use, copy, modify, merge, publish, distribute, sublicense, * +# and/or sell copies of the Software, and to permit persons to whom the * +# Software is furnished to do so, subject to the following conditions: * # * -# The SFS 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 3 of the License, or (at your option) * -# any later version. * +# The above copyright notice and this permission notice shall be included in * +# all copies or substantial portions of the Software. * # * -# The SFS 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. * +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +# DEALINGS IN THE SOFTWARE. * # * -# You should have received a copy of the GNU General Public License along * -# with this program. If not, see . * +# The SFS Toolbox allows to simulate and investigate sound field synthesis * +# methods like wave field synthesis or higher order ambisonics. * # * -# The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -# field synthesis methods like wave field synthesis or higher order * -# ambisonics. * -# * -# http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +# https://sfs.readthedocs.io sfstoolbox@gmail.com * #***************************************************************************** diff --git a/SFS_plotting/gp_load.m b/SFS_plotting/gp_load.m index e902ff7c..05ac35fd 100644 --- a/SFS_plotting/gp_load.m +++ b/SFS_plotting/gp_load.m @@ -1,5 +1,5 @@ function [x,y,header] = gp_load(file) -%GP_LOAD load x,y from a text file +%GP_LOAD loads x,y from a text file % % Usage: [x,y,header] = gp_load(file) % @@ -15,35 +15,32 @@ % in a Gnuplot compatible format %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** % FIXME: is this function doing what it should do? diff --git a/SFS_plotting/gp_save.m b/SFS_plotting/gp_save.m index 50641e68..b11d83fb 100644 --- a/SFS_plotting/gp_save.m +++ b/SFS_plotting/gp_save.m @@ -1,5 +1,5 @@ function gp_save(file,data,header) -% GP_SAVE save x,y as a text file in a Gnuplot compatible format +%GP_SAVE saves x,y as a text file in a Gnuplot compatible format % % Usage: gp_save(file,data,[header]) % @@ -8,41 +8,35 @@ function gp_save(file,data,header) % data - data matrix % header - header comment added before the data % -% GP_SAVE(file,data,header) saves the values data in a text file in a -% format useable by Gnuplot -% % See also: gp_save_matrix %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_plotting/gp_save_loudspeakers.m b/SFS_plotting/gp_save_loudspeakers.m index f27719e7..53b19575 100644 --- a/SFS_plotting/gp_save_loudspeakers.m +++ b/SFS_plotting/gp_save_loudspeakers.m @@ -1,5 +1,5 @@ function gp_save_loudspeakers(file,x0) -% GP_SAVE_LOUDSPEAKERS save x0 as a text file in a Gnuplot compatible format +%GP_SAVE_LOUDSPEAKERS saves x0 as a text file in a Gnuplot compatible format % % Usage: gp_save_loudspeakers(file,x0) % @@ -14,35 +14,32 @@ function gp_save_loudspeakers(file,x0) % See also: gp_save, gp_save_matrix %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_plotting/gp_save_matrix.m b/SFS_plotting/gp_save_matrix.m index 91f960f2..b399729e 100644 --- a/SFS_plotting/gp_save_matrix.m +++ b/SFS_plotting/gp_save_matrix.m @@ -1,50 +1,49 @@ function gp_save_matrix(file,x,y,M) -% GP_SAVE_MATRIX save x,y,M in the matrix binary format of Gnuplot +%GP_SAVE_MATRIX saves x,y,M in the matrix binary format of Gnuplot % % Usage: gp_save_matrix(file,x,y,M) % % Input parameters: % file - filename of the data file -% x - x axis values -% y - y axis values +% x - x axis values (vector or matrix) +% y - y axis values (vector or matrix) % M - matrix data size(M)=y,x % % GP_SAVE_MATRIX(file,x,y,M) saves the values of x,y and M in a binary matrix % format useable by Gnuplot, see % http://www.gnuplotting.org/manpage-gnuplot-4-6/#x1-372000III for details. +% If x,y are provided as matrices as, for example, they are returned by any +% sound_field_*() function, x(1,:) and y(:,1) will be used. % % See also: gp_save %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** @@ -53,12 +52,15 @@ function gp_save_matrix(file,x,y,M) nargmax = 4; narginchk(nargmin,nargmax); isargchar(file); -isargvector(x,y); +isargnumeric(x,y); isargmatrix(M); %% ===== Computation ===================================================== - +% Gnuplot can not handle arbritrary grids, so we extract the first row and first +% column instead +if is_dim_custom(x), x = x(1,:); end +if is_dim_custom(y), y = y(:,1); end % Check if the data has the right format [ly,lx] = size(M); if lx~=length(x) || ly~=length(y) diff --git a/SFS_plotting/gp_set_head.gnu b/SFS_plotting/gp_set_head.gnu index f4170eb4..32580709 100644 --- a/SFS_plotting/gp_set_head.gnu +++ b/SFS_plotting/gp_set_head.gnu @@ -14,35 +14,32 @@ # see also: gp_set_loudspeaker #***************************************************************************** -# Copyright (c) 2010-2015 Quality & Usability Lab, together with * -# Assessment of IP-based Applications * -# Telekom Innovation Laboratories, TU Berlin * -# Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +# The MIT License (MIT) * # * -# Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -# Universitaet Rostock * -# Richard-Wagner-Strasse 31, 18119 Rostock * +# Copyright (c) 2010-2019 SFS Toolbox Developers * # * -# This file is part of the Sound Field Synthesis-Toolbox (SFS). * +# Permission is hereby granted, free of charge, to any person obtaining a * +# copy of this software and associated documentation files (the "Software"), * +# to deal in the Software without restriction, including without limitation * +# the rights to use, copy, modify, merge, publish, distribute, sublicense, * +# and/or sell copies of the Software, and to permit persons to whom the * +# Software is furnished to do so, subject to the following conditions: * # * -# The SFS 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 3 of the License, or (at your option) * -# any later version. * +# The above copyright notice and this permission notice shall be included in * +# all copies or substantial portions of the Software. * # * -# The SFS 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. * +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +# DEALINGS IN THE SOFTWARE. * # * -# You should have received a copy of the GNU General Public License along * -# with this program. If not, see . * +# The SFS Toolbox allows to simulate and investigate sound field synthesis * +# methods like wave field synthesis or higher order ambisonics. * # * -# The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -# field synthesis methods like wave field synthesis or higher order * -# ambisonics. * -# * -# http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +# https://sfs.readthedocs.io sfstoolbox@gmail.com * #***************************************************************************** diff --git a/SFS_plotting/gp_set_loudspeaker.gnu b/SFS_plotting/gp_set_loudspeaker.gnu index 2d9c05b6..fe45a9e6 100644 --- a/SFS_plotting/gp_set_loudspeaker.gnu +++ b/SFS_plotting/gp_set_loudspeaker.gnu @@ -17,35 +17,32 @@ # see also: gp_draw_loudspeakers, gp_set_head #***************************************************************************** -# Copyright (c) 2010-2015 Quality & Usability Lab, together with * -# Assessment of IP-based Applications * -# Telekom Innovation Laboratories, TU Berlin * -# Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +# The MIT License (MIT) * # * -# Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -# Universitaet Rostock * -# Richard-Wagner-Strasse 31, 18119 Rostock * +# Copyright (c) 2010-2019 SFS Toolbox Developers * # * -# This file is part of the Sound Field Synthesis-Toolbox (SFS). * +# Permission is hereby granted, free of charge, to any person obtaining a * +# copy of this software and associated documentation files (the "Software"), * +# to deal in the Software without restriction, including without limitation * +# the rights to use, copy, modify, merge, publish, distribute, sublicense, * +# and/or sell copies of the Software, and to permit persons to whom the * +# Software is furnished to do so, subject to the following conditions: * # * -# The SFS 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 3 of the License, or (at your option) * -# any later version. * +# The above copyright notice and this permission notice shall be included in * +# all copies or substantial portions of the Software. * # * -# The SFS 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. * +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +# DEALINGS IN THE SOFTWARE. * # * -# You should have received a copy of the GNU General Public License along * -# with this program. If not, see . * +# The SFS Toolbox allows to simulate and investigate sound field synthesis * +# methods like wave field synthesis or higher order ambisonics. * # * -# The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -# field synthesis methods like wave field synthesis or higher order * -# ambisonics. * -# * -# http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +# https://sfs.readthedocs.io sfstoolbox@gmail.com * #***************************************************************************** diff --git a/SFS_plotting/norm_sound_field.m b/SFS_plotting/norm_sound_field.m new file mode 100644 index 00000000..55a95a8c --- /dev/null +++ b/SFS_plotting/norm_sound_field.m @@ -0,0 +1,83 @@ +function P = norm_sound_field(P,conf) +%NORM_SOUND_FIELD normalizes the sound field +% +% Usage: P = norm_sound_field(P,conf) +% +% Input parameters: +% P - sound field +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% P - normalized sound field +% +% NORM_SOUND_FIELD(P,conf) normalizes the given sound field P. This depends on +% the conf.plot.normalisation setting. It can be one of the following: +% 'auto' - if the given absolute sound field value at the center is +% > 0.3 it uses automatically 'center', otherwise it uses 'max' +% 'center' - normalises to center of sound field == 1 +% 'max' - normalises to max of sound field == 1 +% +% See also: plot_sound_field + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ==================================== +nargmin = 2; +nargmax = 2; +narginchk(nargmin,nargmax); +isargnumeric(P); +isargstruct(conf); + + +%% ===== Configuration =================================================== +method = conf.plot.normalisation; + + +%% ===== Computation ===================================================== +if strcmp('auto',method) + % If sound field at center > 0.3 normalise to center sound field == 1, + % otherwise normalise to max sound field == 1 + if abs(P(round(end/2),round(end/2)))>0.3 + method = 'center'; + else + method = 'max'; + end +end +if strcmp('center',method) + % Center of sound field == 1 + P = P/max(abs(P(round(end/2),round(end/2)))); +elseif strcmp('max',method) + % Max of sound field == 1 + P = P/max(abs(P(:))); +else + error(['%s: conf.plot.normalisation has to be ''auto'', ''center'' or ', ... + '''max''.'],upper(mfilename)); +end diff --git a/SFS_plotting/plot_sound_field.m b/SFS_plotting/plot_sound_field.m index 095e4a0a..8714a171 100644 --- a/SFS_plotting/plot_sound_field.m +++ b/SFS_plotting/plot_sound_field.m @@ -1,71 +1,63 @@ -function plot_sound_field(P,x,y,z,x0,conf) -%PLOT_SOUND_FIELD plot the given sound field +function plot_sound_field(P,X,Y,Z,x0,conf) +%PLOT_SOUND_FIELD plots a sound field % -% Usage: plot_sound_field(P,x,y,z,[x0],[conf]) +% Usage: plot_sound_field(P,X,Y,Z,[x0],conf) % % Input parameters: % P - matrix containing the sound field in the format P = P(y,x) +% X - x-axis / m; single value or [xmin,xmax] or nD-array +% Y - y-axis / m; single value or [ymin,ymax] or nD-array +% Z - z-axis / m; single value or [zmin,zmax] or nD-array % x,y,z - vectors for the x-, y- and z-axis % x0 - matrix containing the secondary source positions to plot. % Default: plot no secondary sources -% conf - optional configuration struct (see SFS_config) +% conf - configuration struct (see SFS_config) % -% PLOT_SOUND_FIELD(P,x,y,z,x0,conf) plots the sound field P in dependence -% of the axes that are not singleton. To calculate what axes these are you -% have to provide all three of them. For a given set x0 of secondary sources -% the secondary sources are added as dots or loudspeaker symbols depending on -% your setting of conf.plot.realloudspeakers. +% PLOT_SOUND_FIELD(P,X,Y,Z,x0,conf) plots the sound field P in dependence of +% the axes that are non-singleton. You have to provide the axes in the same +% syntax as for the sound field functions. For a given set x0 of secondary +% sources the secondary sources are added as dots or loudspeaker symbols +% depending on your setting of conf.plot.realloudspeakers. % -% See also: sound_field_mono, sound_field_imp +% See also: sound_field_mono, sound_field_imp, draw_loudspeakers %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 4; +nargmin = 5; nargmax = 6; narginchk(nargmin,nargmax); -isargvector(x,y,z); -isargnumeric(P); -if nargin==nargmax-1 - if isstruct(x0) - conf = x0; - x0 = []; - else - conf = SFS_config; - end -elseif nargin==nargmax-2 - conf = SFS_config; +isargnumeric(X,Y,Z,P); +if nargin> [P,x,y,z,x0] = sound_field_mono_wfs(X,Y,Z,[0 -1 0],'pw',1000,conf); +% >> plot_sound_field(P,x,y,z,x0,conf) +% Instead you should do +% >> plot_sound_field(P,X,Y,Z,x0,conf) +% if X,Y,Z are a non-custom grid. +is_custom = is_dim_custom(X,Y,Z); + +if any(is_custom) && sum(is_custom) < sum(dimensions) + error(['%s: it is not possible to combine an axis with regular sampled ' ... + 'grid with an axis with custom grid']); +end + +if ~any(dimensions) error(['%s: you have only one point in the sound field. ', ... 'Omitting the plotting.'],upper(mfilename)); +elseif ~dimensions(1) && ~dimensions(2) + p.xlabel = 'z / m'; elseif ~dimensions(1) - % FIXME: in order to work with gnuplot the label should be printed - % with the extra function, which can handle if the output should be - % LaTeX or something else - %str_xlabel = print_label('y','m',conf); p.xlabel = 'y / m'; p.ylabel = 'z / m'; elseif ~dimensions(2) @@ -118,23 +118,36 @@ function plot_sound_field(P,x,y,z,x0,conf) p.xlabel = 'x / m'; p.ylabel = 'y / m'; else - % FIXME: in this case every three axis should be plotted and we should - % switch to use splot or some other alternativ to plot it in 3D. - to_be_implemented(mfilename); + p.xlabel = 'x / m'; + p.ylabel = 'y / m'; + p.zlabel = 'z / m'; end -if(p.usedb) - % Check if we have any activity in the sound field - if max(abs(P(:)))~=0 - % For the dB case scale the signal maximum to 0 dB - %P = P./max(abs(P(:))); - else - % If we have only zeros in the sound field set the field to eps to avoid - % problems with log(0). +% Remove Inf values from sound field +P(isinf(P)) = NaN; + +% Normalisation +if p.usenormalisation + P = norm_sound_field(P,conf); +end + +if p.usedb + % If we have only zeros in the sound field set the field to eps to avoid + % problems with log(0). + if max(abs(P(:)))==0 P(:) = eps; end - % Change default colormap to chromajs - conf.plot.colormap = 'chromajs'; + % Change default colormap to yellowred + if strcmp('default',p.colormap) + conf.plot.colormap = 'yellowred'; + end + % Calculate sound pressure level in dB + P = 20*log10(abs(P)); + if p.usenormalisation + P = P - max(P(:)); % ensure 0 dB max for dB plots + end +else + P = real(P); end % Check if we should plot loudspeakers symbols @@ -144,7 +157,7 @@ function plot_sound_field(P,x,y,z,x0,conf) p.realloudspeakers = 0; end -% set the color bar axis to default values if not given otherwise +% Set the color bar axis to default values if not given otherwise if p.caxis, else if p.usedb p.caxis = [-45,0]; @@ -153,7 +166,6 @@ function plot_sound_field(P,x,y,z,x0,conf) end end - %% ===== Plotting ======================================================== % Create a new figure @@ -161,54 +173,64 @@ function plot_sound_field(P,x,y,z,x0,conf) % Set size figsize(p.size(1),p.size(2),p.size_unit); -% Scale dB value if needed -if p.usedb - P_dB = 20*log10(abs(P)); - if usenormalisation - P_dB = P_dB - max(P_dB(:)); +switch sum(dimensions) + case 1 + % === 1D Plot ==== + if any(is_custom) % custom grid + plot(x1,P,'o','MarkerFaceColor','blue','MarkerSize',3) + else % regular grid + x1 = linspace(x1(1),x1(2),conf.resolution); + plot(x1,P); end -end - -% Plotting -if sum(dimensions)==1 % singleton dimension + xlabel(p.xlabel); if p.usedb - plot(x1,P_dB); - xlabel(p.xlabel); ylabel('Amplitude / dB'); else - plot(x1,real(P)); - xlabel(p.xlabel); ylabel('Amplitude'); end -else - - if p.usedb - % Plot the amplitude of the sound field in dB - imagesc(x1,x2,P_dB,p.caxis); - else - % Plot the sound field - imagesc(x1,x2,real(P),p.caxis); + case 2 + % === 2D Plot ==== + if any(is_custom) % custom grid + point_size = []; + if isoctave, point_size = 2; end % fix scatter plot point size for Octave + scatter(x1(:),x2(:),point_size,limit_colors(P,p.caxis),'filled'); + else % regular grid + imagesc(x1,x2,P,p.caxis); end - % Add color bar set_colorbar(conf); - % Set the y direction in normal mode (imagesc uses the reverse mode by % default) turn_imagesc; - % Set the axis to use the same amount of space for the same length (m) axis image; % Labels etc. for the plot xlabel(p.xlabel); ylabel(p.ylabel); % Add loudspeaker to the plot - %x0(:,1:2) = x0(:,2:3); if p.loudspeakers % && dimensions(1) && dimensions(2) hold on; draw_loudspeakers(x0,dimensions,conf); hold off; end + case 3 + if ~any(is_custom) + [x1,x2,x3] = xyz_grid(X,Y,Z,conf); + end + % === 3D Plot ==== + point_size = []; + if isoctave, point_size = 5; end % fix scatter plot point size for Octave + scatter3(x1(:),x2(:),x3(:),point_size,limit_colors(P,p.caxis),'filled'); + % Fix perspective of plot in Matlab (https://stackoverflow.com/q/17447404) + set(gcf,'renderer','opengl'); + % Add color bar + set_colorbar(conf); + % Set the axis to use the same amount of space for the same length (m) + axis image; + % Labels etc. for the plot + xlabel(p.xlabel); + ylabel(p.ylabel); + zlabel(p.zlabel); end % Save as file @@ -217,3 +239,20 @@ function plot_sound_field(P,x,y,z,x0,conf) elseif ~isempty(p.file) && strcmp('eps',p.file(end-2:end)) print_eps(p.file); end +end + + +%% ===== Helper functions ================================================ +function P = limit_colors(P,caxis) + % Limits the number of different values in P to 64. + % This speeds up plotting with the scatter function in octave, see: + % https://savannah.gnu.org/bugs/?40663 + % + number_of_colors = 64; + % First apply the caxis values + P = min(caxis(2),max(caxis(1),P(:))); + % Transform to [0...64] and transform to integer + P = fix(number_of_colors/abs(max(P(:))-min(P(:))) .* (P+abs(min(P(:))))); + % Transform back to [caxis(1)...caxis(2)] + P = abs(caxis(2)-caxis(1))/number_of_colors .* P + caxis(1); +end diff --git a/SFS_plotting/print_eps.m b/SFS_plotting/print_eps.m index 562133b1..3ec16422 100644 --- a/SFS_plotting/print_eps.m +++ b/SFS_plotting/print_eps.m @@ -1,56 +1,51 @@ -function print_eps(outfile) -%PRINT_EPS stores the figure as eps file -% -% Usage: print_eps(outfile) -% -% Input options: -% outfile - file name to store the figure -% -% PRINT_EPS(outfile) prints the figure as eps file. -% -% See also: plot_sound_field, print_png - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameter ===================================== -nargmin = 1; -nargmax = 1; -narginchk(nargmin,nargmax); - - -%% ===== Main ============================================================ -% Font type -set_font_type('Arial'); -print(outfile,'-depsc2','-r150'); -close; +function print_eps(outfile) +%PRINT_EPS stores the figure as eps file +% +% Usage: print_eps(outfile) +% +% Input parameters: +% outfile - file name to store the figure +% +% See also: plot_sound_field, print_png + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameter ===================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Main ============================================================ +% Font type +set_font_type('Arial'); +print(outfile,'-depsc2','-r150'); +close; diff --git a/SFS_plotting/print_png.m b/SFS_plotting/print_png.m index fceb06b3..561b18b0 100644 --- a/SFS_plotting/print_png.m +++ b/SFS_plotting/print_png.m @@ -1,56 +1,53 @@ -function print_png(outfile) -%PRINT_PNG stores a figure as png file -% -% Usage: print_png(outfile) -% -% Input options: -% outfile - file name to store the figure -% -% PRINT_EPS(outfile) plots the last figure as an eps file to outfile. -% -% See also: plot_sound_field, print_png - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameter ===================================== -nargmin = 1; -nargmax = 1; -narginchk(nargmin,nargmax); - - -%% ===== Main ============================================================ -% Font type -set_font_type('Arial'); -print(outfile,'-dpng','-r150'); -close; +function print_png(outfile) +%PRINT_PNG stores a figure as png file +% +% Usage: print_png(outfile) +% +% Input parameters: +% outfile - file name to store the figure +% +% See also: plot_sound_field, print_png + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameter ===================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Main ============================================================ +% Font type +set_font_type('Arial'); +pause(0.2); +print('-r150','-opengl','-dpng',outfile); +pause(0.2); +close; diff --git a/SFS_plotting/set_colorbar.m b/SFS_plotting/set_colorbar.m index d35fb7e9..ebd51d80 100644 --- a/SFS_plotting/set_colorbar.m +++ b/SFS_plotting/set_colorbar.m @@ -1,85 +1,78 @@ -function set_colorbar(conf) -%SET_COLORBAR draws a color bar to the plot -% -% Usage: set_colorbar([conf]) -% -% Input options: -% conf - optional configuration struct (see SFS_config) -% -% SET_COLORBAR() drwas a color bar on the figure and sets the map to the color -% specified in conf.plot.colormap. -% -% See also: plot_sound_field, set_colormap - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameter ===================================== -nargmin = 0; -nargmax = 1; -narginchk(nargmin,nargmax); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameter ===================================== -nargmin = 0; -nargmax = 1; -narginchk(nargmin,nargmax); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 1; -narginchk(nargmin,nargmax); -isargpositivescalar(fontsize) - - -%% ===== Apply settings ================================================== -% Get handle for active figure -h=gca; -% Set the font size for the axis tics -set(h,'FontSize',fontsize); -% set the font size for all text strings -set(findall(h,'type','text'),'FontSize',fontsize); -% FIXME: the following produces an segmentation fault under Octave -% Set the font size for colorbar tics -%h=colorbar; -%set(h,'FontSize',fontsize); +function set_font_size(fontsize) +%SET_FONT_SIZE sets the figures font size +% +% Usage: set_font_size(fontsize) +% +% Input parameters: +% fontsize - font size +% +% See also: set_font_type, print_png + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); +isargpositivescalar(fontsize) + + +%% ===== Apply settings ================================================== +% Get handle for active figure +h=gca; +% Set the font size for the axis tics +set(h,'FontSize',fontsize); +% set the font size for all text strings +set(findall(h,'type','text'),'FontSize',fontsize); +% FIXME: the following produces an segmentation fault under Octave +% Set the font size for colorbar tics +%h=colorbar; +%set(h,'FontSize',fontsize); diff --git a/SFS_plotting/set_font_type.m b/SFS_plotting/set_font_type.m index 95863563..add60a95 100644 --- a/SFS_plotting/set_font_type.m +++ b/SFS_plotting/set_font_type.m @@ -1,63 +1,58 @@ -function set_font_type(font) -%SET_FONT_TYPE sets the figures font type -% -% Usage: set_font_type(font) -% -% Input options: -% font - font type name -% -% SET_FONT_TYPE(font) sets the font of the active figure to the given type. -% -% See also: set_font_size, print_png - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 1; -nargmax = 1; -narginchk(nargmin,nargmax); -isargchar(font) - - -%% ===== Apply settings ================================================== -% Get handle for active figure -h=gca; -% Set the font type for the axis tics -set(h,'FontName',font); -% set the font type for all text strings -set(findall(h,'type','text'),'FontName',font); -% FIXME: the following produces an segmentation fault under Octave -% Set the font type for colorbar tics -%h=colorbar; -%set(h,'FontName',font); +function set_font_type(font) +%SET_FONT_TYPE sets the figures font type +% +% Usage: set_font_type(font) +% +% Input parameters: +% font - font type name +% +% See also: set_font_size, print_png + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); +isargchar(font) + + +%% ===== Apply settings ================================================== +% Get handle for active figure +h=gca; +% Set the font type for the axis tics +set(h,'FontName',font); +% set the font type for all text strings +set(findall(h,'type','text'),'FontName',font); +% FIXME: the following produces an segmentation fault under Octave +% Set the font type for colorbar tics +%h=colorbar; +%set(h,'FontName',font); diff --git a/SFS_plotting/turn_imagesc.m b/SFS_plotting/turn_imagesc.m index 60c09348..f0c12e99 100644 --- a/SFS_plotting/turn_imagesc.m +++ b/SFS_plotting/turn_imagesc.m @@ -2,35 +2,32 @@ function turn_imagesc() %TURN_IMAGES corrects the Y axis for imagesc plots %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** diff --git a/SFS_ssr/ssr_brs.m b/SFS_ssr/ssr_brs.m index f773b67e..87904fa3 100644 --- a/SFS_ssr/ssr_brs.m +++ b/SFS_ssr/ssr_brs.m @@ -1,91 +1,83 @@ -function brs = ssr_brs(X,phi,x0,d,irs,conf) -%SSR_BRS generates a binaural room scanning (BRS) set for use with the -%SoundScape Renderer -% -% Usage: brs = ssr_brs(X,phi,x0,d,irs,[conf]) -% -% Input parameters: -% X - listener position / m -% phi - listener direction [head orientation] / rad -% x0 - secondary sources -% d - corresponding driving signals -% irs - IR data set for the second sources -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% brs - conf.N x 2*nangles matrix containing all impulse responses (2 -% channels) for every angles of the BRS set -% -% SSR_BRS(X,phi,x0,d,irs,conf) prepares a BRS set for the given secondary -% sources and its driving signals for the given listener position. -% One way to use this BRS set is using the SoundScapeRenderer (SSR), see -% http://spatialaudio.net/ssr/ -% -% See also: ssr_brs_wfs, ssr_brs_nfchoa, ir_generic - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 5; -nargmax = 6; -narginchk(nargmin,nargmax); -isargposition(X); -isargsecondarysource(x0); -isargmatrix(d); -isargscalar(phi); -check_irs(irs); -if nargin Y0 => focused source] / m -% src - source type: 'pw' - plane wave -% 'ps' - point source -% 'fs' - focused source -% irs - IR data set for the second sources -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% brs - conf.N x 2*nangles matrix containing all impulse responses (2 -% channels) for every angles of the BRS set -% -% SSR_BRS_NFCHOA(X,phi,xs,src,irs,conf) prepares a BRS set for a virtual source -% at position xs for a virtual loudspeaker array driven by nearfield -% compensated higher order Ambisonics (NFC-HOA) and the given listener position. -% One way to use this BRS set is using the SoundScapeRenderer (SSR), see -% http://spatialaudio.net/ssr/ -% -% See also: ir_generic, ir_nfchoa, driving_function_imp_nfchoa - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 5; -nargmax = 6; -narginchk(nargmin,nargmax); -isargposition(X); -isargxs(xs); -isargscalar(phi); -check_irs(irs); -if nargin Y0 => focused source] / m +% src - source type: 'pw' - plane wave +% 'ps' - point source +% 'fs' - focused source +% irs - impulse response data set for the second sources +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% brs - conf.N x 2*nangles matrix containing all impulse responses (2 +% channels) for every angles of the BRS set +% delay - delay added by driving function / s +% +% SSR_BRS_NFCHOA(X,phi,xs,src,irs,conf) prepares a BRS set for a virtual +% source at position xs for a virtual loudspeaker array driven by +% nearfield compensated higher order Ambisonics (NFC-HOA) and the given +% listener position. One way to use this BRS set is using the +% SoundScapeRenderer (SSR), see http://spatialaudio.net/ssr/ +% +% See also: ir_generic, ir_nfchoa, driving_function_imp_nfchoa + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 6; +nargmax = 6; +narginchk(nargmin,nargmax); +isargposition(X); +isargxs(xs); +isargscalar(phi); +isargstruct(conf); + + +%% ===== Computation ===================================================== +% Secondary sources +x0 = secondary_source_positions(conf); +% Calculate driving function +[d,~,delay] = driving_function_imp_nfchoa(x0,xs,src,conf); +% Calculate brs set +brs = ssr_brs(X,phi,x0,d,irs,conf); diff --git a/SFS_ssr/ssr_brs_point_source.m b/SFS_ssr/ssr_brs_point_source.m index 0b7b52d9..c8f08bdc 100644 --- a/SFS_ssr/ssr_brs_point_source.m +++ b/SFS_ssr/ssr_brs_point_source.m @@ -1,74 +1,66 @@ -function brs = ssr_brs_point_source(X,phi,xs,irs,conf) -%SSR_BRS_POINT_SOURCE generates a binaural room scanning (BRS) set for use with -%the SoundScape Renderer -% -% Usage: brs = ssr_brs_point_source(X,phi,xs,irs,[conf]) -% -% Input parameters: -% X - listener position / m -% phi - listener direction [head orientation] / rad -% xs - source position / m -% irs - IR data set for the second sources -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% brs - conf.N x 2*nangles matrix containing all impulse responses (2 -% channels) for every angles of the BRS set -% -% SSR_BRS_POINT_SOURCE(X,phi,xs,irs,conf) prepares a BRS set for -% a reference source (single point source) for the given listener -% position. -% One way to use this BRS set is using the SoundScapeRenderer (SSR), see -% http://spatialaudio.net/ssr/ -% -% See also: ir_generic, ir_point_source, get_ir - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 4; -nargmax = 5; -narginchk(nargmin,nargmax); -isargposition(X); -isargxs(xs); -isargscalar(phi); -check_irs(irs); -if nargin Y0 => focused source] / m -% src - source type: 'pw' - plane wave -% 'ps' - point source -% 'fs' - focused source -% irs - IR data set for the second sources -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% brs - conf.N x 2*nangles matrix containing all impulse responses (2 -% channels) for every angles of the BRS set -% -% SSR_BRS_WFS(X,phi,xs,src,irs,conf) prepares a BRS set for a virtual source -% at xs for WFS and the given listener position. -% One way to use this BRS set is using the SoundScapeRenderer (SSR), see -% http://spatialaudio.net/ssr/ -% -% See also: ir_generic, ir_wfs, driving_function_imp_wfs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 5; -nargmax = 6; -narginchk(nargmin,nargmax); -isargposition(X); -isargxs(xs); -isargscalar(phi); -check_irs(irs); -if nargin Y0 => focused source] / m +% src - source type: 'pw' - plane wave +% 'ps' - point source +% 'fs' - focused source +% irs - impulse response data set for the secondary sources +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% brs - conf.N x 2*nangles matrix containing all impulse responses (2 +% channels) for every angles of the BRS set +% delay - delay added by driving function / s +% +% SSR_BRS_WFS(X,phi,xs,src,irs,conf) prepares a BRS set for a virtual source +% at xs for WFS and the given listener position. One way to use this BRS set +% is using the SoundScapeRenderer (SSR), see http://spatialaudio.net/ssr/ +% +% See also: ir_generic, ir_wfs, driving_function_imp_wfs + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 6; +nargmax = 6; +narginchk(nargmin,nargmax); +isargposition(X); +isargxs(xs); +isargscalar(phi); +isargstruct(conf); + + +%% ===== Computation ===================================================== +% Secondary sources +x0 = secondary_source_positions(conf); +x0 = secondary_source_selection(x0,xs,src); +x0 = secondary_source_tapering(x0,conf); +% Calculate driving function +[d,~,~,delay] = driving_function_imp_wfs(x0,xs,src,conf); +% Calculate brs set +brs = ssr_brs(X,phi,x0,d,irs,conf); diff --git a/SFS_ssr/ssr_generic_nfchoa.m b/SFS_ssr/ssr_generic_nfchoa.m index e281b234..0ba8390d 100644 --- a/SFS_ssr/ssr_generic_nfchoa.m +++ b/SFS_ssr/ssr_generic_nfchoa.m @@ -1,77 +1,70 @@ -function ir = ssr_generic_nfchoa(xs,src,conf) -%SSR_GENERIC_NFCHOA generate an impulse response for the generic renderer of the -%SoundScape Renderer -% -% Usage: ir = ssr_generic_nfchoa(xs,src,[conf]) -% -% Input parameters: -% xs - virtual source position / m -% src - source type: 'pw' -plane wave -% 'ps' - point source -% 'fs' - focused source -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% ir - impulse response for the desired loudspeaker array -% -% GENERIC_NFCHOA(xs,src,conf) calculates an impulse response for a virtual -% source at xs for the loudspeakers of a NFC-HOA array. Every loudspeaker of -% the array is represented by one column in the impulse response. -% For the generic renderer it is of importance to know what position the first -% loudspeaker of your array will have. For example, the included circular -% array has its first loudspeaker at phi=0deg which is on the x-axis. If you -% have another setup you have to provide it with conf.secondary_sources.x0. -% -% -% See also: generic_wfs, brs_nfchoa, driving_function_imp_nfchoa - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 2; -nargmax = 3; -narginchk(nargmin,nargmax); -isargxs(xs); -isargchar(src); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 2; -nargmax = 3; -narginchk(nargmin,nargmax); -isargxs(xs); -isargchar(src); -if nargin. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** -%% ===== Configuration =================================================== -printbanner = false; +%% ===== Checking of input parameters =================================== +nargmin = 0; +nargmax = 1; +narginchk(nargmin,nargmax); +if nargin==0 + printbanner = false; +end %% ===== Adding Path's =================================================== @@ -64,10 +70,15 @@ function SFS_start() addpath([basepath,'/SFS_ir']); addpath([basepath,'/SFS_monochromatic']); addpath([basepath,'/SFS_monochromatic/driving_functions_mono']); + addpath([basepath,'/SFS_monochromatic/circexp_mono']); + addpath([basepath,'/SFS_monochromatic/pwd_mono']); addpath([basepath,'/SFS_plotting']); + addpath([basepath,'/SFS_plotting/colormaps']); addpath([basepath,'/SFS_ssr']); addpath([basepath,'/SFS_time_domain']); addpath([basepath,'/SFS_time_domain/driving_functions_imp']); + addpath([basepath,'/SFS_time_domain/circexp_imp']); + addpath([basepath,'/SFS_time_domain/pwd_imp']); addpath([basepath,'/SFS_HRTF_extrapolation']); addpath([basepath,'/validation']); if isoctave @@ -82,10 +93,15 @@ function SFS_start() path(path,[basepath,'/SFS_ir']); path(path,[basepath,'/SFS_monochromatic']); path(path,[basepath,'/SFS_monochromatic/driving_functions_mono']); + path(path,[basepath,'/SFS_monochromatic/circexp_mono']); + path(path,[basepath,'/SFS_monochromatic/pwd_mono']); path(path,[basepath,'/SFS_plotting']); + path(path,[basepath,'/SFS_plotting/colormaps']); path(path,[basepath,'/SFS_ssr']); path(path,[basepath,'/SFS_time_domain']); path(path,[basepath,'/SFS_time_domain/driving_functions_imp']); + path(path,[basepath,'/SFS_time_domain/circexp_imp']); + path(path,[basepath,'/SFS_time_domain/pwd_imp']); path([basepath,'/SFS_HRTF_extrapolation']); path(path,[basepath,'/validation']); if isoctave @@ -96,6 +112,19 @@ function SFS_start() %% ===== Banner ========================================================== if(printbanner) - printf('SFS %1.1f successfully initialized.\n',SFS_version); + if ~usejava('desktop') % Looks only nice in console + banner = sprintf( ... + [' ▄▄\n', ... + ' ▄█▀▀ █▄ ▄█▀▀ Sound Field Synthesis Toolbox %s\n', ... + ' ▄▄█▀ █ ▄▄█▀ https://sfs-matlab.readthedocs.io\n\n'], ... + SFS_version); + else + banner = sprintf( ... + ['\n', ... + ' Sound Field Synthesis Toolbox %s\n', ... + ' https://sfs-matlab.readthedocs.io\n\n'], ... + SFS_version); + end + fprintf(banner); end diff --git a/SFS_stop.m b/SFS_stop.m index 4281946e..a84342c4 100644 --- a/SFS_stop.m +++ b/SFS_stop.m @@ -9,35 +9,32 @@ function SFS_stop() % See also: SFS_start, SFS_config, SFS_version %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** @@ -68,6 +65,7 @@ function SFS_stop() rmpath([basepath,'/SFS_monochromatic']); rmpath([basepath,'/SFS_monochromatic/driving_functions_mono']); rmpath([basepath,'/SFS_plotting']); + rmpath([basepath,'/SFS_plotting/colormaps']); rmpath([basepath,'/SFS_ssr']); rmpath([basepath,'/SFS_time_domain']); rmpath([basepath,'/SFS_time_domain/driving_functions_imp']); diff --git a/SFS_time_domain/circexp_imp/circexp_imp_ps.m b/SFS_time_domain/circexp_imp/circexp_imp_ps.m new file mode 100644 index 00000000..f4f18fb6 --- /dev/null +++ b/SFS_time_domain/circexp_imp/circexp_imp_ps.m @@ -0,0 +1,131 @@ +function [pm,delay_offset] = circexp_imp_ps(xs,Nce,xq,fhp,conf) +%CIRCEXP_IMP_PS circular basis expansion of a point source in temporal domain +% +% Usage: [pm,delay_offset] = circexp_imp_ps(xs,Nce,xq,[fhp],conf) +% +% Input parameters: +% xs - position of point source / m [1 x 3] +% Nce - maximum order of circular basis expansion +% xq - optional expansion center / m [1 x 3] +% fhp - cut-off frequency of highpass for regularisation +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% pm - regular circular expansion coefficients in time domain +% for m = 0:Nce, [conf.N x Nce+1] +% delay_offset - additional added delay, so you can correct it +% +% See also: circexp_imp_pw + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 4; +nargmax = 5; +narginchk(nargmin,nargmax); +isargcoord(xq,xs); +isargpositivescalar(Nce); +if nargin == nargmin + conf = fhp; +else + isargpositivescalar(fhp); +end + + +%% ===== Configuration ================================================== +N = conf.N; +c = conf.c; +fs = conf.fs; + + +%% ===== Computation ===================================================== + +xs = xs - xq; % shift coordinates +[phis, rs] = cart2pol(xs(1),xs(2)); + +%------------------------------------------------------------------------------- +% Implementation of +% +% i^(|m|-m) +% p_m(t) = --------- IFT[ -ik h_|m|(k rs) ] e^(-im phis) e^(im phi0) +% 4pi +% +% with IFT being the inverse Fourier transform of the spherical Hankel function. +% The IFT is realised by an IIR-implementation using the Laplace domain (s) +% respresentation of the spherical Hankel function: +% _____ +% exp(-s tau) | | (s - z_n/tau) +% h_|m|(s tau) = i^|m| ----------- | | ------------- +% -i s tau n (s - p_n/tau) +% +% z_n and p_n are the zeros and poles of the Hankel function. tau = r_s/c. +%------------------------------------------------------------------------------- + +% === Linkwitz-Riley (LR) filter for stabilisation === +zlr = []; +plr = []; +klr = 1; +if Nce > 0 + if nargin == nargmin + warning('without highpass filtering the implementation is not stable'); + else + [zlr, plr, klr] = linkwitz_riley(ceil(Nce/2)*2, fhp/fs*2, 'high'); + end +end + +% Compute impulse responses for each mode m +pulse = dirac_imp(); +pm = [repmat(pulse,[1 Nce+1]); zeros(N-length(pulse),Nce+1)]; +% Negative m can be inferred from symmetry relations +for m=0:Nce + % === IIR-Implementation of Spherical Hankel function === + if m==0 % not supported by octave + zh = []; ph = []; kh=1; + else + [zh, ph] = sphbesselh_zeros(m); + % Bilinear transform to z-domain + if isoctave + [zh, ph, kh] = bilinear(zh*c/rs, ph*c/rs, 1, 1/fs); + else + [zh, ph, kh] = bilinear(zh*c/rs, ph*c/rs, 1, fs); + end + end + % === Apply Hankel + LR Filter to current mode === + % Zeros remaining after compensating the poles of Hankel function (ph) + zlr_comp = ones(length(zlr)-length(ph),1); + % Generate second-order-sections + [sos, g] = zp2sos([zlr_comp; zh], plr, klr*kh, 'down', 'none'); + % Filtering + pm(:,m+1) = sosfilt(sos, pm(:,m+1)).*g.*(1i).^m.*exp(-1i*m*phis); +end +pm = pm./(4*pi*rs); + +delay_offset = -rs/c; diff --git a/SFS_time_domain/circexp_imp/circexp_imp_pw.m b/SFS_time_domain/circexp_imp/circexp_imp_pw.m new file mode 100644 index 00000000..52237c9e --- /dev/null +++ b/SFS_time_domain/circexp_imp/circexp_imp_pw.m @@ -0,0 +1,72 @@ +function [pm,delay_offset] = circexp_imp_pw(npw,Nce,xq,conf) +%CIRCEXP_IMP_PW circular basis expansion of a plane wave in temporal domain +% +% Usage: [pm,delay_offset] = circexp_imp_pw(npw,Nce,xq,conf) +% +% Input parameters: +% npw - propagation direction of plane wave [1 x 3] +% Nce - maximum order of circular basis expansion +% xq - optional expansion center / m [1 x 3] +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% pm - regular circular expansion coefficients in time domain +% for m = 0:Nce, [conf.N x Nce+1] +% delay_offset - additional added delay, so you can correct it +% +% See also: circexp_imp_ps + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 4; +nargmax = 4; +narginchk(nargmin,nargmax); +isargcoord(xq,npw); +isargpositivescalar(Nce); +isargstruct(conf); + + +%% ===== Configuration ================================================== +N = conf.N; +c = conf.c; + + +%% ===== Computation ===================================================== +[phipw, ~] = cart2pol(npw(1),npw(2)); + +pulse = dirac_imp(); +% Compute impulse responses for each mode m +m = (0:Nce); +pm = (-1i).^m.*exp(-1i*phipw*m)*pulse; +pm = [pm; zeros(N-size(pm,1),Nce+1)]; + +delay_offset = -(xq*npw.')/c; diff --git a/SFS_time_domain/dirac_imp.m b/SFS_time_domain/dirac_imp.m index 8334a5c5..9e765d20 100644 --- a/SFS_time_domain/dirac_imp.m +++ b/SFS_time_domain/dirac_imp.m @@ -1,58 +1,53 @@ -function pulse = dirac_imp() -%DIRAC_IMP returns a pulse as stimulus for the imp driving functions -% -% Usage: pulse = dirac_imp() -% -% Output parameters: -% pulse - short pulse signal -% -% DIRAC_IMP() returns a 1 sample long dirac pulse. -% -% See also: hann_window, driving_function_imp_wfs, driving_function_imp_nfchoa - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking input parameters ======================================= -nargmin = 0; -nargmax = 0; -narginchk(nargmin,nargmax); - - -%% ===== Computation ===================================================== -% FIXME. maybe we should enable switching via a conf entry -% for simulation of a sound field the usage of a hann shaped pulse could be a -% better choice -%pulse = row_vector(hann_window(5,5,10)); -% For binaural simulations we should stick to a dirac pulse -pulse = 1; +function pulse = dirac_imp() +%DIRAC_IMP returns a 1 sample long dirac pulse +% +% Usage: pulse = dirac_imp() +% +% Output parameters: +% pulse - short pulse signal +% +% See also: hann_window, driving_function_imp_wfs, driving_function_imp_nfchoa + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking input parameters ======================================= +nargmin = 0; +nargmax = 0; +narginchk(nargmin,nargmax); + + +%% ===== Computation ===================================================== +% FIXME. maybe we should enable switching via a conf entry +% for simulation of a sound field the usage of a hann shaped pulse could be a +% better choice +%pulse = row_vector(hann_window(5,5,10)); +% For binaural simulations we should stick to a dirac pulse +pulse = 1; diff --git a/SFS_time_domain/driving_function_imp_localwfs.m b/SFS_time_domain/driving_function_imp_localwfs.m deleted file mode 100644 index 0cf7405f..00000000 --- a/SFS_time_domain/driving_function_imp_localwfs.m +++ /dev/null @@ -1,122 +0,0 @@ -function [d, x0, xv] = driving_function_imp_localwfs(x0,xs,src,conf) -%DRIVING_FUNCTION_IMP_LOCALWFS returns the driving signal d for local WFS -% -% Usage: [D, xv, x0] = driving_function_mono_localwfs(x0,xs,src,conf) -% -% Input parameters: -% x0 - position and direction of the secondary source / m [nx6] -% xs - position of virtual source or direction of plane -% wave / m [1x3] -% src - source type of the virtual source -% 'pw' - plane wave (xs is the direction of the -% plane wave in this case) -% 'ps' - point source -% 'ls' - line source -% 'fs' - focused source -% -% f - frequency of the monochromatic source / Hz -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% D - driving function signal [nx1] -% x0 - position, direction, and weights of the real secondary -% sources / m [nx7] -% xv - position, direction, and weights of the virtual secondary -% sources / m [mx7] -% -% References: -% S. Spors (2010) - "Local Sound Field Synthesis by Virtual Secondary -% Sources", 40th AES -% -% See also: plot_sound_field, sound_field_mono_wfs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargsecondarysource(x0); -isargxs(xs); -isargchar(src); -if nargin. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 3; +nargmin = 4; nargmax = 4; narginchk(nargmin,nargmax); isargsecondarysource(x0) isargxs(xs); isargchar(src); -if narginnls - % Check if we have a multiple of the order - if mod(size(d,2),nls)~=0 - conf_tmp = conf; - conf_tmp.nfchoa.order = []; - error(['%s: the given number of driving signals (%i) can not ', ... - 'be subsampled to %i secondary sources. Choose a NFC-HOA ', ... - 'order that is a multiple of %i.'], ... - upper(mfilename),size(d,2),nls,nfchoa_order(nls,conf_tmp)); - end - % Subsample d - ratio = size(d,2)/nls; - d = d(:,1:ratio:end); -% Subsample the secondary sources if we have fewer driving signals than -% secondary sources -elseif size(d,2). * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 3; +nargmin = 4; nargmax = 4; narginchk(nargmin,nargmax); isargsecondarysource(x0) isargxs(xs); isargchar(src); -if nargin0) + [diameter,center] = secondary_source_diameter(conf); + t0 = diameter/c; + if (ceil((max(delay)+t0)*fs) - 1 ) > N + % This is a lot more likely to happen. + warning('conf.N = %i is too short for requested source.',N); + end + if strcmp('fs',src) + % Reject focused source that's too far away + % (this will only happen for unbounded listening arrays.) + if norm(xs(1:3) - center,2) > diameter/2; + error(['%s: Using ''config.wfs.removedelay == 0'', ', ... + 'focused source positions are restricted to the ball ', ... + 'spanned by the array diameter.'],upper(mfilename)); + end + end + delay = delay + t0; + % Return extra added delay. This is can be used to ensure that the virtual + % source always starts at t = 0. + delay_offset = t0 + prefilter_delay; +else + error('%s: t0 needs to be "system" or "source" and not "%s".', ... + upper(mfilename),t0); +end % Append zeros at the end of the driving function. This is necessary, because % the delayline function cuts into the end of the driving signals in order to -% delay them. NOTE: this is can be changed by the conf.N setting +% delay them. NOTE: this can be changed by the conf.N setting d_proto = repmat([row_vector(pulse) zeros(1,N-length(pulse))]',1,size(x0,1)); % Shift and weight prototype driving function -d = delayline(d_proto,delay*fs,weight,conf); +[d, delayline_delay] = delayline(d_proto,delay,weight,conf); +% Add delay offset of delayline +delay_offset = delay_offset + delayline_delay; diff --git a/SFS_time_domain/driving_functions_imp/driving_function_imp_localwfs_sbl_ps.m b/SFS_time_domain/driving_functions_imp/driving_function_imp_localwfs_sbl_ps.m new file mode 100644 index 00000000..0a585d9b --- /dev/null +++ b/SFS_time_domain/driving_functions_imp/driving_function_imp_localwfs_sbl_ps.m @@ -0,0 +1,135 @@ +function [d,delay_offset] = driving_function_imp_localwfs_sbl_ps(x0,xs,conf) +%DRIVING_FUNCTION_IMP_LOCALWFS_SBL_PS driving signal for a point source using +%local WFS with spatial bandwidth limitation +% +% Usage: [d,delay_offset] = driving_function_imp_localwfs_sbl_ps(x0,xs,conf) +% +% Input parameters: +% x0 - position and direction of the secondary source / m [nx7] +% xs - position of virtual point source / m [1x3] +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% d - driving signals [mxn] +% delay_offset - additional added delay, so you can correct it +% +% See also: sound_field_imp_localwfs_sbl, driving_function_imp_localwfs_sbl +% +% References: +% Winter, Hahn, Spors (2017), "Time-Domain Realisation of Model-Based +% Rendering for 2.5D Local Wave Field Synthesis Using Spatial +% Bandwidth-Limitation", 25th European Signal Processing Conference +% (EUSIPCO), pp. 718-722, https://bit.ly/2yMjlOw + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ======================================== +nargmin = 3; +nargmax = 3; +narginchk(nargmin,nargmax); + + +%% ===== Configuration ======================================================== +N0 = size(x0,1); +Nfft = conf.N; +xref = conf.xref; +fs = conf.fs; +% Ambisonics order +if isempty(conf.localwfs_sbl.order) + Nce = nfchoa_order(N0,conf); +else + Nce = conf.localwfs_sbl.order; +end +% Crossover frequency +if isempty(conf.localwfs_sbl.fc) + fc = aliasing_frequency(conf); +else + fc = conf.localwfs_sbl.fc; +end +% Resolution of plane wave decomposition +if isempty(conf.localwfs_sbl.Npw) + Npw = 2*ceil(2*pi*0.9*fs/conf.c*conf.secondary_sources.size/2); +else + Npw = conf.localwfs_sbl.Npw; +end + +%% ===== Variables ============================================================ +Nlr = ceil(Nce/2)*2; % order of Linkwitz-Riley Coefficients +Wlr = fc/fs*2; % normalised cut-off frequency of Linkwitz-Riley + + +%% ===== Computation ========================================================== + +% === Local WFS for high frequencies === +% Regular circular expansion of point source (highpass implicitly) +% Winter et al. (2017), eq. (14) +[pm,delay_circexp] = circexp_imp_ps(xs,Nce,xref,fc,conf); +% Modal window +wm = modal_weighting(Nce,conf); +pm = bsxfun(@times,wm,pm); +% Plane wave decomposition, Winter et al. (2017), eq. (10) +ppwd = pwd_imp_circexp(pm,Npw); +% Driving signal, Winter et al. (2017), eq. (9) +[dlwfs,delay_lwfs] = driving_function_imp_wfs_pwd(x0,ppwd,xref,conf); + +% === WFS for low frequencies === +% Secondary source selection +[~,xdx] = secondary_source_selection(x0,xs,'ps'); +x0(xdx,:) = secondary_source_tapering(x0(xdx,:),conf); +% Driving signal +dwfs = zeros(Nfft,N0); +[dwfs(:,xdx),~,~,delay_lp] = driving_function_imp_wfs(x0(xdx,:),xs,'ps',conf); +% Coefficients for lowpass filtering of WFS driving function +[zlp,plp,klp] = linkwitz_riley(Nlr,Wlr,'low'); % LR Lowpass filter +% Lowpass filtering +[sos,g] = zp2sos(zlp,plp,klp,'down','none'); % generate sos +dwfs = sosfilt(sos,dwfs)*g; + +% === Crossover === +% Winter et al. (2017), eq. (15) +% Get delay of delayline +[~,delay_delayline] = delayline(1,0,0,conf); +% Delay to compensate between lf-part and hf-part +delay_comp = delay_lp - (delay_lwfs+delay_circexp+delay_delayline); +% Combined driving signal +d = dwfs + delayline(dlwfs,delay_comp,1,conf); + +% === Compensate Phase-Distortions by Inverse Allpass === +% Winter et al. (2017), eq. (17) +% TODO: ensure that the time-reserved filter is not truncated +[zap,pap,kap] = linkwitz_riley(Nlr,Wlr,'all'); % LR Allpass filter +[sos,g] = zp2sos(zap,pap,kap,'down','none'); % generate sos +% (time-reversed) allpass filtering +d = sosfilt(sos,d(end:-1:1,:))*g; +d = d(end:-1:1,:); + +% Final delay +delay_offset = delay_lp; diff --git a/SFS_time_domain/driving_functions_imp/driving_function_imp_localwfs_sbl_pw.m b/SFS_time_domain/driving_functions_imp/driving_function_imp_localwfs_sbl_pw.m new file mode 100644 index 00000000..dca6ae36 --- /dev/null +++ b/SFS_time_domain/driving_functions_imp/driving_function_imp_localwfs_sbl_pw.m @@ -0,0 +1,88 @@ +function [d,delay_offset] = driving_function_imp_localwfs_sbl_pw(x0,nk,conf) +%DRIVING_FUNCTION_IMP_LOCALWFS_SBL_PW driving signal for a plane wave using local +%WFS with spatial bandwidth limitation +% +% Usage: [d,delay_offset] = driving_function_imp_localwfs_sbl_pw(x0,nk,conf) +% +% Input parameters: +% x0 - position and direction of the secondary source / m [nx7] +% nk - propagation direction of plane wave / m [1x3] +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% d - driving signals [mxn] +% delay_offset - additional added delay, so you can correct it +% +% See also: sound_field_imp_localwfs_sbl, driving_function_imp_localwfs_sbl +% +% References: +% Winter, Hahn, Spors (2017), "Time-Domain Realisation of Model-Based +% Rendering for 2.5D Local Wave Field Synthesis Using Spatial +% Bandwidth-Limitation", 25th European Signal Processing Conference +% (EUSIPCO), pp. 718-722, http://bit.ly/2yMjlOw + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 3; +nargmax = 3; +narginchk(nargmin,nargmax); + + +%% ===== Configuration ======================================================== +N0 = size(x0,1); +xref = conf.xref; +fs = conf.fs; +% Maximum order of circular basis expansion of sound field +if isempty(conf.localwfs_sbl.order) + Nce = nfchoa_order(N0,conf); +else + Nce = conf.localwfs_sbl.order; +end +% resolution of plane wave decomposition +if isempty(conf.localwfs_sbl.Npw) + Npw = 2*ceil(2*pi*0.9*fs/conf.c*conf.secondary_sources.size/2); +else + Npw = conf.localwfs_sbl.Npw; +end + +%% ===== Computation ========================================================== +% Circular expansion coefficients, Winter et al. (2017), eq. (12) +[pm,delay_circexp] = circexp_imp_pw(nk,Nce,xref,conf); +% Modal window +wm = modal_weighting(Nce,conf); +pm = bsxfun(@times,wm,pm); +% Plane wave decomposition +ppwd = pwd_imp_circexp(pm,Npw); % Winter et al. (2017), eq. (10) +% Driving signal, Winter et al. (2017), eq. (9) +[d,delay_lwfs] = driving_function_imp_wfs_pwd(x0,ppwd,xref,conf); +% Delay +delay_offset = delay_lwfs + delay_circexp; diff --git a/SFS_time_domain/driving_functions_imp/driving_function_imp_nfchoa_fs.m b/SFS_time_domain/driving_functions_imp/driving_function_imp_nfchoa_fs.m index f33c8057..4451bf2a 100644 --- a/SFS_time_domain/driving_functions_imp/driving_function_imp_nfchoa_fs.m +++ b/SFS_time_domain/driving_functions_imp/driving_function_imp_nfchoa_fs.m @@ -1,67 +1,58 @@ -function sos = driving_function_imp_nfchoa_fs(N,R,r,conf) -%DRIVING_FUNCTION_IMP_NFCHOA_FS calculates the second-order section -%representation for a virtual focused source in NFC-HOA +function [sos,g] = driving_function_imp_nfchoa_fs(N,R,r,conf) +%DRIVING_FUNCTION_IMP_NFCHOA_FS second-order section representation for a +%focused source in NFC-HOA % -% Usage: sos = driving_function_imp_nfchoa_fs(N,R,r,[conf]); +% Usage: sos = driving_function_imp_nfchoa_fs(N,R,r,conf) % % Input parameters: -% N - order of spherical hankel function +% N - order of spherical Hankel function % R - radius of secondary source array / m % r - distance of focused source from array center / m -% conf - optional configuration struct (see SFS_config) +% conf - configuration struct (see SFS_config) % % Output parameters: % sos - second-order section representation +% g - scalar gain factor % -% DRIVING_FUNCTION_IMP_NFCHOA_FS(N,R,r,conf) returns the second-order section -% representation for the NFC-HOA driving function for a virtual focused source -% as source model. -% -% See also: sound_field_imp, sound_field_imp_nfchoa, driving_function_imp_nfchoa +% See also: sound_field_imp, sound_field_imp_nfchoa, +% driving_function_imp_nfchoa %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 3; +nargmin = 4; nargmax = 4; narginchk(nargmin,nargmax); isargpositivescalar(N,R,r); -if nargin. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 3; +nargmin = 4; nargmax = 4; narginchk(nargmin,nargmax); isargpositivescalar(N,R,r); -if nargin. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 3; +nargmin = 4; nargmax = 4; narginchk(nargmin,nargmax); isargpositivescalar(N,R,r); -if nargin. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 2; +nargmin = 3; nargmax = 3; narginchk(nargmin,nargmax); isargpositivescalar(N,R); -if nargin. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 3; +nargmin = 4; nargmax = 4; narginchk(nargmin,nargmax); isargmatrix(x0,nx0,xs); -if nargin. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 3; +nargmin = 4; nargmax = 4; narginchk(nargmin,nargmax); isargmatrix(x0,nx0,xs); -if nargin nxs, + % and |nxs| = 1. + % + % https://sfs.rtfd.io/en/3.2/d_wfs/#equation-td-wfs-line + % + % v = (I - nxs'nxs)(x0-xs) + % r = |v| + nxs = nxs(1,:); + v = (x0 - xs)*(eye(3) - nxs'*nxs); + r = vector_norm(v,2); + delay = 1/c .* r; + weight = 1/(2*pi) .* vector_product(v,nx0,2) ./ r.^(3/2); + otherwise + error(['%s: %s, this type of driving function is not implemented', ... + 'for a line source.'],upper(mfilename),driving_functions); + end + else error('%s: the dimension %s is unknown.',upper(mfilename),dimension); end diff --git a/SFS_time_domain/driving_functions_imp/driving_function_imp_wfs_ps.m b/SFS_time_domain/driving_functions_imp/driving_function_imp_wfs_ps.m index 3fcd26a7..49d1b014 100644 --- a/SFS_time_domain/driving_functions_imp/driving_function_imp_wfs_ps.m +++ b/SFS_time_domain/driving_functions_imp/driving_function_imp_wfs_ps.m @@ -1,71 +1,64 @@ function [delay,weight] = driving_function_imp_wfs_ps(x0,nx0,xs,conf) -%DRIVING_FUNCTION_IMP_WFS_PS calculates the WFS weighting and delaying for a -%point source as source model +%DRIVING_FUNCTION_IMP_WFS_PS weights and delays for a point source in WFS % -% Usage: [delay,weight] = driving_function_imp_wfs_ps(x0,nx0,xs,[conf]); +% Usage: [delay,weight] = driving_function_imp_wfs_ps(x0,nx0,xs,conf) % % Input parameters: -% x0 - position of secondary sources (m) [nx3] +% x0 - position of secondary sources / m [nx3] % nx0 - direction of secondary sources [nx3] % xs - position of point source [nx3] -% conf - optional configuration struct (see SFS_config) +% conf - configuration struct (see SFS_config) % % Output parameters: -% delay - delay of the driving function (s) +% delay - delay of the driving function / s % weight - weight (amplitude) of the driving function % -% DRIVING_FUNCTION_IMP_WFS_PS(x0,nx0,xs,conf) returns delays and weights for -% the WFS driving function for a point source as source model. +% See also: sound_field_imp, sound_field_imp_wfs, driving_function_mono_wfs_ps % % References: -% H. Wierstorf, J. Ahrens, F. Winter, F. Schultz, S. Spors (2015) - -% "Theory of Sound Field Synthesis" +% Start (1997) - "Direct Sound Enhancement by Wave Field Synthesis", +% TU Delft, +% http://resolver.tudelft.nl/uuid:c80d5b58-67d3-4d84-9e73-390cd30bde0d % -% See also: sound_field_imp, sound_field_imp_wfs, driving_function_mono_wfs_ps +% Wierstorf (2014) - "Perceptual Assessment of Sound Field Synthesis", +% TU Berlin, https://doi.org/10.14279/depositonce-4310 %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 3; +nargmin = 4; nargmax = 4; narginchk(nargmin,nargmax); isargmatrix(x0,nx0,xs); -if nargin. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 3; +nargmin = 4; nargmax = 4; narginchk(nargmin,nargmax); isargmatrix(x0,nx0,nk); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - -%% ===== Checking of input parameters ================================== -nargmin = 3; -nargmax = 4; -narginchk(nargmin,nargmax); -isargmatrix(dv); -isargsecondarysource(x0,xv); -if nargin 0 - % Focused source position - xs = repmat(xvi(1:3)',[size(x0s,1) 1]); - % Delay and weights for single focused source - [delay(xdx,idx),weight(xdx,idx)] = driving_function_imp_wfs_fs(x0s(:,1:3),x0s(:,4:6),xs,conf); - % Optional tapering - x0s = secondary_source_tapering(x0s,conf); - % Apply secondary sources' tapering and possibly virtual secondary - % sources' tapering to weighting matrix - weight(xdx,idx) = weight(xdx,idx).*x0s(:,7).*xvi(7); - end - idx = idx + 1; -end - -% Remove delay offset, in order to begin always at t=0 with the first wave front -% at any secondary source -delay = delay - min(delay(:)); - -% Compose impulse responses -for idx=1:Nv - xdx = weight(:,idx) ~= 0; - if sum(xdx) > 0 - % Shift and weight prototype driving function - pulse = repmat(dv(:,idx), 1, sum(xdx)); - d(:, xdx) = d(:, xdx) + delayline(pulse, delay(xdx,idx)*fs, weight(xdx,idx), conf); - end -end +function [d,delay_offset] = driving_function_imp_wfs_vss(x0,xv,srcv,dv,conf) +%DRIVING_FUNCTION_IMP_WFS_VSS driving signal for a given set of +%virtual secondary sources and their corresponding driving signals +% +% Usage: d = driving_function_imp_wfs_vss(x0,dv,xv,srcv,conf) +% +% Input parameters: +% x0 - position, direction, and weights of the real secondary +% sources / m [N0x7] +% xv - position, direction, and weights of the virtual secondary +% sources / m [Nvx7] +% srcv - type of virtual secondary sources [mx7] +% 'pw' - plane wave (xv(:,1:3) defines the direction of +% the plane waves in this case) +% 'fs' - focused source (xv(:,1:6) defines the position +% and orientation of the focused sources in this +% case) +% dv - driving signals of virtual secondary sources [NxNv] +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% d - driving function signal [NxN0] +% delay_offset - additional added delay, so you can correct it +% +% See also: driving_function_imp_localwfs_vss, driving_function_mono_wfs_vss +% +% References: +% Spors and Ahrens (2010) - "Local Sound Field Synthesis by Virtual +% Secondary Sources", 40th Conference of the Audio Engineering Society, +% Paper 6-3, http://www.aes.org/e-lib/browse.cfm?elib=15561 + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + +%% ===== Checking of input parameters ================================== +nargmin = 5; +nargmax = 5; +narginchk(nargmin,nargmax); +isargmatrix(dv); +isargsecondarysource(x0,xv); +isargchar(srcv); +isargstruct(conf); + +%% ===== Computation ==================================================== +% Initialize +Nv = size(xv,1); +N0 = size(x0,1); + +tau0 = inf(Nv,N0); +w0 = zeros(Nv,N0); + +% Calculate pre-equalization filter if required hpre(t) +[hpre,delay_offset] = wfs_preequalization(dirac_imp(),conf); + +% Apply hpre to pwd if its more efficient (less virtual sources than +% loudspeakers) +if Nv <= N0 + dv = convolution(dv,hpre); +end +N = size(dv,1); + +% Secondary source selection and driving function to synthesise a single virtual +% secondary source +switch srcv +case 'fs' + ssd_select = @(X0,XS) secondary_source_selection(X0,XS(1:6)','fs'); + driv = @(X0,XS) driving_function_imp_wfs_fs(X0(:,1:3),X0(:,4:6),XS,conf); +case 'pw' + ssd_select = @(X0,XS) secondary_source_selection(X0,XS(1:3)','pw'); + driv = @(X0,XS) driving_function_imp_wfs_pw(X0(:,1:3),X0(:,4:6),XS,conf); +end + +% it's ok to have zero secondary sources selected for pwd +warning('off','SFS:x0'); +idx = 1; +for xvi = xv' + % Select active source for single virtual secondary source + [x0s, xdx] = ssd_select(x0,xvi); + if ~isempty(x0s) && xvi(7) > 0 + % Virtual secondary source position + xs = repmat(xvi(1:3)',[size(x0s,1) 1]); + % Delay and weights for single virtual secondary source + [tau0(idx,xdx),w0(idx,xdx)] = driv(x0s,xs); + % Optional tapering + wtap = tapering_window(x0s, conf); + % Apply secondary sources' tapering and possibly virtual secondary + % sources' tapering to weighting matrix + w0(idx,xdx) = w0(idx,xdx).*wtap.'.*xvi(7); + end + idx = idx + 1; +end +warning('on','SFS:x0'); + +% Remove delay offset, in order to begin always at t=0 with the first wave +% front at any secondary source +delay_offset = delay_offset - min(tau0(w0~=0)); +tau0 = tau0 - min(tau0(w0~=0)); + +% Compose impulse responses +d = zeros(N,N0); +for ndx=1:Nv + % Select only secondary source with non-zero weights + xsel = w0(ndx,:) ~= 0; + + [tmp, delayline_delay] = ... + delayline(dv(:,ndx),tau0(ndx,xsel),w0(ndx,xsel),conf); + d(:,xsel) = d(:,xsel) + tmp; +end +% Add delay of delayline +delay_offset = delay_offset + delayline_delay; + +% Apply hpre to driving signals if its more efficient +if Nv > N0 + d = convolution(d,hpre); +end +d = d(1:conf.N, :); diff --git a/SFS_time_domain/greens_function_imp.m b/SFS_time_domain/greens_function_imp.m index 9b364bf1..33ca4fd7 100644 --- a/SFS_time_domain/greens_function_imp.m +++ b/SFS_time_domain/greens_function_imp.m @@ -1,9 +1,9 @@ function [g,t] = greens_function_imp(x,y,z,xs,src,t,conf) -%GREENS_FUNCTION_IMP returns a Green's function in the time domain +%GREENS_FUNCTION_IMP Green's function in the time domain % -% Usage: [g,t] = greens_function_imp(x,y,z,xs,src,t,[conf]) +% Usage: [g,t] = greens_function_imp(x,y,z,xs,src,t,conf) % -% Input options: +% Input parameters: % x - x points / m % y - y points / m % z - z points / m @@ -12,71 +12,59 @@ % 'ps' - point source % 'ls' - line source % 'pw' - plane wave -% t - time / samples -% conf - optional configuration struct (see SFS_config) +% t - time / s +% conf - configuration struct (see SFS_config) % % Output parameters: % g - Green's function evaluated at the points x,y,z -% t - Correspondiong time values with integrated time -% shift / samples +% t - Corresponding time values with integrated time +% shift / s % -% GREENS_FUNCTION_IMP(x,y,z,xs,src,t) calculates the Green's function for the -% given source model located at xs for the given points x,y,z. Note, that the -% delta function for the time t is returned as an extra argument. If you want -% the value of the Green's function only to this specific time you should have -% a look at sound_field_imp() and apply the folowing command: +% GREENS_FUNCTION_IMP(x,y,z,xs,src,t,conf) calculates the Green's function for +% the given source model located at xs for the given points x,y,z. Note, that +% the delta function for the time t is returned as an extra argument. If you +% want the value of the Green's function only for a specific time you should +% have a look at sound_field_imp() and apply the folowing command: % [p,x,y,z] = sound_field_imp(X,Y,Z,[xs 0 -1 0],src,1,t,conf); % -% References: -% H. Wierstorf, J. Ahrens, F. Winter, F. Schultz, S. Spors (2015) - -% "Theory of Sound Field Synthesis" -% % See also: greens_function_mono, sound_field_imp %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== % disabled checking for performance reasons -nargmax = 7; -if nargin f + +if strcmp('2.5D',dimension) + % Expected slope: 6dB per frequency-doubling + % Find 6dB cut-off frequency + flowidx = find(H <= 1/2, 1, 'first'); + hpreflow = f(flowidx)/2; +elseif strcmp('3D',dimension) || strcmp('2D',dimension) + % Expected slope: 12dB per frequency-doubling + % Find 12dB cut-off frequency + flowidx = find(H <= 1/4, 1, 'first'); + hpreflow = f(flowidx)/4; +else + error('%s: %s is not a valid conf.dimension entry',upper(mfilename)); +end + +% Approximated slope beginning at hpreflow +Hslope = hpreflow./f(flowidx:end); +% Mean of H(f) evaluated from f to fs/2 +Hmean = cumsum(H(end:-1:flowidx)); % cumulative sum +Hmean = Hmean./(1:length(Hmean)).'; % cumulative mean +Hmean = fliplr(Hmean); +% fhighidx is the frequency where both functions intersect the first time +fhighidx = flowidx - 1 + find( Hslope <= Hmean, 1, 'first'); + +if isempty(fhighidx) + hprefhigh = fs/2; +else + hprefhigh = f(fhighidx); +end diff --git a/SFS_time_domain/movie_sound_field_imp_wfs.m b/SFS_time_domain/movie_sound_field_imp_wfs.m index c9d45117..6200a5c0 100644 --- a/SFS_time_domain/movie_sound_field_imp_wfs.m +++ b/SFS_time_domain/movie_sound_field_imp_wfs.m @@ -1,120 +1,112 @@ -function movie_sound_field_imp_wfs(X,Y,Z,xs,src,outfile,conf) -%MOVIE_SOUND_FIELD_IMP_WFS generates movie a WFS sound field -% -% Usage: movie_sound_field_imp_wfs_25d(X,Y,Z,xs,src,outfile,[conf]) -% -% Input parameters: -% X - x-axis / m; single value or [xmin,xmax] -% Y - y-axis / m; single value or [ymin,ymax] -% Z - z-axis / m; single value or [zmin,zmax] -% xs - position of point source / m -% src - sourcetype of the virtual source: -% 'pw' - plane wave (xs, ys are the direction of the -% plane wave in this case) -% 'ps' - point source -% 'fs' - focused source -% outfile - name for the movie file -% conf - optional configuration struct (see SFS_config) -% -% MOVIE_SOUND_FIELD_IMP_WFS(X,Y,Z,xs,src,outfile,conf) generates a movie of -% simulations of a sound field of the given source positioned at xs -% using a WFS driving function in the temporal domain with different phase. -% -% See also: sound_field_imp_wfs, plot_sound_field, generate_movie - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 6; -nargmax = 7; -narginchk(nargmin,nargmax); -isargvector(X,Y,Z); -isargxs(xs); -isargchar(src,outfile); -if nargin. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 7; +nargmin = 8; nargmax = 8; narginchk(nargmin,nargmax); -isargvector(X,Y); -isargmatrix(x0,d); +isargnumeric(X,Y,Z); +isargsecondarysource(x0); isargchar(src); +isargmatrix(d); isargscalar(t); -if nargin x % ^ % position of secondary source % d = d(end:-1:1,:); -% + % Add additional zeros to the driving signal to ensure an amplitude of 0 in the % whole listening area before and after the real driving signal. +% % First get the maximum distance of the listening area and convert it into time -% samples, than compare it to the size of the secondary sources. If the size is -% biger use this for padding zeros. -[~,x1,x2,x3] = xyz_axes_selection(x,y,z); % get active axes -max_distance_in_samples = ... - round(max(norm([x(1) y(1) z(1)]-[x(end) y(end) z(end)])/c*fs,2*L/c*fs)); - +% samples, then compare it to the size 2*L of the secondary sources. If the size +% is larger use this for padding zeros. +max_listening_area = [max(xx(:)) max(yy(:)) max(zz(:))]; +min_listening_area = [min(xx(:)) min(yy(:)) min(zz(:))]; +max_distance = max(norm(max_listening_area-min_listening_area),2*L); +max_distance_in_samples = round(max_distance/c*fs); % Append zeros at the beginning of the driving signal d = [zeros(max_distance_in_samples,size(d,2)); d]; -% Correct time vector to work with inverted driving functions -% this will lead to a time point of t=0 for the starting of emitting the driving -% signal -t_inverted = t-size(d,1); +% Correct time vector to work with inverted driving functions, this will lead to +% a time point of t=0 for the starting of emitting the driving signal +t_inverted = t-size(d,1)/fs; % Append zeros at the end of the driving signal d = [d; zeros(max_distance_in_samples,size(d,2))]; - % Initialize empty sound field (dependent on the axes we want) -p = squeeze(zeros(length(x3),length(x2),length(x1))); +p = zeros(size(x1)); -% Apply bandbass filter +% Apply bandpass filter if usebandpass d = bandpass(d,bandpassflow,bandpassfhigh,conf); end - - + % Integration over secondary sources for ii = 1:size(x0,1) - % progress bar if showprogress, progress_bar(ii,size(x0,1)); end % ================================================================ % Secondary source model: Greens function g3D(x,t) - % distance of secondary source to receiver position [g,t_delta] = greens_function_imp(xx,yy,zz,x0(ii,1:3),src,t_inverted,conf); % Interpolate the driving function w.r.t. the propagation delay from % the secondary sources to a field point. The t returned from the Green's - % function already inlcudes the desired time shift of the driving signal. + % function already includes the desired time shift of the driving signal. % NOTE: the interpolation is required to account for the fractional % delay times from the loudspeakers to the field points - ds = interp1(1:length(d(:,ii)),d(:,ii),t_delta,'spline'); + ds = interp1(1:length(d(:,ii)),d(:,ii),t_delta*fs,'spline'); % ================================================================ % Integration @@ -186,7 +171,8 @@ % p(x,t) = | d(x0,t) g(x-x0,t) dx0 % / % - % see Wierstorf et al. (2015), eq.(#single:layer) or Williams (1993), p. 36 + % Compare https://sfs.rtfd.io/en/3.2/problem/#equation-fd-single-layer + % % x0(ii,7) is a weight for the single secondary sources which includes for % example a tapering window for WFS or a weighting of the sources for % integration on a sphere. @@ -195,23 +181,20 @@ end % === Checking of sound field === -check_sound_field(p,t); -% Normalize field -p = norm_sound_field(p,conf); +warning_if_zero(p,t); % Return parameter if nargout>0, varargout{1}=p; end -if nargout>1, varargout{2}=x; end -if nargout>2, varargout{3}=y; end -if nargout>3, varargout{4}=z; end +if nargout>1, varargout{2}=xx; end +if nargout>2, varargout{3}=yy; end +if nargout>3, varargout{4}=zz; end %% ===== Plotting ======================================================== if nargout==0 || useplot - plot_sound_field(p,x,y,z,x0,conf); + plot_sound_field(p,X,Y,Z,x0,conf); end -% Some debug stuff if debug figure; imagesc(db(abs(d))); title('driving functions'); caxis([-100 0]); colorbar; end diff --git a/SFS_time_domain/sound_field_imp_line_source.m b/SFS_time_domain/sound_field_imp_line_source.m index 30e19bb8..270f7061 100644 --- a/SFS_time_domain/sound_field_imp_line_source.m +++ b/SFS_time_domain/sound_field_imp_line_source.m @@ -1,67 +1,72 @@ -function varargout = sound_field_imp_line_source(X,Y,Z,xs,varargin) -%SOUND_FIELD_IMP_LINE_SOURCE simulates a sound field for a line source -% -% Usage: [P,x,y,z] = sound_field_imp_line_source(X,Y,Z,xs,t,[conf]) -% -% Input parameters: -% X - x-axis / m; single value or [xmin,xmax] -% Y - y-axis / m; single value or [ymin,ymax] -% Z - z-axis / m; single value or [zmin,zmax] -% xs - position of line source / m -% t - time / samples -% conf - optional configuration struct (see SFS_config) -% -% Output parameters: -% P - Simulated sound field -% x - corresponding x axis / m -% y - corresponding y axis / m -% z - corresponding z axis / m -% -% SOUND_FIELD_IMP_LINE_SOURCE(X,Y,Z,xs,t,conf) simulates a sound -% field of a line source positioned at xs. -% To plot the result use plot_sound_field(P,x,y,z). -% -% See also: sound_field_imp, plot_sound_field, sound_field_mono_line_source - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 5; -nargmax = 6; -narginchk(nargmin,nargmax); -isargxs(xs); - - -%% ===== Computation ==================================================== -[varargout{1:nargout}] = sound_field_imp(X,Y,Z,[xs 0 -1 0 1],'ls',1,varargin{:}); +function varargout = sound_field_imp_line_source(X,Y,Z,xs,t,conf) +%SOUND_FIELD_IMP_LINE_SOURCE sound field of a line source +% +% Usage: [p,x,y,z] = sound_field_imp_line_source(X,Y,Z,xs,t,conf) +% +% Input parameters: +% X - x-axis / m; single value or [xmin,xmax] or nD-array +% Y - y-axis / m; single value or [ymin,ymax] or nD-array +% Z - z-axis / m; single value or [zmin,zmax] or nD-array +% xs - position of line source / m +% t - time / s +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% p - Simulated sound field +% x - corresponding x values / m +% y - corresponding y values / m +% z - corresponding z values / m +% +% SOUND_FIELD_IMP_LINE_SOURCE(X,Y,Z,xs,t,conf) simulates a sound +% field of a line source positioned at xs at time t. +% +% To plot the result use: +% plot_sound_field(p,X,Y,Z,conf); +% or simple call the function without output argument: +% sound_field_imp_line_source(X,Y,Z,xs,t,conf) +% For plotting you may also consider to display the result in dB, by setting +% the following configuration option before: +% conf.plot.usedB = true; +% +% See also: sound_field_imp, plot_sound_field, sound_field_mono_line_source + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 6; +nargmax = 6; +narginchk(nargmin,nargmax); +isargxs(xs); + + +%% ===== Computation ==================================================== +x0 = [xs 0 -1 0 1]; +[varargout{1:nargout}] = sound_field_imp(X,Y,Z,x0,'ls',dirac_imp(),t,conf); diff --git a/SFS_time_domain/sound_field_imp_localwfs.m b/SFS_time_domain/sound_field_imp_localwfs.m deleted file mode 100644 index 3673cffa..00000000 --- a/SFS_time_domain/sound_field_imp_localwfs.m +++ /dev/null @@ -1,119 +0,0 @@ -function varargout = sound_field_imp_localwfs(X,Y,Z,xs,src,t,conf) -%SOUND_FIELD_IMP_LOCALWFS returns the sound field in time domain of an impulse -% -% Usage: [p,x,y,z,x0] = sound_field_imp_localwfs(X,Y,Z,xs,src,t,[conf]) -% -% Input options: -% X - x-axis / m; single value or [xmin,xmax] -% Y - y-axis / m; single value or [ymin,ymax] -% Z - z-axis / m; single value or [zmin,zmax] -% xs - position of point source / m -% src - source type of the virtual source -% 'pw' - plane wave (xs, ys are the direction of the -% plane wave in this case) -% 'ps' - point source -% t - time point t of the sound field / samples -% conf - optional configuration struct (see SFS_config) -% -% Output options: -% p - simulated sound field -% x - corresponding x axis / m -% y - corresponding y axis / m -% z - corresponding z axis / m -% x0 - secondary sources / m -% -% SOUND_FIELD_IMP_LOCALWFS(X,Y,Z,xs,src,t,conf) simulates a sound field of the -% given source type (src) using a LOCALWFS driving function with a delay line at -% the time t. -% -% To plot the result use: -% conf.plot.usedb = 1; -% plot_sound_field(p,x,y,z,x0,win,conf); -% -% See also: driving_function_imp_localwfs, sound_field_mono_localwfs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - -%% ===== Checking of input parameters ================================== -nargmin = 6; -nargmax = 7; -narginchk(nargmin,nargmax); -isargvector(X,Y,Z); -isargxs(xs); -isargchar(src); -isargscalar(t); -if nargin. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 6; +nargmin = 7; nargmax = 7; narginchk(nargmin,nargmax); -isargvector(X,Y,Z); isargxs(xs); isargchar(src); isargscalar(t); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 5; -nargmax = 6; -narginchk(nargmin,nargmax); -isargxs(xs); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 5; -nargmax = 6; -narginchk(nargmin,nargmax); -isargxs(xs); - - -%% ===== Computation ==================================================== -[varargout{1:nargout}] = sound_field_imp(X,Y,Z,[xs 0 -1 0 1],'ps',1,varargin{:}); +function varargout = sound_field_imp_point_source(X,Y,Z,xs,t,conf) +%SOUND_FIELD_IMP_POINT_SOURCE sound field of a point source +% +% Usage: [p,x,y,z] = sound_field_imp_point_source(X,Y,Z,xs,t,conf) +% +% Input parameters: +% X - x-axis / m; single value or [xmin,xmax] or nD-array +% Y - y-axis / m; single value or [ymin,ymax] or nD-array +% Z - z-axis / m; single value or [zmin,zmax] or nD-array +% xs - position of point source / m +% t - time / s +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% p - simulated sound field +% x - corresponding x values / m +% y - corresponding y values / m +% z - corresponding z values / m +% +% SOUND_FIELD_IMP_POINT_SOURCE(X,Y,Z,xs,t,conf) simulates a sound +% field of a point source positioned at xs at time t. +% +% To plot the result use: +% plot_sound_field(p,X,Y,Z,conf); +% or simple call the function without output argument: +% sound_field_imp_point_source(X,Y,Z,xs,t,conf) +% For plotting you may also consider to display the result in dB, by setting +% the following configuration option before: +% conf.plot.usedB = true; +% +% See also: sound_field_imp, plot_sound_field, sound_field_mono_point_source + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ================================== +nargmin = 6; +nargmax = 6; +narginchk(nargmin,nargmax); +isargxs(xs); + + +%% ===== Computation ==================================================== +x0 = [xs 0 -1 0 1]; +[varargout{1:nargout}] = sound_field_imp(X,Y,Z,x0,'ps',dirac_imp(),t,conf); diff --git a/SFS_time_domain/sound_field_imp_wfs.m b/SFS_time_domain/sound_field_imp_wfs.m index 1796f5d5..39d4517d 100644 --- a/SFS_time_domain/sound_field_imp_wfs.m +++ b/SFS_time_domain/sound_field_imp_wfs.m @@ -1,110 +1,100 @@ -function varargout = sound_field_imp_wfs(X,Y,Z,xs,src,t,conf) -%SOUND_FIELD_IMP_WFS returns the sound field in time domain of an impulse -% -% Usage: [p,x,y,z,x0] = sound_field_imp_wfs(X,Y,Z,xs,src,t,[conf]) -% -% Input options: -% X - x-axis / m; single value or [xmin,xmax] -% Y - y-axis / m; single value or [ymin,ymax] -% Z - z-axis / m; single value or [zmin,zmax] -% xs - position of point source / m -% src - source type of the virtual source -% 'pw' - plane wave (xs, ys are the direction of the -% plane wave in this case) -% 'ps' - point source -% 'fs' - focused source -% t - time point t of the sound field / samples -% conf - optional configuration struct (see SFS_config) -% -% Output options: -% p - simulated sound field -% x - corresponding x axis / m -% y - corresponding y axis / m -% z - corresponding z axis / m -% x0 - secondary sources / m -% -% SOUND_FIELD_IMP_WFS(X,Y,Z,xs,src,t,conf) simulates a sound field of the -% given source type (src) using a WFS driving function with a delay line at -% the time t. -% -% To plot the result use: -% conf.plot.usedb = 1; -% plot_sound_field(p,x,y,z,x0,win,conf); -% -% See also: driving_function_imp_wfs, sound_field_mono_wfs - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ================================== -nargmin = 6; -nargmax = 7; -narginchk(nargmin,nargmax); -isargvector(X,Y,Z); -isargxs(xs); -isargchar(src); -isargscalar(t); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - - -%% ===== Checking of input parameters ================================== -nargmin = 0; -nargmax = 1; -narginchk(nargmin,nargmax); -if nargin f -% -% Pre-equilization filter from flow to fhigh -if strcmp('2.5D',dimension) - % _______ - % H(f) = \|f/fhigh, for flow<=f<=fhigh - % - % see Wierstorf et al. (2015), eq.(#wfs:preeq:2.5D) - % - H(idxflow:idxfhigh) = sqrt(f(idxflow:idxfhigh)./fhigh); -elseif strcmp('3D',dimension) || strcmp('2D',dimension) - % - % H(f) = f/fhigh, for flow<=f<=fhigh - % - % see Wierstorf et al. (2015), eq.(#wfs:preeq) - % - H(idxflow:idxfhigh) = f(idxflow:idxfhigh)./fhigh; -else - error('%s: %s is not a valid conf.dimension entry',upper(mfilename)); -end -% Set the response for idxf < idxflow to the value at idxflow -H(1:idxflow) = H(idxflow)*ones(1,idxflow); - -% Compute filter -hpre = firls(Nfilt,2*f/fs,H); - -% Truncate length to power of 2 -hpre = hpre(1:end-1); +function hpre = wfs_fir_prefilter(conf) +%WFS_FIR_PREFILTER pre-equalization filter for WFS +% +% Usage: hpre = wfs_fir_prefilter(conf) +% +% Input parameters: +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% hpre - pre-equalization filter +% +% WFS_FIR_PREFILTER(conf) calculates a sqrt(j k) pre-equalization filter for +% Wave Field Synthesis (from conf.wfs.hpreflow to conf.wfs.hprefhigh, +% see SFS_config). +% +% See also: wfs_preequalization, wfs_iir_prefilter, sound_field_imp_wfs, ir_wfs + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + + +%% ===== Checking of input parameters ================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); +isargstruct(conf); + + +%% ===== Configuration ================================================== +fs = conf.fs; % Sampling rate +c = conf.c; % Speed of sound +dimension = conf.dimension; % Dimensionality +flow = conf.wfs.hpreflow; % Lower frequency limit of preequalization + % filter (= frequency when subwoofer is active) +fhigh = conf.wfs.hprefhigh; % Upper frequency limit of preequalization + % filter (= aliasing frequency of system) +Nfilt = conf.wfs.hpreFIRorder; % Number of coefficients for filter +if isodd(Nfilt) + error(['%s: conf.wfs.hpreFIRorder == %i is not a valid filter order. ', ... + 'Must be an even integer.'],upper(mfilename),Nfilt); +end +%% ===== Variables ====================================================== +% Frequency axis +f = linspace(0,fs/2,fs/10); +% Find indices for frequencies in f smaller and nearest to fhigh and flow +idxfhigh = max(find(f f +% +% Pre-equalization filter from flow to fhigh +if strcmp('2.5D',dimension) + % ______ + % |2*pi*f + % H(f) = \ |------ for flow<=f<=fhigh + % \| c + % + % https://sfs.rtfd.io/en/3.2/d_wfs/#equation-td-wfs-prefilter-25d + % + H(idxflow:idxfhigh) = sqrt(2*pi*f(idxflow:idxfhigh)/c); + H(idxfhigh:end) = H(idxfhigh); +elseif strcmp('3D',dimension) || strcmp('2D',dimension) + % + % 2*pi*f + % H(f) = ------ for flow<=f<=fhigh + % c + % + % https://sfs.rtfd.io/en/3.2/d_wfs/#equation-td-wfs-prefilter + % + H(idxflow:idxfhigh) = 2*pi*f(idxflow:idxfhigh)/c; + H(idxfhigh:end) = H(idxfhigh); +else + error('%s: %s is not a valid conf.dimension entry',upper(mfilename),dimension); +end +% Set the response for idxf < idxflow to the value at idxflow +H(1:idxflow) = H(idxflow); + +% Compute filter +hpre = firls(Nfilt,2*f/fs,H); + diff --git a/SFS_time_domain/wfs_iir_prefilter.m b/SFS_time_domain/wfs_iir_prefilter.m index cd8d7c8c..a99a825f 100644 --- a/SFS_time_domain/wfs_iir_prefilter.m +++ b/SFS_time_domain/wfs_iir_prefilter.m @@ -1,10 +1,10 @@ function hpre = wfs_iir_prefilter(conf) -%WFS_IIR_PREFILTER creates a minimum-phase IIR pre-equalization filter for WFS +%WFS_IIR_PREFILTER minimum-phase IIR pre-equalization filter for WFS % -% Usage: hpre = wfs_iir_prefilter([conf]) +% Usage: hpre = wfs_iir_prefilter(conf) % % Input parameters: -% conf - optional configuration struct (see SFS_config) +% conf - configuration struct (see SFS_config) % % must at least include: % conf.fs = 44100; - sampling frequency / Hz @@ -29,78 +29,70 @@ % filter % % Required Functions: -% get_shelve_lagrange.m (included in SFS-toolbox) -% fdesign (included in the Matlab Signal Processing Toolbox, requiring DSP System Design Toolbox) -% +% get_shelve_lagrange (included in SFS-toolbox) +% fdesign (included in the Matlab Signal Processing Toolbox, requiring DSP +% System Design Toolbox) % % WFS_IIR_PREFILTER(conf) calculates a sqrt(j k) pre-equalization filter % with high shelving characterstics for Wave Field Synthesis. % Note, this function does not work in Octave, use conf.wfs.hpretype='FIR' % instead. % -% For details see [Sch13]: -% Frank Schultz, Vera Erbes, Sascha Spors, Stefan Weinzierl (2013): -% "Derivation of IIR prefilters for soundfield synthesis using linear -% secondary source distributions", In: Proc. of the -% International Conference on Acoustics AIA-DAGA 2013, Merano, Italy, -% 18 - 21 March 2013, pages 2372-2375 -% % See also: wfs_preequalization, wfs_fir_prefilter, driving_function_imp_wfs, % wfs_ir - +% +% References: +% Schultz, Erbes, Spors, Weinzierl (2013) - "Derivation of IIR prefilters +% for soundfield synthesis using linear secondary source distributions", +% International Conference on Acoustics (AIA-DAGA), p.2372-2375, +% http://pub.dega-akustik.de/AIA_DAGA_2013/data/articles/000604.pdf %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * % Revision: 07/02/2013 frank.schultz@uni-rostock.de initial development * %***************************************************************************** %% ===== Checking of input parameters ================================== -nargmin = 0; +nargmin = 1; nargmax = 1; narginchk(nargmin,nargmax); -if nargin. * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters ==================================== -nargmin = 1; -nargmax = 2; -narginchk(nargmin,nargmax); -isargmatrix(ir); -if narginlength(hpre)+1 - ir = ir(1:len_ir,:); -end +function [ir,delay] = wfs_preequalization(ir,conf) +%WFS_PREEQUALIZATION applies the pre-equalization filter for WFS +% +% Usage: ir = wfs_preequalization(ir,conf) +% +% Input parameters: +% ir - signal to which the pre-equalization filter should be applied +% conf - configuration struct (see SFS_config) +% +% Output parameters: +% ir - signal with applied pre-equalization +% delay - additional delay added by pre-equalization / s +% +% See also: wfs_fir_prefilter, wfs_iir_prefilter, driving_function_imp_wfs + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +%% ===== Checking of input parameters ==================================== +nargmin = 2; +nargmax = 2; +narginchk(nargmin,nargmax); +isargmatrix(ir); +isargstruct(conf); + + +%% ===== Configuration ================================================== +usehpre = conf.wfs.usehpre; +fs = conf.fs; + + +%% ===== Computation ===================================================== +% Check if we should procide +if ~usehpre + delay = 0; + return; +end +% Store original length +len_ir = size(ir,1); +% Get the filter +if strcmp('FIR',conf.wfs.hpretype) + % Get FIR filter + hpre = wfs_fir_prefilter(conf); + % Apply filter + ir = convolution(hpre,ir); + % Delay in s added by filter + delay = conf.wfs.hpreFIRorder/2 / fs; +elseif strcmp('IIR',conf.wfs.hpretype) + if len_ir == 1 + % Happens when called from driving_function_imp_wfs() + % Zeropadding to length conf.N + ir = [ir; zeros(conf.N-1,size(ir,2))]; + end + % Get IIR filter + hpre = wfs_iir_prefilter(conf); + % Apply filter + ir = sosfilt(hpre.sos,ir,1); + % IIR is minimum phase, so no proper delay introduced + delay = 0; +else + error('%s: %s is an unknown filter type.',upper(mfilename),hpretype); +end +% Correct length of ir +if strcmp('FIR',conf.wfs.hpretype) && (len_ir>length(hpre)+1) + ir = ir(1:len_ir,:); +end diff --git a/SFS_version.m b/SFS_version.m index 0faf77cc..b525c905 100644 --- a/SFS_version.m +++ b/SFS_version.m @@ -9,38 +9,35 @@ % See also: SFS_start, SFS_config %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** %% ===== Configuration =================================================== % Version number -versionnumber = '1.2.0'; +versionnumber = '2.5.0'; diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 00000000..472c5b75 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,13 @@ +Online Documentation +==================== + +This directory holds the documentation in reStructuredText/Sphinx format. +Have a look at the online documentation for the auto-generated HTML version: + +https://sfs-matlab.readthedocs.io/ + +In order to generate a version on your local machine run: + +```bash +$ sphinx-build -b html -d ./_build/doctrees . ./_build/html-preview/ +``` diff --git a/doc/_static/css/abbr.css b/doc/_static/css/abbr.css new file mode 100644 index 00000000..a919f3c2 --- /dev/null +++ b/doc/_static/css/abbr.css @@ -0,0 +1,4 @@ +abbr[title] { + border-bottom: 1px dotted; + text-decoration: none !important; +} diff --git a/doc/_static/css/title.css b/doc/_static/css/title.css new file mode 100644 index 00000000..e539e2b1 --- /dev/null +++ b/doc/_static/css/title.css @@ -0,0 +1,33 @@ +.wy-side-nav-search>a, .wy-side-nav-search .wy-dropdown>a { + font-family: "Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif; + font-size: 200%; + margin-top: .222em; + margin-bottom: .202em; +} +.wy-side-nav-search { + padding: 0; +} +form#rtd-search-form { + margin-left: .809em; + margin-right: .809em; +} +.rtd-nav a { + float: left; + display: block; + width: 33.3%; + height: 100%; + padding-top: 7px; + color: white; +} +.rtd-nav { + overflow: hidden; + width: 100%; + height: 35px; + margin-top: 15px; +} +.rtd-nav a:hover { + background-color: #388bbd; +} +.rtd-nav a.active { + background-color: #388bbd; +} diff --git a/doc/_template/layout.html b/doc/_template/layout.html new file mode 100644 index 00000000..3d313c84 --- /dev/null +++ b/doc/_template/layout.html @@ -0,0 +1,14 @@ +{% extends "!layout.html" %} +{% block sidebartitle %} + + {{ project }} + + {% include "searchbox.html" %} + +
+ Theory + Matlab + Python +
+ +{% endblock %} diff --git a/doc/acronyms.py b/doc/acronyms.py new file mode 100644 index 00000000..b69b5b6a --- /dev/null +++ b/doc/acronyms.py @@ -0,0 +1,26 @@ +# Definitions of acronyms that are used on https://sfs-matlab.readthedocs.io/ +# +# This uses the rst-epilog variable, which will be appended to every source +# file by sphinx, see: +# http://www.sphinx-doc.org/en/stable/config.html#confval-rst_epilog +# +# Include this into your conf.py file with +# from acronyms import rst_epilog + +acronyms = """ +.. |BRIR| replace:: :abbr:`BRIR (Binaural Room Impulse Response)` +.. |BRS| replace:: :abbr:`BRS (Binaural Room Scanning)` +.. |FFT| replace:: :abbr:`FFT (Fast Fourier Transform)` +.. |HOA| replace:: :abbr:`HOA (Higher Order Ambisonics)` +.. |HRIR| replace:: :abbr:`HRIR (Head-Related Impulse Response)` +.. |HRTF| replace:: :abbr:`HRTF (Head-Related Transfer Function)` +.. |KEMAR| replace:: :abbr:`KEMAR (Knowles Electronics Manikin for Acoustic Research)` +.. |LSFS| replace:: :abbr:`LSFS (Local Sound Field Synthesis)` +.. |NFC-HOA| replace:: :abbr:`NFC-HOA (Near-Field Compensated Higher Order Ambisonics)` +.. |SDM| replace:: :abbr:`SDM (Spectral Division Method)` +.. |SOFA| replace:: :abbr:`SOFA (Spatially Oriented Format for Acoustics)` +.. |SSR| replace:: :abbr:`SSR (SoundScape Renderer)` +.. |WFS| replace:: :abbr:`WFS (Wave Field Synthesis)` +""" + +# vim: textwidth=300: diff --git a/doc/aes132_paper.bib b/doc/aes132_paper.bib deleted file mode 100644 index dafb9047..00000000 --- a/doc/aes132_paper.bib +++ /dev/null @@ -1,6 +0,0 @@ -@inproceedings{Wierstorf2012a, -author = {Wierstorf, Hagen and Spors, Sascha}, -booktitle = {132nd Convention of the Audio Engineering Society}, -title = {{Sound Field Synthesis Toolbox}}, -year = {2012} -} diff --git a/doc/binaural-simulations.rst b/doc/binaural-simulations.rst new file mode 100644 index 00000000..b546b522 --- /dev/null +++ b/doc/binaural-simulations.rst @@ -0,0 +1,318 @@ +.. _sec-binaural-simulations: + +Binaural Simulations +==================== + +If you have a set of |HRTF|\ s or |BRIR|\ s you can simulate the ear signals +reaching a listener sitting at a given point in the listening area for different +spatial audio systems. + +In order to easily use different |HRTF| or |BRIR| sets the Toolbox uses the +`SOFA file format `_. In order to use it you have +to install the `SOFA API for Matlab/Octave +`_ and run ``SOFAstart`` before you can +use it inside the SFS Toolbox. If you are looking for different |HRTF|\ s and +|BRIR|\ s, a large set of different impulse responses is available: +https://www.sofaconventions.org/mediawiki/index.php/Files. + +The files dealing with the binaural simulations are in the folder +``SFS_binaural_synthesis``. Files dealing with |HRTF|\ s and |BRIR|\ s are in +the folder ``SFS_ir``. If you want to extrapolate your |HRTF|\ s to plane waves +you may also want to have a look in the folder ``SFS_HRTF_extrapolation``. + +In the following we present some examples of binaural simulations. For their +auralization an anechoic recording of a cello is used, which can be downloaded +from `anechoic\_cello.wav +`__. + +Binaural simulation of arbitrary loudspeaker arrays +--------------------------------------------------- + +.. figure:: img/tu_berlin_hrtf.jpg + :align: center + + Setup of the |KEMAR| and a loudspeaker during a |HRTF| measurement. + +If you use an |HRTF| data set, it has the advantage that it was recorded in +anechoic conditions and the only parameter that matters is the relative position +of the loudspeaker to the head during the measurement. This advantage can be +used to create every possible loudspeaker array you can imagine, given that the +relative locations of all loudspeakers are available in the |HRTF| data set. The +above picture shows an example of a |HRTF| measurement. You can download the +corresponding `QU_KEMAR_anechoic_3m.sofa`_ |HRTF| set, which we can directly use +with the Toolbox. + +.. _QU_KEMAR_anechoic_3m.sofa: https://github.com/sfstoolbox/data/raw/master/HRTFs/QU_KEMAR_anechoic_3m.sofa + +The following example will load the |HRTF| data set and extracts a single +impulse response for an angle of 30° from it. If the desired angle of +30° is not available, a linear interpolation between the next two +available angles will be applied. Afterwards the impulse response will +be convolved with the cello recording by the ``auralize_ir()`` function. + +.. sourcecode:: matlab + + X = [0 0 0]; + head_orientation = [0 0]; + xs = [rad(30) 0 3]; + coordinate_system = 'spherical'; + hrtf = SOFAload('QU_KEMAR_anechoic_3m.sofa'); + conf = SFS_config; + ir = get_ir(hrtf,X,head_orientation,xs,coordinate_system,conf); + cello = wavread('anechoic_cello.wav'); + sig = auralize_ir(ir,cello,1,conf); + sound(sig,conf.fs); + +To simulate the same source as a virtual point source synthesized by |WFS| +and a circular array with a diameter of 3 m, you have to do the +following. + +.. sourcecode:: matlab + + X = [0 0 0]; + head_orientation = [pi/2 0]; + xs = [0 3 0]; + src = 'ps'; + hrtf = SOFAload('QU_KEMAR_anechoic_3m.sofa'); + conf = SFS_config; + conf.secondary_sources.size = 3; + conf.secondary_sources.number = 56; + conf.secondary_sources.geometry = 'circle'; + conf.dimension = '2.5D'; + ir = ir_wfs(X,head_orientation,xs,src,hrtf,conf); + cello = wavread('anechoic_cello.wav'); + sig = auralize_ir(ir,cello,1,conf); + +If you want to use binaural simulations in listening experiments, you should not +only have the |HRTF| data set, but also a corresponding headphone compensation +filter, which was recorded with the same dummy head as the |HRTF|\ s and the +headphones you are going to use in your test. For the |HRTF|\ s we used in the +last example and the AKG K601 headphones you can download +`QU_KEMAR_AKGK601_hcomp.wav`_. If you want to redo the last simulation with +headphone compensation, just add the following lines before calling +``ir_wfs()``. + +.. _QU_KEMAR_AKGK601_hcomp.wav: https://raw.githubusercontent.com/sfstoolbox/data/master/headphone_compensation/QU_KEMAR_AKGK601_hcomp.wav + +.. sourcecode:: matlab + + conf.ir.usehcomp = true; + conf.ir.hcompfile = 'QU_KEMAR_AKGK601_hcomp.wav'; + conf.N = 4096; + +The last setting ensures that your impulse response will be long enough +for convolution with the compensation filter. + +Binaural simulation of a real setup +----------------------------------- + +.. figure:: img/university_rostock_loudspeaker_array.jpg + :align: center + + Boxed shaped loudspeaker array at the University Rostock. + +Besides simulating arbitrary loudspeaker configurations in an anechoic space, +you can also do binaural simulations of real loudspeaker setups. In the +following example we use |BRIR|\ s from the 64-channel loudspeaker array of the +University Rostock as shown in the panorama photo above. The |BRIR|\ s and +additional information on the recordings are available for download, see +`doi:10.14279/depositonce-87.2`_. For such a measurement the |SOFA| file format +has the advantage to be able to include all loudspeakers and head orientations +in just one file. + +.. _`doi:10.14279/depositonce-87.2`: https://doi.org/10.14279/depositonce-87.2 + +.. sourcecode:: matlab + + X = [0 0 0]; + head_orientation = [0 0]; + xs = [3 0 0]; + src = 'ps'; + brir = 'BRIR_AllAbsorbers_ArrayCentre_Emitters1to64.sofa'; + conf = SFS_config; + conf.secondary_sources.geometry = 'custom'; + conf.secondary_sources.x0 = brir; + conf.N = 44100; + ir = ir_wfs(X,head_orientation,xs,src,brir,conf); + cello = wavread('anechoic_cello.wav'); + sig = auralize_ir(ir,cello,1,conf); + +In this case, we don't load the |BRIR|\ s into the memory with +``SOFAload()`` as the file is too large. Instead, we make use of the +ability that |SOFA| can request single impulse responses from the file by +just passing the file name to the ``ir_wfs()`` function. In addition, we +have to set ``conf.N`` to a reasonable large value as this determines +the length of the impulse response ``ir_wfs()`` will return, which has +to be larger as for the anechoic case as it should now include the room +reflections. Note, that the head orientation is chosen to be ``0`` +instead of ``pi/2`` as in the |HRTF| examples due to a difference in the +orientation of the coordinate system of the |BRIR| measurement. + +Impulse response of your spatial audio system +--------------------------------------------- + +Binaural simulations are also an interesting approach to investigate the +behavior of a given spatial audio system at different listener positions. Here, we +are mainly interested in the influence of the system and not the |HRTF|\ s so we +simply use a Dirac impulse as |HRTF| as provided by ``dummy_irs()``. + +.. sourcecode:: matlab + + X = [0 0 0]; + head_orientation = [0 0]; + xs = [2.5 0 0]; + src = 'ps'; + t = (1:1000)/conf.fs*1000; + hrtf = dummy_irs(conf); + conf = SFS_config; + conf.t0 = 'source'; + [ir,~,delay] = ir_wfs(X,head_orientation,xs,src,hrtf,conf); + figure; + figsize(540,404,'px'); + plot(t,ir(1:1000,1),'-g'); + hold on; + offset = round(delay*conf.fs); + plot(t,ir(1+offset:1000+offset,1),'-b'); + hold off; + xlabel('time / ms'); + ylabel('amplitude'); + %print_png('img/impulse_response_wfs_25d.png'); + +.. figure:: img/impulse_response_wfs_25d.png + :align: center + + Sound pressure of an impulse synthesized as a point source by 2.5D |WFS| at + (2.5, 0, 0) m. The sound pressure is observed by a virtual microphone at + (0, 0, 0) m. The impulse is plotted including the delay offset of the WFS + driving function (green) and with a corrected delay that corresponds to the + source poisition (blue). + +The figure includes two versions of the impulse response at two different time +instances. The green impulse response includes the processing delay that is +added by ``driving_function_imp_wfs()`` and other functions performing filtering +and delaying of signals. This delay is returned by ``ir_wfs()`` as well and can +be used to correct it during plotting. The blue impulse response is the +corrected one, which is now placed at 7.3 ms which corresponds to the actual +distance of the synthesized source of 2.5 m. + +The impulse response can also be calculated without involving functions for +binaural simulations, but by utilizing directly ``sound_field_imp()`` related +function. + +.. sourcecode:: matlab + + X = [0 0 0]; + head_orientation = [0 0]; + xs = [2.5 0 0]; + src = 'ps'; + conf = SFS_config; + conf.N = 1000; + conf.t0 = 'source'; + time_response_wfs(X,xs,src,conf) + axis([0 25 -0.005 0.025]); + %print_png('img/impulse_response_wfs_25d_imp.png'); + +.. figure:: img/impulse_response_wfs_25d_imp.png + :align: center + + Sound pressure of an impulse synthesized as a point source by 2.5D + |WFS| at (2.5, 0, 0) m. The sound pressure is observed by a virtual + microphone at (0, 0, 0) m. + +This time the delay offset of the driving function is automatically corrected +for and the involved calculation uses inherently a fractional delay filter. The +downside is that the calculation takes longer and the amplitude is slightly +lower by the involved fractional delay method. + + +Frequency response of your spatial audio system +----------------------------------------------- + +Binaural simulations are also a nice way to investigate the frequency +response of your reproduction system. The following code will +investigate the influence of the pre-equalization filter in |WFS| on the +frequency response. For the red line the pre-filter is used and its +upper frequency is set to the expected aliasing frequency of the system +(above these frequency the spectrum becomes very noise as you can see in +the figure). + +.. sourcecode:: matlab + + X = [0 0 0]; + head_orientation = [pi/2 0]; + xs = [0 2.5 0]; + src = 'ps'; + hrtf = dummy_irs(conf); + conf = SFS_config; + conf.ir.usehcomp = false; + conf.wfs.usehpre = false; + [ir1,x0] = ir_wfs(X,head_orientation,xs,src,hrtf,conf); + conf.wfs.usehpre = true; + conf.wfs.hprefhigh = aliasing_frequency(x0,conf); + ir2 = ir_wfs(X,head_orientation,xs,src,hrtf,conf); + [a1,p,f] = spectrum_from_signal(norm_signal(ir1(:,1)),conf); + a2 = spectrum_from_signal(norm_signal(ir2(:,1)),conf); + figure; + figsize(540,404,'px'); + semilogx(f,20*log10(a1),'-b',f,20*log10(a2),'-r'); + axis([10 20000 -80 -40]); + set(gca,'XTick',[10 100 250 1000 5000 20000]); + legend('w/o pre-filter','w pre-filter'); + xlabel('frequency / Hz'); + ylabel('magnitude / dB'); + %print_png('img/frequency_response_wfs_25d.png'); + +.. figure:: img/frequency_response_wfs_25d.png + :align: center + + Sound pressure in decibel of a point source synthesized by 2.5D |WFS| for + different frequencies. The 2.5D |WFS| is performed with and without the + pre-equalization filter. The calculation is performed in the time domain. + +The same can be done in the frequency domain, but in this case we are +not able to set a maximum frequency of the pre-equalization filter and +the whole frequency range will be affected. + +.. sourcecode:: matlab + + X = [0 0 0]; + xs = [0 2.5 0]; + src = 'ps'; + conf = SFS_config; + freq_response_wfs(X,xs,src,conf); + axis([10 20000 -40 0]); + %print_png('img/frequency_response_wfs_25d_mono.png'); + +.. figure:: img/frequency_response_wfs_25d_mono.png + :align: center + + Sound pressure in decibel of a point source synthesized by 2.5D |WFS| for + different frequencies. The 2.5D |WFS| is performed only with the + pre-equalization filter active at all frequencies. The calculation is + performed in the frequency domain. + +Using the SoundScape Renderer with the SFS Toolbox +-------------------------------------------------- + +In addition to binaural synthesis, you may want to apply dynamic binaural +synthesis, which means you track the position of the head of the listener and +switches the used impulse responses regarding the head position. The `SoundScape +Renderer (SSR)`_ is able to do this. The SFS Toolbox provides functions to +generate the needed wav files containing the impulse responses used by the +SoundScape Renderer. All functions regarding the |SSR| are stored in folder +``SFS_ssr``. + +.. sourcecode:: matlab + + X = [0 0 0]; + head_orientation = [pi/2 0]; + xs = [0 2.5 0]; + src = 'ps'; + hrtf = SOFAload('QU_KEMAR_anechoic_3m.sofa'); + conf = SFS_config; + brs = ssr_brs_wfs(X,head_orientation,xs,src,hrtf,conf); + wavwrite(brs,conf.fs,16,'brs_set_for_SSR.wav'); + +.. _SoundScape Renderer (SSR): http://spatialaudio.net/ssr/ + +.. vim: filetype=rst spell: diff --git a/doc/conf.py b/doc/conf.py new file mode 100644 index 00000000..29b65cd9 --- /dev/null +++ b/doc/conf.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- + +import sys +import os +import subprocess +import sphinx_rtd_theme +# Allow local modules and extensions +sys.path.insert(0, os.path.abspath('.')) # for acronyms.py +from acronyms import acronyms # |HRTF| etc. + + +# -- GENERAL ------------------------------------------------------------- + +project = 'SFS Toolbox' +copyright = '2010-2019 SFS Toolbox Developers' +author = 'SFS Toolbox Developers' + +needs_sphinx = '1.3' # minimal sphinx version +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.mathjax', + 'sphinx.ext.viewcode', +] +master_doc = 'index' +source_suffix = '.rst' +exclude_patterns = ['_build'] +# The full version, including alpha/beta/rc tags. +#release = version +try: + release = subprocess.check_output( + ('git', 'describe', '--tags', '--always')) + release = release.decode().strip() +except Exception: + release = '' + +# Append acronyms at the end of every page +rst_epilog = acronyms + + +# -- FIGURES AND CODE ---------------------------------------------------- +numfig = True +# Code syntax highlighting style +pygments_style = 'trac' + + +# -- HTML ---------------------------------------------------------------- + +def setup(app): + """Include custom theme files to sphinx HTML header""" + app.add_stylesheet('css/abbr.css') + app.add_stylesheet('css/title.css') + +html_theme = "sphinx_rtd_theme" +html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +html_static_path = ['_static'] +templates_path = ['_template'] +html_title = "SFS Toolbox" +html_short_title = "" +htmlhelp_basename = 'sfs-matlab' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + 'papersize': 'letterpaper', + 'pointsize': '10pt', + 'preamble': '', + 'figure_align': 'htbp', +} +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'sfs-matlab.tex', u'SFS Toolbox - Matlab Documentation', + u'SFS Toolbox Developers', 'manual'), +] +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None diff --git a/doc/custom-grid.rst b/doc/custom-grid.rst new file mode 100644 index 00000000..8f958651 --- /dev/null +++ b/doc/custom-grid.rst @@ -0,0 +1,46 @@ +.. _sec-custom-grid: + +Custom Grids +============ + +As stated earlier you can provide the sound field simulation functions a +custom grid instead of the ``[min max]`` ranges. Again, you can provide +it for one dimension, two dimensions, or all three dimensions. + +.. sourcecode:: matlab + + conf = SFS_config; + conf.dimension = '3D'; + conf.secondary_sources.number = 225; + conf.secondary_sources.geometry = 'sphere'; + conf.resolution = 100; + conf.plot.normalisation = 'center'; + X = randi([-2000 2000],125000,1)/1000; + Y = randi([-2000 2000],125000,1)/1000; + Z = randi([-2000 2000],125000,1)/1000; + sound_field_mono_wfs(X,Y,Z,[0 -1 0],'pw',800,conf); + %print_png('img/sound_field_wfs_3d_xyz_custom_grid.png'); + conf.plot.usedb = true; + conf.dimension = '2.5D'; + conf.secondary_sources.number = 64; + conf.secondary_sources.geometry = 'circle'; + sound_field_imp_nfchoa(X,Y,0,[0 2 0],'ps',0.005,conf); + %print_png('img/sound_field_imp_nfchoa_25d_dB_custom_grid.png'); + +.. figure:: img/sound_field_wfs_3d_xyz_custom_grid.png + :align: center + + Sound pressure of a monochromatic point source synthesized by 3D |WFS|. The + plane wave has a frequency of 800 Hz and is travelling into the direction + (0,-1,0). The sound pressure is calculated only at the explicitly provided + grid points. + +.. figure:: img/sound_field_imp_nfchoa_25d_dB_custom_grid.png + :align: center + + Sound pressure in decibel of a broadband impulse point source synthesized by + 2.5D |NFC-HOA|. The point source is placed at (0,2,0) m and a time snapshot + after 5 ms of the first active secondary source is shown. The sound pressure + is calculated only at the explicitly provided grid points. + +.. vim: filetype=rst spell: diff --git a/doc/frequency-domain.rst b/doc/frequency-domain.rst new file mode 100644 index 00000000..0142fd2d --- /dev/null +++ b/doc/frequency-domain.rst @@ -0,0 +1,232 @@ +.. _sec-frequency-domain: + +Frequency Domain +================ + +With the files in the folder ``SFS_monochromatic`` you can simulate a +monochromatic sound field in a specified area for different techniques like +|WFS| and |NFC-HOA|. The area can be a 3D cube, a 2D plane, a line or only one +point. This depends on the specification of ``X,Y,Z``. For example ``[-2 2],[-2 +2],[-2 2]`` will be a 3D cube; ``[-2 2],0,[-2 2]`` the xz-plane; ``[-2 2],0,0`` +a line along the x-axis; ``3,2,1`` a single point. If you present a range like +``[-2 2]`` the Toolbox will create automatically a regular grid from this +ranging from -2 to 2 with ``conf.resolution`` steps in between. Alternatively +you could apply a :ref:`custom grid ` by providing a matrix +instead of the ``[min max]`` range for all active axes. + +For all 2.5D functions the configuration ``conf.xref`` is important as it +defines the point for which the amplitude is corrected in the sound +field. The default entry is + +.. sourcecode:: matlab + + conf.xref = [0 0 0]; + +Wave Field Synthesis +-------------------- + +The following will simulate the field of a virtual plane wave with a +frequency of 800 Hz going into the direction of (0 -1 0) synthesized +with 3D |WFS|. + +.. sourcecode:: matlab + + conf = SFS_config; + conf.dimension = '3D'; + conf.secondary_sources.size = 3; + conf.secondary_sources.number = 225; + conf.secondary_sources.geometry = 'sphere'; + % [P,x,y,z,x0,win] = sound_field_mono_wfs(X,Y,Z,xs,src,f,conf); + sound_field_mono_wfs([-2 2],[-2 2],0,[0 -1 0],'pw',800,conf); + %print_png('img/sound_field_wfs_3d_xy.png'); + sound_field_mono_wfs([-2 2],0,[-2 2],[0 -1 0],'pw',800,conf); + %print_png('img/sound_field_wfs_3d_xz.png'); + sound_field_mono_wfs(0,[-2 2],[-2 2],[0 -1 0],'pw',800,conf); + %print_png('img/sound_field_wfs_3d_yz.png'); + +.. figure:: img/sound_field_wfs_3d_xy.png + :align: center + + Sound pressure of a mono-chromatic plane wave synthesized by 3D |WFS|. The + plane wave has a frequency of 800Hz and is travelling into the direction + (0,-1,0). The plot shows the xy-plane. + +.. figure:: img/sound_field_wfs_3d_xz.png + :align: center + + The same as in the figure before, but now showing the xz-plane. + +.. figure:: img/sound_field_wfs_3d_yz.png + :align: center + + The same as in the figure before, but now showing the yz-plane. + +You can see that the Toolbox is now projecting all the secondary source +positions into the plane for plotting them. In addition the axis are +automatically chosen and labeled. + +It is also possible to simulate and plot the whole 3D cube, but in this +case no secondary sources will be added to the plot. + +.. sourcecode:: matlab + + conf = SFS_config; + conf.dimension = '3D'; + conf.secondary_sources.size = 3; + conf.secondary_sources.number = 225; + conf.secondary_sources.geometry = 'sphere'; + conf.resolution = 100; + sound_field_mono_wfs([-2 2],[-2 2],[-2 2],[0 -1 0],'pw',800,conf); + %print_png('img/sound_field_wfs_3d_xyz.png'); + +.. figure:: img/sound_field_wfs_3d_xyz.png + :align: center + + Sound pressure of a mono-chromatic plane wave synthesized by 3D |WFS|. The + plane wave has a frequency of 800Hz and is travelling into the direction + (0,-1,0). All three dimensions are shown. + +In the next plot we use a two dimensional array, 2.5D |WFS| and a virtual +point source located at (0 2.5 0) m. The 3D example showed you, that the +sound fields are automatically plotted if we specify now output +arguments. If we specify one, we have to explicitly say if we want also +plot the results, by ``conf.plot.useplot = true;``. + +.. sourcecode:: matlab + + conf = SFS_config; + conf.dimension = '2.5D'; + conf.plot.useplot = true; + conf.plot.normalisation = 'center'; + % [P,x,y,z,x0] = sound_field_mono_wfs(X,Y,Z,xs,src,f,conf); + [P,x,y,z,x0] = sound_field_mono_wfs([-2 2],[-2 2],0,[0 2.5 0],'ps',800,conf); + %print_png('img/sound_field_wfs_25d.png'); + +.. figure:: img/sound_field_wfs_25d.png + :align: center + + Sound pressure of a mono-chromatic point source synthesized by 2.5D |WFS|. + The point source has a frequency of 800Hz and is placed at (0 2.5 0)m. Only + the active loudspeakers of the array are plotted. + +If you want to plot the whole loudspeaker array and not only the active +secondary sources, you can do this by adding these commands. First we +store all sources in an extra variable ``x0_all``, then we get the active +ones ``x0`` and the corresponding indices of these active ones in ``x0_all``. +Afterwards we set all sources in ``x0_all`` to zero, which are inactive and +only the active ones to the loudspeaker weights ``x0(:,7)``. + +.. sourcecode:: matlab + + x0_all = secondary_source_positions(conf); + [~,idx] = secondary_source_selection(x0_all,[0 2.5 0],'ps'); + x0_all(:,7) = zeros(1,size(x0_all,1)); + x0_all(idx,7) = x0(:,7); + plot_sound_field(P,[-2 2],[-2 2],0,x0_all,conf); + %print_png('img/sound_field_wfs_25d_with_all_sources.png'); + +.. figure:: img/sound_field_wfs_25d_with_all_sources.png + :align: center + + Sound pressure of a mono-chromatic point source synthesized by 2.5D |WFS|. + The point source has a frequency of 800Hz and is placed at (0 2.5 0)m. All + loudspeakers are plotted. Their color correspond to the loudspeaker weights, + where white stands for zero. + + +Near-Field Compensated Higher Order Ambisonics +---------------------------------------------- + +In the following we will simulate the field of a virtual plane wave with +a frequency of 800 Hz traveling into the direction (0 -1 0), synthesized +with 2.5D |NFC-HOA|. + +.. sourcecode:: matlab + + conf = SFS_config; + conf.dimension = '2.5D'; + % sound_field_mono_nfchoa(X,Y,Z,xs,src,f,conf); + sound_field_mono_nfchoa([-2 2],[-2 2],0,[0 -1 0],'pw',800,conf); + %print_png('img/sound_field_nfchoa_25d.png'); + +.. figure:: img/sound_field_nfchoa_25d.png + :align: center + + Sound pressure of a monochromatic plane wave synthesized by 2.5D |NFC-HOA|. + The plane wave has a frequency of 800 Hz and is traveling into the direction + (0,-1,0). + +Local Wave Field Synthesis +-------------------------- + +In |NFC-HOA| the aliasing frequency in a small region inside the listening +area can be increased by limiting the used order. A similar outcome can +be achieved in |WFS| by applying so called local Wave Field Synthesis. In +this case the original loudspeaker array is driven by |WFS| to create a +virtual loudspeaker array consisting of focused sources which can then +be used to create the desired sound field in a small area. The settings +are the same as for |WFS|, but a new struct ``conf.localwfs`` has to be filled +out, which for example provides the settings for the desired position +and form of the local region with higher aliasing frequency, have a look +into ``SFS_config.m`` for all possible settings. + +.. sourcecode:: matlab + + X = [-1 1]; + Y = [-1 1]; + Z = 0; + xs = [1 -1 0]; + src = 'pw'; + f = 7000; + conf = SFS_config; + conf.resolution = 1000; + conf.dimension = '2D'; + conf.secondary_sources.geometry = 'box'; + conf.secondary_sources.number = 4*56; + conf.secondary_sources.size = 2; + conf.localwfs_vss.size = 0.4; + conf.localwfs_vss.center = [0 0 0]; + conf.localwfs_vss.geometry = 'circular'; + conf.localwfs_vss.number = 56; + sound_field_mono_localwfs_vss(X,Y,Z,xs,src,f,conf); + axis([-1.1 1.1 -1.1 1.1]); + %print_png('img/sound_field_localwfs_2d.png'); + +.. figure:: img/sound_field_localwfs_2d.png + :align: center + + Sound pressure of a monochromatic plane wave synthesized by 2D local |WFS|. + The plane wave has a frequency of 7000 Hz and is traveling into the + direction (1,-1,0). The local |WFS| is created by using focused sources to + create a virtual circular loudspeaker array in he center of the actual + loudspeaker array. + +Stereo +------ + +The Toolbox includes not only |WFS| and |NFC-HOA|, but also some generic +sound field functions that are doing only the integration of the driving +signals of the single secondary sources to the resulting sound field. +With these function you can for example easily simulate a stereophonic +setup. In this example we set the +``conf.plot.normalisation = 'center';`` configuration manually as the +amplitude of the sound field is too low for the default ``'auto'`` +setting to work. + +.. sourcecode:: matlab + + conf = SFS_config; + conf.plot.normalisation = 'center'; + x0 = [-1 2 0 0 -1 0 1;1 2 0 0 -1 0 1]; + % [P,x,y,z] = sound_field_mono(X,Y,Z,x0,src,D,f,conf) + sound_field_mono([-2 2],[-1 3],0,x0,'ps',[1 1],800,conf) + %print_png('img/sound_field_stereo.png'); + +.. figure:: img/sound_field_stereo.png + :align: center + + Sound pressure of a monochromatic phantom source generated by stereophony. + The phantom source has a frequency of 800 Hz and is placed at (0,2,0) by + amplitude panning. + +.. vim: filetype=rst spell: diff --git a/doc/helper-functions.rst b/doc/helper-functions.rst new file mode 100644 index 00000000..b2d670be --- /dev/null +++ b/doc/helper-functions.rst @@ -0,0 +1,13 @@ +.. _sec-helper-functions: + +Helper Functions +================ + +The Toolbox provides you also with a set of useful small functions. Here the +highlights are angle conversion with ``rad()`` and ``deg()``, |FFT| calculation +and plotting ``spectrum_from_signal()``, rotation matrix ``rotation_matrix()``, +multi-channel fast convolution ``convolution()``, nearest neighbour search +``findnearestneighbour()``, even or odd checking ``iseven()`` ``isodd()``, +spherical Bessel functions ``sphbesselh()`` ``sphbesselj()`` ``sphbessely()``. + +.. vim: filetype=rst spell: diff --git a/doc/img/frequency_response_wfs_25d.png b/doc/img/frequency_response_wfs_25d.png new file mode 100644 index 00000000..98e2e342 Binary files /dev/null and b/doc/img/frequency_response_wfs_25d.png differ diff --git a/doc/img/frequency_response_wfs_25d_mono.png b/doc/img/frequency_response_wfs_25d_mono.png new file mode 100644 index 00000000..b3ff8b5a Binary files /dev/null and b/doc/img/frequency_response_wfs_25d_mono.png differ diff --git a/doc/img/generate_README_plots.m b/doc/img/generate_README_plots.m deleted file mode 100644 index c69d1e7d..00000000 --- a/doc/img/generate_README_plots.m +++ /dev/null @@ -1,194 +0,0 @@ -%% ===== Secondary sources =============================================== -conf = SFS_config_example; -conf.secondary_sources.size = 3; - -% === linear === -conf.secondary_sources.geometry = 'line'; -conf.secondary_sources.number = 21; -x0 = secondary_source_positions(conf); -figure; -figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); -draw_loudspeakers(x0,conf); -axis([-2 2 -2 1]); -pause(1) -print_png('secondary_sources_linear.png'); - -% === circular === -conf.secondary_sources.geometry = 'circle'; -conf.secondary_sources.number = 56; -x0 = secondary_source_positions(conf); -figure; -figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); -draw_loudspeakers(x0,conf); -axis([-2 2 -2 2]); -print_png('secondary_sources_circle.png'); - -% === box shaped === -conf.secondary_sources.geometry = 'box'; -conf.secondary_sources.number = 84; -x0 = secondary_source_positions(conf); -figure; -figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); -draw_loudspeakers(x0,conf); -axis([-2 2 -2 2]); -print_png('secondary_sources_box.png'); - -% === spherical array === -conf.secondary_sources.geometry = 'sphere'; % or 'spherical' -conf.secondary_sources.number = 225; -x0 = secondary_source_positions(conf); -figure; -figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); -draw_loudspeakers(x0,conf); -axis([-2 2 -2 2]); -print_png('secondary_sources_sphere.png'); - -% === arbitrary shaped arrays === -% create a stadium like shape by combining two half circles with two linear -% arrays -% first getting a full circle with 56 loudspeakers -conf.secondary_sources.geometry = 'circle'; -conf.secondary_sources.number = 56; -conf.secondary_sources.x0 = []; -x0 = secondary_source_positions(conf); -% store the first half cricle and move it up -x01 = x0(2:28,:); -x01(:,2) = x01(:,2) + ones(size(x01,1),1)*0.5; -% store the second half circle and move it down -x03 = x0(30:56,:); -x03(:,2) = x03(:,2) - ones(size(x03,1),1)*0.5; -% create a linear array -conf.secondary_sources.geometry = 'linear'; -conf.secondary_sources.number = 7; -conf.secondary_sources.size = 1; -x0 = secondary_source_positions(conf); -% rotate it and move it left -R = rotation_matrix(pi/2); -x02 = [(R*x0(:,1:3)')' (R*x0(:,4:6)')']; -x02(:,1) = x02(:,1) - ones(size(x0,1),1)*1.5; -x02(:,7) = x0(:,7); -% rotate it the other way around and move it right -R = rotation_matrix(-pi/2); -x04 = [(R*x0(:,1:3)')' (R*x0(:,4:6)')']; -x04(:,1) = x04(:,1) + ones(size(x0,1),1)*1.5; -x04(:,7) = x0(:,7); -% combine everything -conf.secondary_sources.x0 = [x01; x02; x03; x04]; -% if we gave the conf.secondary_sources.x0 to the secondary_source_positions -% function it will simply return the defined x0 matrix -x0 = secondary_source_positions(conf); -figure; -figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); -draw_loudspeakers(x0,conf); -axis([-2 2 -2.5 2.5]); -print_png('secondary_sources_arbitrary.png'); -conf.plot.realloudspeakers = true; -figure; -figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); -draw_loudspeakers(x0,conf); -axis([-2 2 -2.5 2.5]); -print_png('secondary_sources_arbitrary_realloudspeakers.png'); - -%% ===== Monochromatic sound fields ====================================== -% === stereo setup === -conf = SFS_config_example; -x0 = [-1 2 0 0 -1 0 1;1 2 0 0 -1 0 1]; -% [P,x,y,z] = sound_field_mono(X,Y,Z,x0,src,D,f,conf) -sound_field_mono([-2 2],[-1 3],0,x0,'ps',[1 1],800,conf) -print_png('sound_field_stereo.png'); - -% === WFS 3D === -conf = SFS_config_example; -conf.dimension = '3D'; -conf.secondary_sources.size = 3; -conf.secondary_sources.number = 225; -conf.secondary_sources.geometry = 'sphere'; -% [P,x,y,z,x0,win] = sound_field_mono_wfs_25d(X,Y,Z,xs,src,fconf); -sound_field_mono_wfs([-2 2],[-2 2],0,[0 -1 0],'pw',800,conf); -print_png('sound_field_wfs_3d_xy.png'); -sound_field_mono_wfs([-2 2],0,[-2 2],[0 -1 0],'pw',800,conf); -print_png('sound_field_wfs_3d_xz.png'); -sound_field_mono_wfs(0,[-2 2],[-2 2],[0 -1 0],'pw',800,conf); -print_png('sound_field_wfs_3d_yz.png'); - - -% simulating 2.5D WFS with circular array and a point source -conf = SFS_config_example; -conf.dimension = '2.5D'; -conf.plot.useplot = 1; -% [P,x,y,z,x0] = sound_field_mono_wfs(X,Y,Z,xs,src,f,conf); -[P,x,y,z,x0] = sound_field_mono_wfs([-2 2],[-2 2],0,[0 2.5 0],'ps',800,conf); -print_png('sound_field_wfs_25d.png'); -% plotting WFS with all secondary sources -x0_all = secondary_source_positions(conf); -[~,idx] = secondary_source_selection(x0,[0 2.5 0],'ps'); -x0_all(:,7) = zeros(1,size(x0_all,1)); -x0_all(idx,7) = x0(:,7); -plot_sound_field(P,x,y,z,x0_all,conf); -print_png('sound_field_wfs_25d_with_all_sources.png'); -% simulating 2.5D NFCHOA with circular array and a plane wave -conf = SFS_config_example; -conf.dimension = '2.5D'; -% sound_field_mono_nfchoa(X,Y,Z,xs,src,f,conf); -sound_field_mono_nfchoa([-2 2],[-2 2],0,[0 -1 0],'pw',800,conf); -print_png('sound_field_nfchoa_25d.png'); - -% 2D local WFS with box shaped array and circular virtual array -conf = SFS_config_example; -conf.resolution = 1000; -conf.dimension = '2D'; -conf.secondary_sources.geometry = 'box'; -conf.secondary_sources.number = 4*56; -conf.secondary_sources.size = 2; -conf.localsfs.vss.size = 0.4; -conf.localsfs.vss.center = [0 0 0]; -conf.localsfs.vss.geometry = 'circular'; -conf.localsfs.vss.number = 56; -sound_field_mono_localwfs([-1 1],[-1 1],0,[1.0 -1.0 0],'pw',7000,conf); -axis([-1.1 1.1 -1.1 1.1]); -print_png('sound_field_localwfs_2d.png'); - -% --- spatio-temporal snapshots of the sound field --- -conf = SFS_config_example; -conf.dimension = '2.5D'; -conf.plot.useplot = true; -% sound_field_imp_nfchoa(X,Y,Z,xs,src,t,conf) -[p,x,y,z,x0] = sound_field_imp_nfchoa([-2 2],[-2 2],0,[0 2 0],'ps',200,conf); -print_png('sound_field_imp_nfchoa_25d.png'); -conf.plot.usedb = true; -plot_sound_field(p,x,y,z,x0,conf); -print_png('sound_field_imp_nfchoa_25d_dB.png'); - - -% --- impulse response of the system --- -conf = SFS_config_example; -conf.ir.usehcomp = 0; -conf.wfs.usehpre = 0; -irs = dummy_irs; -[ir1,x0] = ir_wfs([0 0 0],pi/2,[0 2.5 0],'ps',irs,conf); -conf.wfs.usehpre = 1; -conf.wfs.hprefhigh = aliasing_frequency(x0); -ir2 = ir_wfs([0 0 0],pi/2,[0 2.5 0],'ps',irs,conf); -[a1,p,f] = easyfft(norm_signal(ir1(:,1)),conf); -a2 = easyfft(norm_signal(ir2(:,1)),conf); -figure; -figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); -semilogx(f,20*log10(a1),'-b',f,20*log10(a2),'-r'); -axis([10 20000 -80 -40]); -set(gca,'XTick',[10 100 250 1000 5000 20000]); -legend('w/o pre-filter','w pre-filter'); -xlabel('frequency / Hz'); -ylabel('magnitude / dB'); -print_png('impulse_response_wfs_25d.png'); -% alternative variant -conf = SFS_config_example; -[a,f] = freq_response_wfs([0 0 0],[0 2.5 0],'ps',conf); -figure; -figsize(conf.plot.size(1),conf.plot.size(2),conf.plot.size_unit); -semilogx(f,20*log10(a),'-r'); -axis([10 20000 -20 20]); -set(gca,'XTick',[10 100 250 1000 5000 20000]); -legend('w pre-filter'); -xlabel('frequency / Hz'); -ylabel('magnitude / dB'); -print_png('impulse_response_wfs_25d_mono.png'); diff --git a/doc/img/generate_plots.m b/doc/img/generate_plots.m new file mode 100644 index 00000000..cfef9326 --- /dev/null +++ b/doc/img/generate_plots.m @@ -0,0 +1,349 @@ +%% ===== Secondary sources =============================================== +conf = SFS_config; +conf.secondary_sources.size = 3; + +% === linear === +conf.secondary_sources.geometry = 'line'; +conf.secondary_sources.number = 21; +x0 = secondary_source_positions(conf); +figure; +figsize(540,404,'px'); +draw_loudspeakers(x0,conf); +axis([-2 2 -2 1]); +pause(1) +print_png('secondary_sources_linear.png'); + +conf.secondary_sources.logspread = 3.5; +x0 = secondary_source_positions(conf); +figure; +figsize(540,404,'px'); +draw_loudspeakers(x0,conf); +axis([-2 2 -2 1]); +pause(1) +print_png('secondary_sources_linear_log.png'); + +% === circular === +conf.secondary_sources.geometry = 'circle'; +conf.secondary_sources.number = 56; +x0 = secondary_source_positions(conf); +figure; +figsize(540,404,'px'); +draw_loudspeakers(x0,conf); +axis([-2 2 -2 2]); +set(gca, 'XTick', -2:1:2); set(gca, 'YTick', -2:1:2); +print_png('secondary_sources_circle.png'); + +% === box shaped === +conf.secondary_sources.geometry = 'box'; +conf.secondary_sources.number = 84; +x0 = secondary_source_positions(conf); +figure; +figsize(540,404,'px'); +draw_loudspeakers(x0,conf); +axis([-2 2 -2 2]); +set(gca, 'XTick', -2:1:2); set(gca, 'YTick', -2:1:2); +print_png('secondary_sources_box.png'); + +% === box shaped with smoothed edges === +conf.secondary_sources.geometry = 'rounded-box'; +conf.secondary_sources.number = 84; +conf.secondary_sources.corner_radius = 0.3; +x0 = secondary_source_positions(conf); +figure; +figsize(540,404,'px'); +draw_loudspeakers(x0,conf); +axis([-2 2 -2 2]); +set(gca, 'XTick', -2:1:2); set(gca, 'YTick', -2:1:2); +print_png('secondary_sources_rounded-box.png'); + +% === spherical array === +conf.secondary_sources.geometry = 'sphere'; % or 'spherical' +conf.secondary_sources.number = 225; +x0 = secondary_source_positions(conf); +figure; +figsize(540,404,'px'); +draw_loudspeakers(x0,conf); +axis([-2 2 -2 2]); +set(gca, 'XTick', -2:1:2); set(gca, 'YTick', -2:1:2); +print_png('secondary_sources_sphere.png'); + +% === arbitrary shaped arrays === +% create a stadium like shape by combining two half circles with two linear +% arrays +% first getting a full circle with 56 loudspeakers +conf.secondary_sources.geometry = 'circle'; +conf.secondary_sources.number = 56; +conf.secondary_sources.x0 = []; +x0 = secondary_source_positions(conf); +% store the first half cricle and move it up +x01 = x0(2:28,:); +x01(:,2) = x01(:,2) + ones(size(x01,1),1)*0.5; +% store the second half circle and move it down +x03 = x0(30:56,:); +x03(:,2) = x03(:,2) - ones(size(x03,1),1)*0.5; +% create a linear array +conf.secondary_sources.geometry = 'linear'; +conf.secondary_sources.number = 7; +conf.secondary_sources.size = 1; +x0 = secondary_source_positions(conf); +% rotate it and move it left +R = rotation_matrix(pi/2); +x02 = [(R*x0(:,1:3)')' (R*x0(:,4:6)')']; +x02(:,1) = x02(:,1) - ones(size(x0,1),1)*1.5; +x02(:,7) = x0(:,7); +% rotate it the other way around and move it right +R = rotation_matrix(-pi/2); +x04 = [(R*x0(:,1:3)')' (R*x0(:,4:6)')']; +x04(:,1) = x04(:,1) + ones(size(x0,1),1)*1.5; +x04(:,7) = x0(:,7); +% combine everything +conf.secondary_sources.geometry = 'custom'; +conf.secondary_sources.x0 = [x01; x02; x03; x04]; +% if we gave the conf.secondary_sources.x0 to the secondary_source_positions +% function it will simply return the defined x0 matrix +x0 = secondary_source_positions(conf); +figure; +figsize(540,404,'px'); +draw_loudspeakers(x0,conf); +axis([-2 2 -2.5 2.5]); +set(gca, 'XTick', -2:1:2); set(gca, 'YTick', -2:1:2); +print_png('secondary_sources_arbitrary.png'); +conf.plot.realloudspeakers = true; +figure; +figsize(540,404,'px'); +draw_loudspeakers(x0,conf); +axis([-2 2 -2.5 2.5]); +set(gca, 'XTick', -2:1:2); set(gca, 'YTick', -2:1:2); +print_png('secondary_sources_arbitrary_realloudspeakers.png'); + +%% ===== Monochromatic sound fields ====================================== +% === WFS 3D === +conf = SFS_config; +conf.dimension = '3D'; +conf.secondary_sources.size = 3; +conf.secondary_sources.number = 225; +conf.secondary_sources.geometry = 'sphere'; +% [P,x,y,z,x0,win] = sound_field_mono_wfs_25d(X,Y,Z,xs,src,fconf); +sound_field_mono_wfs([-2 2],[-2 2],0,[0 -1 0],'pw',800,conf); +axis([-2 2 -2 2]); +set(gca, 'XTick', -2:1:2); set(gca, 'YTick', -2:1:2); +print_png('sound_field_wfs_3d_xy.png'); +sound_field_mono_wfs([-2 2],0,[-2 2],[0 -1 0],'pw',800,conf); +axis([-2 2 -2 2]); +set(gca, 'XTick', -2:1:2); set(gca, 'YTick', -2:1:2); +print_png('sound_field_wfs_3d_xz.png'); +sound_field_mono_wfs(0,[-2 2],[-2 2],[0 -1 0],'pw',800,conf); +axis([-2 2 -2 2]); +set(gca, 'XTick', -2:1:2); set(gca, 'YTick', -2:1:2); +print_png('sound_field_wfs_3d_yz.png'); +conf.resolution = 100; +sound_field_mono_wfs([-2 2],[-2 2],[-2 2],[0 -1 0],'pw',800,conf); +print_png('sound_field_wfs_3d_xyz.png'); + +% === WFS 2.5D === +% simulating 2.5D WFS with circular array and a point source +conf = SFS_config; +conf.dimension = '2.5D'; +conf.plot.useplot = true; +conf.plot.normalisation = 'center'; +% [P,x,y,z,x0] = sound_field_mono_wfs(X,Y,Z,xs,src,f,conf); +[P,~,~,~,x0] = sound_field_mono_wfs([-2 2],[-2 2],0,[0 2.5 0],'ps',800,conf); +axis([-2 2 -2 2]); +set(gca, 'XTick', -2:1:2); set(gca, 'YTick', -2:1:2); +print_png('sound_field_wfs_25d.png'); +% plotting WFS with all secondary sources +x0_all = secondary_source_positions(conf); +[~,idx] = secondary_source_selection(x0_all,[0 2.5 0],'ps'); +x0_all(:,7) = zeros(1,size(x0_all,1)); +x0_all(idx,7) = x0(:,7); +conf.plot.realloudspeakers = true; +plot_sound_field(P,[-2 2],[-2 2],0,x0_all,conf); +axis([-2 2 -2 2]); +set(gca, 'XTick', -2:1:2); set(gca, 'YTick', -2:1:2); +print_png('sound_field_wfs_25d_with_all_sources.png'); +% simulating 2.5D NFCHOA with circular array and a plane wave +conf = SFS_config; +conf.dimension = '2.5D'; +% sound_field_mono_nfchoa(X,Y,Z,xs,src,f,conf); +sound_field_mono_nfchoa([-2 2],[-2 2],0,[0 -1 0],'pw',800,conf); +axis([-2 2 -2 2]); +set(gca, 'XTick', -2:1:2); set(gca, 'YTick', -2:1:2); +print_png('sound_field_nfchoa_25d.png'); + +% === 2D local WFS with box shaped array and circular virtual array === +X = [-1 1]; +Y = [-1 1]; +Z = 0; +xs = [1 -1 0]; +src = 'pw'; +f = 7000; +conf = SFS_config; +conf.resolution = 1000; +conf.dimension = '2D'; +conf.secondary_sources.geometry = 'box'; +conf.secondary_sources.number = 4*56; +conf.secondary_sources.size = 2; +conf.localwfs_vss.size = 0.4; +conf.localwfs_vss.center = [0 0 0]; +conf.localwfs_vss.geometry = 'circular'; +conf.localwfs_vss.number = 56; +sound_field_mono_localwfs_vss(X,Y,Z,xs,src,f,conf); +axis([-1.1 1.1 -1.1 1.1]); +print_png('sound_field_localwfs_2d.png'); + +% === stereo setup === +conf = SFS_config; +conf.plot.normalisation = 'center'; +x0 = [-1 2 0 0 -1 0 1;1 2 0 0 -1 0 1]; +% [P,x,y,z] = sound_field_mono(X,Y,Z,x0,src,D,f,conf) +sound_field_mono([-2 2],[-1 3],0,x0,'ps',[1 1],800,conf) +print_png('sound_field_stereo.png'); + +%% ===== spatio-temporal snapshots of the sound field ==================== +conf = SFS_config; +conf.dimension = '2.5D'; +conf.plot.useplot = true; +% sound_field_imp_nfchoa(X,Y,Z,xs,src,t,conf) +[p,x,y,z,x0] = sound_field_imp_nfchoa([-2 2],[-2 2],0,[0 2 0],'ps',0.005,conf); +axis([-2 2 -2 2]); +set(gca, 'XTick', -2:1:2); set(gca, 'YTick', -2:1:2); +print_png('sound_field_imp_nfchoa_25d.png'); +conf.plot.usedb = true; +plot_sound_field(p,[-2 2],[-2 2],0,x0,conf); +axis([-2 2 -2 2]); +set(gca, 'XTick', -2:1:2); set(gca, 'YTick', -2:1:2); +print_png('sound_field_imp_nfchoa_25d_dB.png'); +conf.plot.useplot = false; +conf.t0 = 'source'; +t_40cm = 0.4/conf.c; % time to travel 40 cm in s +t0 = 0.0005; % start time of focused source in s +[p_ps,~,~,~,x0_ps] = ... + sound_field_imp_wfs([-2 2],[-2 2],0,[1.9 0 0],'ps',t0+t_40cm,conf); +[p_pw,~,~,~,x0_pw] = ... + sound_field_imp_wfs([-2 2],[-2 2],0,[1 -2 0],'pw',t0-t_40cm,conf); +[p_fs,~,~,~,x0_fs] = ... + sound_field_imp_wfs([-2 2],[-2 2],0,[0 -1 0 0 1 0],'fs',t0,conf); +plot_sound_field(p_ps+p_pw+p_fs,[-2 2],[-2 2],0,[x0_ps; x0_pw; x0_fs],conf) +hold; +scatter(0,0,'k','x'); % origin of plane wave +scatter(1.9,0,'k','o'); % point source +scatter(0,-1,'k','o'); % focused source +hold off; +axis([-2 2 -2 2]); +set(gca, 'XTick', -2:1:2); set(gca, 'YTick', -2:1:2); +print_png('sound_field_imp_multiple_sources_dB.png'); + +%% ===== custom grids ==================================================== +conf = SFS_config; +conf.dimension = '3D'; +conf.secondary_sources.number = 225; +conf.secondary_sources.geometry = 'sphere'; +conf.resolution = 100; +conf.plot.normalisation = 'center'; +X = randi([-2000 2000],125000,1)/1000; +Y = randi([-2000 2000],125000,1)/1000; +Z = randi([-2000 2000],125000,1)/1000; +sound_field_mono_wfs(X,Y,Z,[0 -1 0],'pw',800,conf); +print_png('sound_field_wfs_3d_xyz_custom_grid.png'); +conf.plot.usedb = true; +conf.dimension = '2.5D'; +conf.secondary_sources.number = 64; +conf.secondary_sources.geometry = 'circle'; +sound_field_imp_nfchoa(X,Y,0,[0 2 0],'ps',0.005,conf); +axis([-2 2 -2 2]); +set(gca, 'XTick', -2:1:2); set(gca, 'YTick', -2:1:2); +print_png('sound_field_imp_nfchoa_25d_dB_custom_grid.png'); + +%% ===== modal windows =================================================== +conf = SFS_config; +conf.dimension = '2.5D'; +conf.secondary_sources.number = 16; +conf.secondary_sources.geometry = 'circular'; +conf.secondary_sources.size = 3; +conf.resolution = 300; +conf.plot.usedb = true; +conf.t0 = 'source'; +X = [-2,2]; +Y = [-2,2]; +Z = 0; +conf.modal_window = 'rect'; % default +sound_field_imp_nfchoa(X,Y,Z,[0 -1 0],'pw',0,conf); +print_png('sound_field_imp_nfchoa_25d_dB_rect.png'); +conf.modal_window = 'max-rE'; +sound_field_imp_nfchoa(X,Y,Z,[0 -1 0],'pw',0,conf); +print_png('sound_field_imp_nfchoa_25d_dB_max-rE.png'); +conf.modal_window = 'kaiser'; +conf.modal_window_parameter = 1.0; +sound_field_imp_nfchoa(X,Y,Z,[0 -1 0],'pw',0,conf); +print_png('sound_field_imp_nfchoa_25d_dB_kaiser.png'); +conf.modal_window = 'tukey'; +conf.modal_window_parameter = 0.5; +sound_field_imp_nfchoa(X,Y,Z,[0 -1 0],'pw',0,conf); +print_png('sound_field_imp_nfchoa_25d_dB_tukey.png'); + + +%% ===== impulse response of a spatial audio system ====================== +conf = SFS_config; +conf.t0 = 'source'; +X = [0 0 0]; +phi = 0; +xs = [2.5 0 0]; +src = 'ps'; +t = (1:1000)/conf.fs*1000; +hrtf = dummy_irs(conf); +[ir,~,delay] = ir_wfs(X,phi,xs,src,hrtf,conf); +figure; +figsize(540,404,'px'); +plot(t,ir(1:1000,1),'-g'); +hold on; +offset = round(delay*conf.fs); +plot(t,ir(1+offset:1000+offset,1),'-b'); +hold off; +xlabel('time / ms'); +ylabel('amplitude'); +print_png('impulse_response_wfs_25d.png'); +X = [0 0 0]; +head_orientation = [0 0]; +xs = [2.5 0 0]; +src = 'ps'; +conf = SFS_config; +conf.N = 1000; +conf.t0 = 'source'; +time_response_wfs(X,xs,src,conf) +axis([0 25 -0.005 0.025]); +print_png('impulse_response_wfs_25d_imp.png'); + + +%% ===== frequency response of a spatial audio system ==================== +X = [0 0 0]; +head_orientation = [pi/2 0]; +xs = [0 2.5 0]; +src = 'ps'; +hrtf = dummy_irs(conf); +conf = SFS_config; +conf.ir.usehcomp = false; +conf.wfs.usehpre = false; +[ir1,x0] = ir_wfs(X,head_orientation,xs,src,hrtf,conf); +conf.wfs.usehpre = true; +conf.wfs.hprefhigh = aliasing_frequency(x0,conf); +ir2 = ir_wfs(X,head_orientation,xs,src,hrtf,conf); +[a1,p,f] = spectrum_from_signal(norm_signal(ir1(:,1)),conf); +a2 = spectrum_from_signal(norm_signal(ir2(:,1)),conf); +figure; +figsize(540,404,'px'); +semilogx(f,20*log10(a1),'-b',f,20*log10(a2),'-r'); +axis([10 20000 -80 -40]); +set(gca,'XTick',[10 100 250 1000 5000 20000]); +legend('w/o pre-filter','w pre-filter'); +xlabel('frequency / Hz'); +ylabel('magnitude / dB'); +print_png('frequency_response_wfs_25d.png'); +% alternative variant +X = [0 0 0]; +xs = [0 2.5 0]; +src = 'ps'; +conf = SFS_config; +freq_response_wfs(X,xs,src,conf); +axis([10 20000 -40 0]); +print_png('frequency_response_wfs_25d_mono.png'); + diff --git a/doc/img/impulse_response_wfs_25d.png b/doc/img/impulse_response_wfs_25d.png index 7862b3b5..67f39ee9 100644 Binary files a/doc/img/impulse_response_wfs_25d.png and b/doc/img/impulse_response_wfs_25d.png differ diff --git a/doc/img/impulse_response_wfs_25d_imp.png b/doc/img/impulse_response_wfs_25d_imp.png new file mode 100644 index 00000000..84657a3c Binary files /dev/null and b/doc/img/impulse_response_wfs_25d_imp.png differ diff --git a/doc/img/impulse_response_wfs_25d_mono.png b/doc/img/impulse_response_wfs_25d_mono.png deleted file mode 100644 index 9bd94a54..00000000 Binary files a/doc/img/impulse_response_wfs_25d_mono.png and /dev/null differ diff --git a/doc/img/secondary_sources_arbitrary.png b/doc/img/secondary_sources_arbitrary.png index 5902084a..b71f128e 100644 Binary files a/doc/img/secondary_sources_arbitrary.png and b/doc/img/secondary_sources_arbitrary.png differ diff --git a/doc/img/secondary_sources_arbitrary_realloudspeakers.png b/doc/img/secondary_sources_arbitrary_realloudspeakers.png index 17b99870..3c8dc99c 100644 Binary files a/doc/img/secondary_sources_arbitrary_realloudspeakers.png and b/doc/img/secondary_sources_arbitrary_realloudspeakers.png differ diff --git a/doc/img/secondary_sources_box.png b/doc/img/secondary_sources_box.png index 461b6415..810976e8 100644 Binary files a/doc/img/secondary_sources_box.png and b/doc/img/secondary_sources_box.png differ diff --git a/doc/img/secondary_sources_circle.png b/doc/img/secondary_sources_circle.png index 2b856295..b48584cc 100644 Binary files a/doc/img/secondary_sources_circle.png and b/doc/img/secondary_sources_circle.png differ diff --git a/doc/img/secondary_sources_linear.png b/doc/img/secondary_sources_linear.png index a2961c53..9d870ff0 100644 Binary files a/doc/img/secondary_sources_linear.png and b/doc/img/secondary_sources_linear.png differ diff --git a/doc/img/secondary_sources_linear_log.png b/doc/img/secondary_sources_linear_log.png new file mode 100644 index 00000000..16ee1086 Binary files /dev/null and b/doc/img/secondary_sources_linear_log.png differ diff --git a/doc/img/secondary_sources_rounded-box.png b/doc/img/secondary_sources_rounded-box.png new file mode 100644 index 00000000..fb858969 Binary files /dev/null and b/doc/img/secondary_sources_rounded-box.png differ diff --git a/doc/img/secondary_sources_sphere.png b/doc/img/secondary_sources_sphere.png index 37ae7f5c..5ddddcab 100644 Binary files a/doc/img/secondary_sources_sphere.png and b/doc/img/secondary_sources_sphere.png differ diff --git a/doc/img/sound_field_imp_multiple_sources_dB.png b/doc/img/sound_field_imp_multiple_sources_dB.png new file mode 100644 index 00000000..db34a099 Binary files /dev/null and b/doc/img/sound_field_imp_multiple_sources_dB.png differ diff --git a/doc/img/sound_field_imp_nfchoa_25d.png b/doc/img/sound_field_imp_nfchoa_25d.png index 86de125d..0aa617c8 100644 Binary files a/doc/img/sound_field_imp_nfchoa_25d.png and b/doc/img/sound_field_imp_nfchoa_25d.png differ diff --git a/doc/img/sound_field_imp_nfchoa_25d_dB.png b/doc/img/sound_field_imp_nfchoa_25d_dB.png index 73978931..063ebe3f 100644 Binary files a/doc/img/sound_field_imp_nfchoa_25d_dB.png and b/doc/img/sound_field_imp_nfchoa_25d_dB.png differ diff --git a/doc/img/sound_field_imp_nfchoa_25d_dB_custom_grid.png b/doc/img/sound_field_imp_nfchoa_25d_dB_custom_grid.png new file mode 100644 index 00000000..c0a13c80 Binary files /dev/null and b/doc/img/sound_field_imp_nfchoa_25d_dB_custom_grid.png differ diff --git a/doc/img/sound_field_imp_nfchoa_25d_dB_kaiser.png b/doc/img/sound_field_imp_nfchoa_25d_dB_kaiser.png new file mode 100644 index 00000000..ffe8c0aa Binary files /dev/null and b/doc/img/sound_field_imp_nfchoa_25d_dB_kaiser.png differ diff --git a/doc/img/sound_field_imp_nfchoa_25d_dB_max-rE.png b/doc/img/sound_field_imp_nfchoa_25d_dB_max-rE.png new file mode 100644 index 00000000..786c9959 Binary files /dev/null and b/doc/img/sound_field_imp_nfchoa_25d_dB_max-rE.png differ diff --git a/doc/img/sound_field_imp_nfchoa_25d_dB_rect.png b/doc/img/sound_field_imp_nfchoa_25d_dB_rect.png new file mode 100644 index 00000000..83e9db06 Binary files /dev/null and b/doc/img/sound_field_imp_nfchoa_25d_dB_rect.png differ diff --git a/doc/img/sound_field_imp_nfchoa_25d_dB_tukey.png b/doc/img/sound_field_imp_nfchoa_25d_dB_tukey.png new file mode 100644 index 00000000..d696da11 Binary files /dev/null and b/doc/img/sound_field_imp_nfchoa_25d_dB_tukey.png differ diff --git a/doc/img/sound_field_localwfs_2d.png b/doc/img/sound_field_localwfs_2d.png index a1776342..2bba5c4d 100644 Binary files a/doc/img/sound_field_localwfs_2d.png and b/doc/img/sound_field_localwfs_2d.png differ diff --git a/doc/img/sound_field_nfchoa_25d.png b/doc/img/sound_field_nfchoa_25d.png index 9f386d03..3e9d1c11 100644 Binary files a/doc/img/sound_field_nfchoa_25d.png and b/doc/img/sound_field_nfchoa_25d.png differ diff --git a/doc/img/sound_field_stereo.png b/doc/img/sound_field_stereo.png index 457198df..0f482cc5 100644 Binary files a/doc/img/sound_field_stereo.png and b/doc/img/sound_field_stereo.png differ diff --git a/doc/img/sound_field_wfs_25d.png b/doc/img/sound_field_wfs_25d.png index 0d293ade..37c33ca7 100644 Binary files a/doc/img/sound_field_wfs_25d.png and b/doc/img/sound_field_wfs_25d.png differ diff --git a/doc/img/sound_field_wfs_25d_with_all_sources.png b/doc/img/sound_field_wfs_25d_with_all_sources.png index fcd529b2..33ae1e59 100644 Binary files a/doc/img/sound_field_wfs_25d_with_all_sources.png and b/doc/img/sound_field_wfs_25d_with_all_sources.png differ diff --git a/doc/img/sound_field_wfs_3d_xy.png b/doc/img/sound_field_wfs_3d_xy.png index d7c4efbc..25cb4c01 100644 Binary files a/doc/img/sound_field_wfs_3d_xy.png and b/doc/img/sound_field_wfs_3d_xy.png differ diff --git a/doc/img/sound_field_wfs_3d_xyz.png b/doc/img/sound_field_wfs_3d_xyz.png new file mode 100644 index 00000000..3081caad Binary files /dev/null and b/doc/img/sound_field_wfs_3d_xyz.png differ diff --git a/doc/img/sound_field_wfs_3d_xyz_custom_grid.png b/doc/img/sound_field_wfs_3d_xyz_custom_grid.png new file mode 100644 index 00000000..a65d8108 Binary files /dev/null and b/doc/img/sound_field_wfs_3d_xyz_custom_grid.png differ diff --git a/doc/img/sound_field_wfs_3d_xz.png b/doc/img/sound_field_wfs_3d_xz.png index cb51aefb..975d0f95 100644 Binary files a/doc/img/sound_field_wfs_3d_xz.png and b/doc/img/sound_field_wfs_3d_xz.png differ diff --git a/doc/img/sound_field_wfs_3d_yz.png b/doc/img/sound_field_wfs_3d_yz.png index ecf9411a..bbcf569e 100644 Binary files a/doc/img/sound_field_wfs_3d_yz.png and b/doc/img/sound_field_wfs_3d_yz.png differ diff --git a/doc/img/tu_berlin_hrtf.jpg b/doc/img/tu_berlin_hrtf.jpg new file mode 100644 index 00000000..7bdf1ae4 Binary files /dev/null and b/doc/img/tu_berlin_hrtf.jpg differ diff --git a/doc/img/university_rostock_loudspeaker_array.jpg b/doc/img/university_rostock_loudspeaker_array.jpg new file mode 100644 index 00000000..06a4485d Binary files /dev/null and b/doc/img/university_rostock_loudspeaker_array.jpg differ diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 00000000..180e3a2d --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,16 @@ +.. _sec-readme: + +.. include:: ../README.rst + +.. toctree:: + :hidden: + + secondary-sources + frequency-domain + time-domain + modal-window + custom-grid + binaural-simulations + helper-functions + plotting + versions diff --git a/doc/modal-window.rst b/doc/modal-window.rst new file mode 100644 index 00000000..ef28fb7c --- /dev/null +++ b/doc/modal-window.rst @@ -0,0 +1,68 @@ +.. _sec-modal-window: + +Modal Windows +============= + +In the time-domain implementation of |NFC-HOA| it is possible to apply +different weighting factors to each mode of the driving signals in the circular +harmonics domain by changing the ``conf.modal_window`` configuration parameter. +Using a weighting window that is smoother than the default rectangular window, +causes a concentration of energy to fewer loudspeakers. + +.. sourcecode:: matlab + + conf = SFS_config; + conf.dimension = '2.5D'; + conf.secondary_sources.number = 16; + conf.secondary_sources.geometry = 'circular'; + conf.secondary_sources.size = 3; + conf.resolution = 300; + conf.plot.usedb = true; + conf.t0 = 'source'; + X = [-2,2]; + Y = [-2,2]; + Z = 0; + conf.modal_window = 'rect'; % default + sound_field_imp_nfchoa(X,Y,Z,[0 -1 0],'pw',0,conf); + %print_png('sound_field_imp_nfchoa_25d_dB_rect.png'); + conf.modal_window = 'max-rE'; + sound_field_imp_nfchoa(X,Y,Z,[0 -1 0],'pw',0,conf); + %print_png('sound_field_imp_nfchoa_25d_dB_max-rE.png'); + conf.modal_window = 'kaiser'; + conf.modal_window_parameter = 1.0; + sound_field_imp_nfchoa(X,Y,Z,[0 -1 0],'pw',0,conf); + %print_png('sound_field_imp_nfchoa_25d_dB_kaiser.png'); + conf.modal_window = 'tukey'; + conf.modal_window_parameter = 0.5; + sound_field_imp_nfchoa(X,Y,Z,[0 -1 0],'pw',0,conf); + %print_png('sound_field_imp_nfchoa_25d_dB_tukey.png'); + +.. figure:: img/sound_field_imp_nfchoa_25d_dB_rect.png + :align: center + + Sound pressure in decibel of a broadband impulse plane wave synthesized by + 2.5D |NFC-HOA| using a rectangular window. The plane wave propagates + into the direction of (0,-1,0). + +.. figure:: img/sound_field_imp_nfchoa_25d_dB_max-rE.png + :align: center + + Sound pressure in decibel of a broadband impulse plane wave synthesized by + 2.5D |NFC-HOA| using a max-rE window. The plane wave propagates into the + direction of (0,-1,0). + +.. figure:: img/sound_field_imp_nfchoa_25d_dB_kaiser.png + :align: center + + Sound pressure in decibel of a broadband impulse plane wave synthesized by + 2.5D |NFC-HOA| using a Kaiser window. The plane wave propagates into the + direction of (0,-1,0). + +.. figure:: img/sound_field_imp_nfchoa_25d_dB_tukey.png + :align: center + + Sound pressure in decibel of a broadband impulse plane wave synthesized by + 2.5D |NFC-HOA| using a modified Tukey window. The plane wave propagates into + the direction of (0,-1,0). + +.. vim: filetype=rst spell: diff --git a/doc/plotting.rst b/doc/plotting.rst new file mode 100644 index 00000000..17579495 --- /dev/null +++ b/doc/plotting.rst @@ -0,0 +1,16 @@ +.. _sec-plotting: + +Plotting +======== + +The Toolbox provides you with a function for plotting your simulated sound +fields (``plot_sound_field()``) and adding loudspeaker symbols to the figure +(``draw_loudspeakers()``). If you have gnuplot installed, you can use the +functions ``gp_save_matrix()`` and ``gp_save_loudspeakers()`` to save your data +in a way that it can be used with gnuplot. An example use case can be found `at +this plot of a plane wave`_ which includes the Matlab/Octave code to generate +the data and the gnuplot script for plotting it. + +.. _at this plot of a plane wave: https://github.com/hagenw/phd-thesis/tree/master/02_theory_of_sound_field_synthesis/fig2_04 + +.. vim: filetype=rst spell: diff --git a/doc/requirements.txt b/doc/requirements.txt new file mode 100644 index 00000000..82133027 --- /dev/null +++ b/doc/requirements.txt @@ -0,0 +1,2 @@ +sphinx +sphinx_rtd_theme diff --git a/doc/secondary-sources.rst b/doc/secondary-sources.rst new file mode 100644 index 00000000..0c268553 --- /dev/null +++ b/doc/secondary-sources.rst @@ -0,0 +1,257 @@ +.. _sec-secondary-sources: + +Secondary Sources +================= + +The Toolbox comes with a function which can generate different common +shapes of loudspeaker arrays for you. At the moment linear, circular, +box shaped and spherical arrays are supported. + +Before showing the different geometries, we start with some common +settings. First we get a configuration struct and set the array +size/diameter to 3 m. + +.. sourcecode:: matlab + + conf = SFS_config; + conf.secondary_sources.size = 3; + +Linear array +------------ + +.. sourcecode:: matlab + + conf = SFS_config; + conf.secondary_sources.geometry = 'line'; % or 'linear' + conf.secondary_sources.number = 21; + x0 = secondary_source_positions(conf); + figure; + figsize(540,404,'px'); + draw_loudspeakers(x0,conf); + axis([-2 2 -2 1]); + %print_png('img/secondary_sources_linear.png'); + +.. figure:: img/secondary_sources_linear.png + :align: center + + Linear loudspeaker array with a length of 3m consiting of 21 loudspeakers. + +You can also create logarithmic spacing for a linear array setting +``conf.secondary_sources.logspread`` different from its default value of +``1.0``. For values smaller than 1 the secondary sources will be more dense at +the edges of the array, whereas for larger values they will be more dense at the +center. + +.. sourcecode:: matlab + + conf = SFS_config; + conf.secondary_sources.geometry = 'line'; + conf.secondary_sources.number = 21; + conf.secondary_sources.logspread = 3.5; + x0 = secondary_source_positions(conf); + figure; + figsize(504,404,'px'); + draw_loudspeakers(x0,conf); + axis([-2 2 -2 1]); + %print_png('img/secondary_sources_linear_log.png'); + +.. figure:: img/secondary_sources_linear_log.png + :align: center + + Linear loudspeaker array with a length of 3m consiting of 21 logarithmically + spaced loudspeakers. + +Circular array +-------------- + +.. sourcecode:: matlab + + conf = SFS_config; + conf.secondary_sources.geometry = 'circle'; % or 'circular' + conf.secondary_sources.number = 56; + x0 = secondary_source_positions(conf); + figure; + figsize(540,404,'px'); + draw_loudspeakers(x0,conf); + axis([-2 2 -2 2]); + %print_png('img/secondary_sources_circle.png'); + +.. figure:: img/secondary_sources_circle.png + :align: center + + Circular loudspeaker array with a diameter of 3m consiting of 56 + loudspeakers. + +Box shaped array +---------------- + +.. sourcecode:: matlab + + conf = SFS_config; + conf.secondary_sources.geometry = 'box'; + conf.secondary_sources.number = 84; + x0 = secondary_source_positions(conf); + figure; + figsize(540,404,'px'); + draw_loudspeakers(x0,conf); + axis([-2 2 -2 2]); + %print_png('img/secondary_sources_box.png'); + +.. figure:: img/secondary_sources_box.png + :align: center + + Box shaped loudspeaker array with a diameter of 3m consisting of 84 + loudspeakers. + +Box shaped array with rounded edges +----------------------------------- + +``conf.secondary_sources.edge_radius`` defines the bending radius of the +corners. It can be chosen in a range between ``0.0`` and the half of +``conf.secondary_sources.size``. While the prior represents a square box +the latter yields a circle. Note that the square box behaves it little +bit different than the Box Shaped Array since loudspeakers might also be +place directly in the corners of the box. + +.. sourcecode:: matlab + + conf = SFS_config; + conf.secondary_sources.geometry = 'rounded-box'; + conf.secondary_sources.number = 84; + conf.secondary_sources.corner_radius = 0.3; + x0 = secondary_source_positions(conf); + figure; + figsize(540,404,'px'); + draw_loudspeakers(x0,conf); + axis([-2 2 -2 2]); + %print_png('img/secondary_sources_rounded-box.png'); + +.. figure:: img/secondary_sources_rounded-box.png + :align: center + + Box shaped loudspeaker array with rounded edges. It has again a diameter of + 3m, consists of 84 loudspeakers and has a edge bending factor of 0.3. + +Spherical array +--------------- + +For a spherical array you need a grid to place the secondary sources on the +sphere. At the moment we provide grids with the Toolbox, that can be found in +the `corresponding folder of the data repository`_. You have to specify your +desired grid, for example ``conf.secondary_sources.grid = +'equally_spaced_points'``. The ``secondary_source_positions()`` functions will +then automatically download the desired grid from that web page and stores it +under ``<$SFS_MAIN_PATH>/data``. If the download is not working (which can +happen especially under Matlab and Windows) you can alternatively checkout or +download the whole `data repository`_ to the data folder, or use the ``gauss`` +grid which is calculated on the fly. + +.. _corresponding folder of the data repository: + https://github.com/sfstoolbox/data/tree/master/spherical_grids +.. _data repository: https://github.com/sfstoolbox/data + +.. sourcecode:: matlab + + conf = SFS_config; + conf.secondary_sources.size = 3; + conf.secondary_sources.geometry = 'sphere'; % or 'spherical' + conf.secondary_sources.grid = 'equally_spaced_points'; + conf.secondary_sources.number = 225; + x0 = secondary_source_positions(conf); + figure; + figsize(540,404,'px'); + draw_loudspeakers(x0,conf); + axis([-2 2 -2 2]); + %print_png('img/secondary_sources_sphere.png'); + +.. figure:: img/secondary_sources_sphere.png + :align: center + + Spherical loudspeaker array with a diameter of 3m consiting of 225 + loudspeakers arranged on a grid with equally spaced points. + +Arbitrary shaped arrays +----------------------- + +You can create arbitrarily shaped arrays by setting +``conf.secondary_sources.geometry`` to ``'custom'`` and define the values of the +single loudspeaker directly in the ``conf.secondary_sources.x0`` matrix. The +rows of the matrix contain the single loudspeakers and the six columns are ``[x +y z nx ny nz w]``, the position and direction and weight of the single +loudspeakers. The weight ``w`` is a factor the driving function of this +particular loudspeaker is multiplied with in a function that calculates the +sound field from the given driving signals and secondary sources. For |WFS| +``w`` could include the tapering window, a spherical grid weight, and the +:math:`r^2 \cos(\theta)` weights for integration on a sphere. + +.. sourcecode:: matlab + + conf = SFS_config; + % create a stadium like shape by combining two half circles with two linear + % arrays + % first getting a full circle with 56 loudspeakers + conf.secondary_sources.geometry = 'circle'; + conf.secondary_sources.number = 56; + conf.secondary_sources.x0 = []; + x0 = secondary_source_positions(conf); + % store the first half cricle and move it up + x01 = x0(2:28,:); + x01(:,2) = x01(:,2) + ones(size(x01,1),1)*0.5; + % store the second half circle and move it down + x03 = x0(30:56,:); + x03(:,2) = x03(:,2) - ones(size(x03,1),1)*0.5; + % create a linear array + conf.secondary_sources.geometry = 'line'; + conf.secondary_sources.number = 7; + conf.secondary_sources.size = 1; + x0 = secondary_source_positions(conf); + % rotate it and move it left + R = rotation_matrix(pi/2); + x02 = [(R*x0(:,1:3)')' (R*x0(:,4:6)')']; + x02(:,1) = x02(:,1) - ones(size(x0,1),1)*1.5; + x02(:,7) = x0(:,7); + % rotate it the other way around and move it right + R = rotation_matrix(-pi/2); + x04 = [(R*x0(:,1:3)')' (R*x0(:,4:6)')']; + x04(:,1) = x04(:,1) + ones(size(x0,1),1)*1.5; + x04(:,7) = x0(:,7); + % combine everything + conf.secondary_sources.geometry = 'custom'; + conf.secondary_sources.x0 = [x01; x02; x03; x04]; + % if we gave the conf.x0 to the secondary_source_positions function it will + % simply return the defined x0 matrix + x0 = secondary_source_positions(conf); + figure; + figsize(540,404,'px'); + draw_loudspeakers(x0,conf); + axis([-2 2 -2.5 2.5]); + %print_png('img/secondary_sources_arbitrary.png'); + +.. figure:: img/secondary_sources_arbitrary.png + :align: center + + Custom arena shaped loudspeaker array consiting of 70 loudspeakers. + +Plot loudspeaker symbols +------------------------ + +For two dimensional setups you can plot the secondary sources with +loudspeaker symbols, for example the following will replot the last +array. + +.. sourcecode:: matlab + + conf.plot.realloudspeakers = true; + figure; + figsize(540,404,'px'); + draw_loudspeakers(x0,conf); + axis([-2 2 -2.5 2.5]); + %print_png('img/secondary_sources_arbitrary_realloudspeakers.png'); + +.. figure:: img/secondary_sources_arbitrary_realloudspeakers.png + :align: center + + Custom arena shaped loudspeaker array consiting of 70 loudspeakers, plotted + using loudspeaker symbols instead of circles for the single loudspeakers. + +.. vim: filetype=rst spell: diff --git a/doc/time-domain.rst b/doc/time-domain.rst new file mode 100644 index 00000000..3c5adce0 --- /dev/null +++ b/doc/time-domain.rst @@ -0,0 +1,89 @@ +.. _sec-time-domain: + +Time Domain +=========== + +With the files in the folder ``SFS_time_domain`` you can simulate snapshots in time +of an impulse originating from your |WFS| or |NFC-HOA| system. + +In the following we will create a snapshot in time after 5 ms for +a broadband virtual point source placed at (0 2 0) m for 2.5D |NFC-HOA|. + +.. sourcecode:: matlab + + conf = SFS_config; + conf.dimension = '2.5D'; + conf.plot.useplot = true; + % sound_field_imp_nfchoa(X,Y,Z,xs,src,t,conf) + [p,x,y,z,x0] = sound_field_imp_nfchoa([-2 2],[-2 2],0,[0 2 0],'ps',0.005,conf); + %print_png('img/sound_field_imp_nfchoa_25d.png'); + +.. figure:: img/sound_field_imp_nfchoa_25d.png + :align: center + + Sound pressure of a broadband impulse point source synthesized by 2.5D + |NFC-HOA|. The point source is placed at (0,2,0) m and the time snapshot is + shown 5 ms after the first secondary source was active. + +The output can also be plotted in dB by setting ``conf.plot.usedb = true;``. +In this case the default color map is changed and a color bar is plotted +in the figure. For none dB plots no color bar is shown in the plots. In +these cases the color coding goes always from -1 to 1, with clipping of +larger values. + +.. sourcecode:: matlab + + conf.plot.usedb = true; + plot_sound_field(p,[-2 2],[-2 2],0,x0,conf); + %print_png('img/sound_field_imp_nfchoa_25d_dB.png'); + +.. figure:: img/sound_field_imp_nfchoa_25d_dB.png + :align: center + + Sound pressure in decibel of the same broadband impulse point source as in + the figure above. + +You could change the color map yourself doing the following before the +plot command. + +.. sourcecode:: matlab + + conf.plot.colormap = 'jet'; % Matlab rainbow color map + +If you want to simulate more than one virtual source, it is a good idea +to set the starting time of your simulation to start with the activity +of your virtual source and not with the secondary sources, which is the +default behavior. You can change this by setting +``conf.t0 = 'source'``. + +.. sourcecode:: matlab + + conf.plot.useplot = false; + conf.t0 = 'source'; + t_40cm = 0.4/conf.c; % time to travel 40 cm in s + t0 = 0.0005; % start time of focused source in s + [p_ps,~,~,~,x0_ps] = ... + sound_field_imp_wfs([-2 2],[-2 2],0,[1.9 0 0],'ps',t0+t_40cm,conf); + [p_pw,~,~,~,x0_pw] = ... + sound_field_imp_wfs([-2 2],[-2 2],0,[1 -2 0],'pw',t0-t_40cm,conf); + [p_fs,~,~,~,x0_fs] = ... + sound_field_imp_wfs([-2 2],[-2 2],0,[0 -1 0 0 1 0],'fs',t0,conf); + plot_sound_field(p_ps+p_pw+p_fs,[-2 2],[-2 2],0,[x0_ps; x0_pw; x0_fs],conf) + hold; + scatter(0,0,'kx'); % origin of plane wave + scatter(1.9,0,'ko'); % point source + scatter(0,-1,'ko'); % focused source + hold off; + %print_png('sound_field_imp_multiple_sources_dB.png'); + +.. figure:: img/sound_field_imp_multiple_sources_dB.png + :align: center + + Sound pressure in decibel of a boradband impulse plane wave, point source, + and focused source synthesized all by 2.5D |WFS|. The plane wave is + traveling into the direction (1,-2,0) and shown 0.7 ms before it starting + point at (0,0,0). The point source is placed at (1.9,0,0) m and shown 1.7 ms + after its start. The focused source is placed at (0,-1,0) m and shown 0.5 ms + after its start. + +.. vim: filetype=rst spell: diff --git a/doc/versions.rst b/doc/versions.rst new file mode 100644 index 00000000..203530cd --- /dev/null +++ b/doc/versions.rst @@ -0,0 +1,6 @@ +.. _sec-versions: + +Version History +=============== + +.. include:: ../NEWS diff --git a/validation/README.rst b/validation/README.rst new file mode 100644 index 00000000..bd98b9e7 --- /dev/null +++ b/validation/README.rst @@ -0,0 +1,22 @@ +Validation scripts +================== + +This folder contains test scripts for the most important functions of the SFS +Toolbox. + +In order to check if no error during execution occurs, run: + +.. sourcecode:: Matlab + + >> test_all(0) + +which should return a ``1`` if everything runs smoothly. + +In order to get a detailed overview if the algorithms return desired results you +have to check the resulting plots via inspection. To do so run + +.. sourcecode:: Matlab + + >> test_all(1) + +and follow the instructions presented in the command prompt. diff --git a/validation/test_all.m b/validation/test_all.m new file mode 100644 index 00000000..5dc62e94 --- /dev/null +++ b/validation/test_all.m @@ -0,0 +1,155 @@ +function status = test_all(modus) +%TEST_ALL runs all tests +% +% Usage: test_all(modus) +% +% Input parameters: +% modus - 0: numerical +% 1: visual +% +% Output parameters: +% status - true or false + +% TEST_ALL(modus) runs all test function that should be checked before +% preparing a new release of the toolbox. + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters =================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Main ============================================================ +if modus + disp('Running graphical modus, please inspect the figures'); + disp(''); + disp('Running "test_colormaps(1)"'); + test_colormaps(1); + disp('Hit Enter to continue'); + pause + disp('Running "test_delayline(1)"'); + test_delayline(1); + disp('Hit Enter to continue'); + pause + disp('Running "test_driving_functions_imp_with_delay(1)"'); + test_driving_functions_imp_with_delay(1); + disp('Hit Enter to continue'); + pause + disp('Running "test_driving_functions(1)"'); + test_driving_functions(1); + disp('Hit Enter to continue'); + pause + disp('Running "test_hrtf_extrapolation(1,''QU_KEMAR'')"'); + test_hrtf_extrapolation(1,'QU_KEMAR'); + disp('Hit Enter to continue'); + pause + disp('Running "test_interpolation_methods(1)"'); + test_interpolation_methods(1); + pause + disp('Running "test_interpolation_point_selection(1)"'); + test_interpolation_point_selection(1); + disp('Hit Enter to continue'); + pause + disp('Running "test_localwfs_vss(1)"'); + test_localwfs_vss(1); + disp('Hit Enter to continue'); + pause + disp('Running "test_localwfs_sbl(1)"'); + test_localwfs_sbl(1); + disp('Hit Enter to continue'); + pause + disp('Running "test_non_regular_grid(1)"'); + test_non_regular_grid(1); + disp('Hit Enter to continue'); + pause + disp('Running "test_plot(1)"'); + test_plotting(1); + disp('Hit Enter to continue'); + pause + disp('Running "test_secondary_source_positions(1)"'); + test_secondary_source_positions(1); + disp('Hit Enter to continue'); + pause + disp('Running "test_wfs_25d(1)"'); + test_wfs_25d(1); + disp('Hit Enter to continue'); + pause + disp('Running "test_imp_25d(1)"'); + test_imp_25d(1); + disp('Hit Enter to continue'); + pause + disp('Running "test_fft_ifft(1)"'); + test_spectrum_signal_conversion(1); + disp('Hit Enter to continue'); + pause + disp('Running "test_modal_weighting(1)"'); + test_modal_weighting(1); + disp('Hit Enter to continue'); + pause + disp('Running "test_linkwitz_riley(1)"'); + test_linkwitz_riley(1); + disp('Hit Enter to continue'); + pause + disp('Running "test_sphbesselh_zeros(1)"'); + test_sphbesselh_zeros(1); +else + if ~all([test_binaural_synthesis(0); ... + test_delayline(0); ... + test_driving_functions_imp_with_delay(0); ... + test_driving_functions(0); ... + test_hrtf_extrapolation(0,'QU_KEMAR'); ... + test_interpolation_point_selection(0); ... + test_localwfs_vss(0); ... + test_localwfs_sbl(0); ... + test_non_regular_grid(0); ... + test_secondary_source_diameter(0); ... + test_secondary_source_positions(0); ... + test_secondary_source_selection(0); ... + test_tapering_window(0); ... + test_wfs_25d(0); ... + test_imp_25d(0); ... + test_spectrum_signal_conversion(0); + test_modal_weighting(0); + test_linkwitz_riley(0); + test_sphbesselh_zeros(0); + %test_wfs_iir_prefilter(0); ... % needs DSP Tooblox + ]) + return; + end +end + + +status = true; diff --git a/validation/test_binaural_synthesis.m b/validation/test_binaural_synthesis.m index 287dab05..3267a97c 100644 --- a/validation/test_binaural_synthesis.m +++ b/validation/test_binaural_synthesis.m @@ -1,61 +1,70 @@ -function test_binaural_synthesis() -%TEST_BINAURAL_SYNTHESIS tests the correctness of the binaural synthesis -%functions +function status = test_binaural_synthesis(modus) +%TEST_BINAURAL_SYNTHESIS tests the binaural synthesis functions % -% Usage: test_binaural_synthesis() +% Usage: status = test_binaural_synthesis(modus) % -% TEST_BINAURAL_SYNTHESIS() tests the ir_wfs_25d function for different +% Input parameters: +% modus - 0: numerical +% 1: visual (not available) +% +% Output parameters: +% status - true or false + +% TEST_BINAURAL_SYNTHESIS(modus) tests the ir_wfs function for different % loudspeaker arrays and source models. %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% The MIT License (MIT) * % * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% The SFS 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. * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** -%% ===== Checking of input parameters =================================== -nargmin = 0; -nargmax = 0; +status = false; + + +%% ===== Checking of input parameters ==================================== +nargmin = 1; +nargmax = 1; narginchk(nargmin,nargmax); +if modus + warning('%s: visual modus not available.',upper(mfilename)); +end %% ===== Settings ======================================================== +conf = SFS_config; conf.c = 343; conf.fs = 44100; conf.secondary_sources.x0 = []; conf.secondary_sources.center = [0 0 0]; conf.secondary_sources.size = 3; -conf.ir.useoriglength = false; conf.ir.usehcomp = false; conf.ir.useinterpolation = true; -conf.N = 2048; +conf.N = 4096; conf.dimension = '2.5D'; conf.driving_functions = 'default'; conf.usetapwin = true; @@ -64,22 +73,24 @@ function test_binaural_synthesis() conf.wfs.hpretype = 'FIR'; conf.wfs.hpreflow = 50; conf.wfs.hprefhigh = 1200; -conf.usefracdelay = false; +conf.delayline.resampling = 'none'; +conf.delayline.filter = 'integer'; conf.debug = 0; conf.showprogress = false; %% ===== Main ============================================================ -% check if HRTF data set is available, download otherwise +% Check if HRTF data set is available, download otherwise basepath = get_sfs_path(); -hrtf_file = [basepath '/data/HRTFs/QU_KEMAR_anechoic_3m.mat']; +hrtf_file = [basepath '/data/HRTFs/QU_KEMAR_anechoic_3m.sofa']; if ~exist(hrtf_file,'file') - url = ['https://dev.qu.tu-berlin.de/projects/measurements/repository/', ... - 'raw/2010-11-kemar-anechoic/mat/QU_KEMAR_anechoic_3m.mat']; + disp('Download'); + url = ['https://github.com/sfstoolbox/data/blob/master/', ... + 'HRTFs/QU_KEMAR_anechoic_3m.sofa?raw=true']; download_file(url,hrtf_file); end -% load HRTF data set -hrtf = read_irs(hrtf_file,conf); +% Load HRTF data set +hrtf = SOFAload(hrtf_file); %% ===== WFS 2.5D ======================================================== @@ -139,3 +150,6 @@ function test_binaural_synthesis() src = 'fs'; xs = [0.5 0.5 0 -1 -1 0]; ir_wfs(X,phi,xs,src,hrtf,conf); + + +status = true; diff --git a/validation/test_colormaps.m b/validation/test_colormaps.m new file mode 100644 index 00000000..01af5bca --- /dev/null +++ b/validation/test_colormaps.m @@ -0,0 +1,103 @@ +function status = test_colormaps(modus) +%TEST_COLORMAPS does sound field plots with different colormaps +% +% Usage: status = test_colormaps(modus) +% +% Input parameters: +% modus - 0: numerical (not available) +% 1: visual +% +% Output parameters: +% status - true or false + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters ==================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); +if ~modus + warning('%s: numerical modus not available.',upper(mfilename)); + status = true; + return; +end + + +%% ===== Configuration =================================================== +conf = SFS_config; +xs = [0 -1 0]; +src = 'pw'; +f = 1000; +t = 0.007; +X = [-2 2]; +Y = [-2 2]; +Z = 0; + + +%% ===== Sound field plots =============================================== +conf.plot.normalisation = 'center'; +conf.plot.usedb = true; + +color_maps = { ... + 'yellowred'; ... + 'gray'; ... + }; +color_maps_reversed = { ... + 'magma'; ... + 'inferno'; ... + 'bone'; ... + }; + +[P,~,~,~,x0] = sound_field_mono_wfs([-2 2],[-2 2],0,xs,src,f,conf); +p = sound_field_imp_wfs(X,Y,Z,xs,src,t,conf); + +for ii=1:length(color_maps) + conf.plot.colormap = color_maps{ii}; + plot_sound_field(P,X,Y,Z,x0,conf) + title(sprintf('Monochromatic, %s',color_maps{ii})) + plot_sound_field(p,X,Y,Z,x0,conf) + title(sprintf('Time-domain, %s',color_maps{ii})) +end +for ii=1:length(color_maps_reversed) + conf.plot.colormap = color_maps_reversed{ii}; + plot_sound_field(P,X,Y,Z,x0,conf) + colormap(flipud(colormap)) + title(sprintf('Monochromatic, %s reversed',color_maps_reversed{ii})) + plot_sound_field(p,X,Y,Z,x0,conf) + colormap(flipud(colormap)) + title(sprintf('Time-domain, %s reversed',color_maps_reversed{ii})) +end + + +status = true; diff --git a/validation/test_delayline.m b/validation/test_delayline.m index cb9aeff7..24a56791 100644 --- a/validation/test_delayline.m +++ b/validation/test_delayline.m @@ -1,116 +1,133 @@ -function test_delayline() -%TEST_DELAYLINE evaluates the delayline implementation -% -% Usage: test_delayline() -% -% TEST_DELAYLINE() tests the implementation of the delayline. For different -% types (conf.usefracdelay) you have to manual edit the code below at the -% moment. - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Configuration ================================================== -% Delays to evaluate -dt=[-5 -2.5 0 2.5 5]; -%dt=[-1 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1]; -%dt=[0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1]; -%dt=1*[0 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.1]; -%dt=linspace(0,2,200); -% Parameters for delayline -conf.usefracdelay = true; -fracdelay_methods = { ... - 'least_squares'; ... - 'resample'; ... - 'interp1'; ... -}; - -conf.fracdelay_method = 'interp1'; - -% Length of input signal -L=256; -% Create frequency axis -w = (0:1:(L-1))/L; -wpi = w*pi; -wpi2=wpi(2:L); -% Set up input signal -insig = zeros(L,1); -insig(L/2) = 1; - - -%% ===== Computation and Plotting ======================================== -for method = fracdelay_methods' - conf.fracdelay_method = method{:}; - - % --- Computation --- - % Test all given delays - for n=1:length(dt) - outsig(:,n) = delayline(insig,dt(n),1,conf); - H(:,n) = freqz(outsig(:,n),1,wpi); - magresp(:,n) = abs(H(:,n)); - uwphase(:,n)=-unwrap(angle(H(:,n))); - phasdel(:,n) = uwphase(2:L,n)./wpi2'; - end - - % --- Plotting --- - % setup legend and axis - t=1:L; - t=t-L/2; - % Phase delay - figure; - plot(wpi2/pi,phasdel-(L/2)+1); - title([method{:},' - phase delay']); - ylabel('phase delay'); - xlabel('normalized frequency'); - grid on; - % Magnitude response - figure; - plot(wpi/pi,magresp); - title([method{:},' - magnitude response']); - ylabel('magnitude'); - xlabel('normalized frequency'); - grid on; - % Impluse response - figure; - %plot(t(L/2-10:L/2+10),outsig(L/2-10:L/2+10,:)); - imagesc(dt,t(L/2-50:L/2+50),db(abs(outsig(L/2-50:L/2+50,:)))); - title([method{:},' - impulse response']); - caxis([-100 10]); - ylabel('samples'); - xlabel('delay'); - set(gca,'XTick',dt) - turn_imagesc; - colorbar; - grid on; - -end +function status = test_delayline(modus) +%TEST_DELAYLINE evaluates the delayline implementation +% +% Usage: status = test_delayline(modus) +% +% Input parameters: +% modus - 0: numerical +% 1: visual +% +% Output parameters: +% status - true or false +% +% TEST_DELAYLINE(modus) tests the implementation of the delayline. For +% different types (conf.usefracdelay) you have to manual edit the code below +% at the moment. + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters ==================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Configuration ================================================== +% Delays to evaluate in samples (they will be transformed into seconds later) +dt = [-5 -2.5 0 2.5 5]; +%dt=[-1 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1]; +%dt=[0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1]; +%dt=1*[0 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.1]; +%dt=linspace(0,2,200); + +% Length of input signal +L=256; +% Create frequency axis +w = (0:1:(L-1))/L; +wpi = w*pi; +wpi2=wpi(2:L); +% Set up input signal +insig = zeros(L,1); +insig(L/2) = 1; + +conf.fs = 44100; +conf.delayline.filterorder = 4; % / 1 +conf.delayline.resamplingfactor = 4; % / 1 +conf.delayline.resamplingorder = 128; % / 1 + +%% ===== Computation and Plotting ======================================== +for resampling = {'none', 'matlab', 'pm'} + conf.delayline.resampling = resampling{:}; + for filter = {'lagrange', 'thiran', 'least_squares', 'integer'} + conf.delayline.filter = filter{:}; + + % --- Computation --- + % Test all given delays + for n=1:length(dt) + [outsig(:,n), delay_offset] = delayline(insig,dt(n)/conf.fs,1,conf); + H(:,n) = freqz(outsig(:,n),1,wpi); + magresp(:,n) = abs(H(:,n)); + uwphase(:,n)=-unwrap(angle(H(:,n))); + phasdel(:,n) = uwphase(2:L,n)./wpi2'; + end + + % --- Plotting --- + if modus + figure; + % setup legend and axis + t=1:L; + t=t-L/2; + % Phase delay + subplot(2,2,1); + plot(wpi2/pi,phasdel-(L/2)+1-delay_offset); + title(['resample: ', resampling{:}, ', filter: ', filter{:},' - phase delay']); + ylabel('phase delay'); + xlabel('normalized frequency'); + legend(num2str(dt.','%.1f')); + grid on; + % Magnitude response + subplot(2,2,2); + plot(wpi/pi,magresp); + title(['resample: ', resampling{:}, ', filter: ', filter{:},' - magnitude response']); + ylabel('magnitude'); + xlabel('normalized frequency'); + legend(num2str(dt.','%.1f')); + grid on; + % Impluse response + subplot(2,2,3); + imagesc(dt,t(L/2-50:L/2+50),db(abs(outsig(L/2-50:L/2+50,:)))); + title(['resample: ', resampling{:}, ', filter: ', filter{:},' - impulse response']); + caxis([-100 10]); + ylabel('samples'); + xlabel('delay / samples'); + set(gca,'XTick',dt) + turn_imagesc; + colorbar; + grid on; + end + end +end + + +status = true; diff --git a/validation/test_driving_functions.m b/validation/test_driving_functions.m index ebff9316..9d3444c2 100644 --- a/validation/test_driving_functions.m +++ b/validation/test_driving_functions.m @@ -1,52 +1,47 @@ -function boolean = test_driving_functions(modus) +function status = test_driving_functions(modus) %TEST_DRIVING_FUNCTIONS tests the correctness of the driving functions % -% Usage: boolean = test_driving_functions(modus) +% Usage: status = test_driving_functions(modus) % % Input parameters: % modus - 0: numerical % 1: visual % % Output parameters: -% booelan - true or false -% -% TEST_DRIVING_FUNCTIONS(MODUS) checks if the functions, that calculates -% the driving functions working correctly. Therefore different sound -% fields are simulated. +% status - true or false %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** + % TODO: add mode to save data as reference data +status = false; %% ===== Checking of input parameters =================================== @@ -56,41 +51,55 @@ %% ===== Configuration =================================================== -conf = SFS_config_example; +conf = SFS_config; conf.secondary_sources.size = 3; f = 1000; -t = 200; +t = 200/conf.fs; conf.plot.useplot = false; +conf.plot.usenormalisation = true; conf.driving_functions = 'default'; % test scenarios scenarios = { ... - 'WFS', '2D', 'linear', 'pw', [ 0.5 -1.0 0.0]; ... - 'WFS', '2D', 'linear', 'ls', [ 0.0 1.0 0.0]; ... - 'WFS', '2D', 'linear', 'fs', [ 0.0 -1.0 0.0 0.0 -1.0 0.0]; ... - 'WFS', '2D', 'circular', 'pw', [ 0.5 0.5 0.0]; ... - 'WFS', '2D', 'circular', 'ls', [ 0.0 2.5 0.0]; ... - 'WFS', '2D', 'circular', 'ps', [ 0.0 2.5 0.0]; ... - 'WFS', '2D', 'circular', 'fs', [ 0.0 0.5 0.0 0.0 -1.0 0.0]; ... - 'WFS', '2D', 'box', 'pw', [ 0.5 1.0 0.0]; ... - 'WFS', '2D', 'box', 'ls', [ 2.0 2.0 0.0]; ... - 'WFS', '2D', 'box', 'ps', [ 2.0 2.0 0.0]; ... - 'WFS', '2D', 'box', 'fs', [ 0.5 0.5 0.0 -1.0 -1.0 0.0]; ... - 'WFS', '2.5D', 'linear', 'pw', [ 0.5 -1.0 0.0]; ... - 'WFS', '2.5D', 'linear', 'ps', [ 0.0 1.0 0.0]; ... - 'WFS', '2.5D', 'linear', 'fs', [ 0.0 -1.0 0.0 0.0 -1.0 0.0]; ... - 'WFS', '2.5D', 'circular', 'pw', [ 0.5 0.5 0.0]; ... - 'WFS', '2.5D', 'circular', 'ps', [ 0.0 2.5 0.0]; ... - 'WFS', '2.5D', 'circular', 'fs', [ 0.0 0.5 0.0 0.0 -1.0 0.0]; ... - 'WFS', '2.5D', 'box', 'pw', [ 0.5 1.0 0.0]; ... - 'WFS', '2.5D', 'box', 'ps', [ 2.0 2.0 0.0]; ... - 'WFS', '2.5D', 'box', 'fs', [ 0.5 0.5 0.0 -1.0 -1.0 0.0]; ... - 'HOA', '2.5D', 'circular', 'pw', [ 0.5 0.5 0.0]; ... - 'HOA', '2.5D', 'circular', 'ps', [ 0.0 2.5 0.0]; ... - 'WFS', '3D', 'sphere', 'ps', [ 0.0 2.5 0.0]; ... - 'WFS', '3D', 'sphere', 'pw', [ 0.0 -1.0 0.0]; ... - 'WFS', '3D', 'sphere', 'fs', [ 0.0 0.5 0.0 0.0 -1.0 0.0]; ... - 'HOA', '3D', 'sphere', 'ps', [ 0.0 2.5 0.0]; ... - 'HOA', '3D', 'sphere', 'pw', [ 0.0 -1.0 0.0]; ... + 'WFS', '2D', 'linear', 'pw', [ 0.5 -1.0 0.0] '' + 'WFS', '2D', 'linear', 'ls', [ 0.0 1.0 0.0] '' + 'WFS', '2D', 'linear', 'ps', [ 0.0 1.0 0.0] '' + 'WFS', '2D', 'linear', 'fs', [ 0.0 -1.0 0.0 0.0 -1.0 0.0] '' + 'WFS', '2D', 'circular', 'pw', [ 0.5 0.5 0.0] '' + 'WFS', '2D', 'circular', 'ls', [ 0.0 2.5 0.0] '' + 'WFS', '2D', 'circular', 'ps', [ 0.0 2.5 0.0] '' + 'WFS', '2D', 'circular', 'fs', [ 0.0 0.5 0.0 0.0 -1.0 0.0] '' + 'WFS', '2D', 'box', 'pw', [ 0.5 1.0 0.0] '' + 'WFS', '2D', 'box', 'ls', [ 2.0 2.0 0.0] '' + 'WFS', '2D', 'box', 'ps', [ 2.0 2.0 0.0] '' + 'WFS', '2D', 'box', 'fs', [ 0.5 0.5 0.0 -1.0 -1.0 0.0] '' + 'WFS', '2.5D', 'linear', 'pw', [ 0.5 -1.0 0.0] '' + 'WFS', '2.5D', 'linear', 'ps', [ 0.0 1.0 0.0] '' + 'WFS', '2.5D', 'linear', 'ls', [ 0.0 1.0 0.0] '' + 'WFS', '2.5D', 'linear', 'fs', [ 0.0 -1.0 0.0 0.0 -1.0 0.0] '' + 'WFS', '2.5D', 'circular', 'pw', [ 0.5 0.5 0.0] '' + 'WFS', '2.5D', 'circular', 'ls', [ 0.0 2.5 0.0] '' + 'WFS', '2.5D', 'circular', 'ps', [ 0.0 2.5 0.0] '' + 'WFS', '2.5D', 'circular', 'fs', [ 0.0 0.5 0.0 0.0 -1.0 0.0] '' + 'WFS', '2.5D', 'box', 'pw', [ 0.5 1.0 0.0] '' + 'WFS', '2.5D', 'box', 'ls', [ 2.0 2.0 0.0] '' + 'WFS', '2.5D', 'box', 'ps', [ 2.0 2.0 0.0] '' + 'WFS', '2.5D', 'box', 'fs', [ 0.5 0.5 0.0 -1.0 -1.0 0.0] '' + 'HOA', '2.5D', 'circular', 'pw', [ 0.5 0.5 0.0] 'rect' + 'HOA', '2.5D', 'circular', 'pw', [ 0.5 0.5 0.0] 'max-rE' + 'HOA', '2.5D', 'circular', 'ls', [ 0.0 2.5 0.0] 'rect' + 'HOA', '2.5D', 'circular', 'ls', [ 0.0 2.5 0.0] 'max-rE' + 'HOA', '2.5D', 'circular', 'ps', [ 0.0 2.5 0.0] 'rect' + 'HOA', '2.5D', 'circular', 'ps', [ 0.0 2.5 0.0] 'max-rE' + 'WFS', '3D', 'sphere', 'pw', [ 0.0 -1.0 0.0] '' + 'WFS', '3D', 'sphere', 'ls', [ 0.0 2.5 0.0 0.0 1.0 1.0] '' + 'WFS', '3D', 'sphere', 'ps', [ 0.0 2.5 0.0] '' + 'WFS', '3D', 'sphere', 'fs', [ 0.0 0.5 0.0 0.0 -1.0 0.0] '' + 'HOA', '3D', 'sphere', 'pw', [ 0.0 -1.0 0.0] 'rect' + 'HOA', '3D', 'sphere', 'pw', [ 0.0 -1.0 0.0] 'max-rE' + 'HOA', '3D', 'sphere', 'ls', [ 0.0 2.5 0.0 0.0 1.0 1.0] 'rect' + 'HOA', '3D', 'sphere', 'ls', [ 0.0 2.5 0.0 0.0 1.0 1.0] 'max-rE' + 'HOA', '3D', 'sphere', 'ps', [ 0.0 2.5 0.0] 'rect' + 'HOA', '3D', 'sphere', 'ps', [ 0.0 2.5 0.0] 'max-rE' }; % Start testing @@ -98,7 +107,7 @@ % get current dimension conf.dimension = scenarios{ii,2}; - + % get listening area switch scenarios{ii,3} case 'linear' @@ -130,6 +139,9 @@ conf.secondary_sources.geometry = scenarios{ii,3}; src = scenarios{ii,4}; xs = scenarios{ii,5}; + + % modal window for nfchoa + conf.modal_window = scenarios{ii,6}; % ===== WFS ========================================================== if strcmp('WFS',scenarios{ii,1}) @@ -137,7 +149,8 @@ try [P,x,y,z,x0] = sound_field_mono_wfs(X,Y,Z,xs,src,f,conf); if modus - plot_sound_field(P,x,y,z,x0,conf); + conf.plot.normalisation = 'center'; + plot_sound_field(P,X,Y,Z,x0,conf); title_str = sprintf('WFS %s %s array, %s, mono-frequent', ... conf.dimension,conf.secondary_sources.geometry,src); title(title_str); @@ -151,7 +164,8 @@ try [p,x,y,z,x0] = sound_field_imp_wfs(X,Y,Z,xs,src,t,conf); if modus - plot_sound_field(p,x,y,z,x0,conf); + conf.plot.normalisation = 'max'; + plot_sound_field(p,X,Y,Z,x0,conf); title_str = sprintf('WFS %s %s array, %s, impulse response', ... conf.dimension,conf.secondary_sources.geometry,src); title(title_str); @@ -161,16 +175,17 @@ upper(mfilename),conf.secondary_sources.geometry,conf.dimension,src); lasterr end - + % ===== NFC-HOA ====================================================== elseif strcmp('HOA',scenarios{ii,1}) % mono-frequent try [P,x,y,z,x0] = sound_field_mono_nfchoa(X,Y,Z,xs,src,f,conf); if modus - plot_sound_field(P,x,y,z,x0,conf); - title_str = sprintf('NFC-HOA %s %s array, %s, mono-frequent', ... - conf.dimension,conf.secondary_sources.geometry,src); + conf.plot.normalisation = 'center'; + plot_sound_field(P,X,Y,Z,x0,conf); + title_str = sprintf('NFC-HOA %s %s array, %s, mono-frequent, %s window', ... + conf.dimension,conf.secondary_sources.geometry,src, conf.modal_window); title(title_str); end catch @@ -182,9 +197,10 @@ try [p,x,y,z,x0] = sound_field_imp_nfchoa(X,Y,Z,xs,src,t,conf); if modus - plot_sound_field(p,x,y,z,x0,conf); - title_str = sprintf('NFC-HOA %s %s array, %s, impulse response', ... - conf.dimension,conf.secondary_sources.geometry,src); + conf.plot.normalisation = 'max'; + plot_sound_field(p,X,Y,Z,x0,conf); + title_str = sprintf('NFC-HOA %s %s array, %s, impulse response, %s window', ... + conf.dimension,conf.secondary_sources.geometry,src, conf.modal_window); title(title_str); end catch @@ -194,3 +210,6 @@ end end end + + +status = true; diff --git a/validation/test_driving_functions_imp_with_delay.m b/validation/test_driving_functions_imp_with_delay.m new file mode 100644 index 00000000..f757e27e --- /dev/null +++ b/validation/test_driving_functions_imp_with_delay.m @@ -0,0 +1,182 @@ +function status = test_driving_functions_imp_with_delay(modus) +%TEST_DRIVING_FUNCTIONS_IMP_WITH_DELAY tests the correctness of the time-domain +%driving functions, in the case of conf.t0 = 'source' +% +% Usage: status = test_driving_functions_imp_with_delay(modus) +% +% Input parameters: +% modus - 0: numerical +% 1: visual +% +% Output parameters: +% status - true or false + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +% TODO: add mode to save data as reference data +status = false; + + +%% ===== Checking of input parameters =================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Configuration =================================================== +conf = SFS_config; +conf.t0 = 'source'; +conf.secondary_sources.size = 3; +conf.plot.useplot = false; +conf.plot.usenormalisation = true; +conf.plot.usedb = true; +conf.driving_functions = 'default'; +% test scenarios +scenarios = { ... + 'WFS', '2D', 'linear', 'pw', [ 0.5 -1.0 0.0]; ... + 'WFS', '2D', 'linear', 'ls', [ 0.0 1.0 0.0]; ... + 'WFS', '2D', 'linear', 'fs', [ 0.0 -1.0 0.0 0.0 -1.0 0.0]; ... + 'WFS', '2D', 'circular', 'pw', [ 0.5 0.5 0.0]; ... + 'WFS', '2D', 'circular', 'ls', [ 0.0 2.5 0.0]; ... + 'WFS', '2D', 'circular', 'ps', [ 0.0 2.5 0.0]; ... + 'WFS', '2D', 'circular', 'fs', [ 0.0 0.5 0.0 0.0 -1.0 0.0]; ... + 'WFS', '2D', 'box', 'pw', [ 0.5 1.0 0.0]; ... + 'WFS', '2D', 'box', 'ls', [ 2.0 2.0 0.0]; ... + 'WFS', '2D', 'box', 'ps', [ 2.0 2.0 0.0]; ... + 'WFS', '2D', 'box', 'fs', [ 0.5 0.5 0.0 -1.0 -1.0 0.0]; ... + 'WFS', '2.5D', 'linear', 'pw', [ 0.5 -1.0 0.0]; ... + 'WFS', '2.5D', 'linear', 'ps', [ 0.0 1.0 0.0]; ... + 'WFS', '2.5D', 'linear', 'fs', [ 0.0 -1.0 0.0 0.0 -1.0 0.0]; ... + 'WFS', '2.5D', 'circular', 'pw', [ 0.5 0.5 0.0]; ... + 'WFS', '2.5D', 'circular', 'ps', [ 0.0 2.5 0.0]; ... + 'WFS', '2.5D', 'circular', 'fs', [ 0.0 0.5 0.0 0.0 -1.0 0.0]; ... + 'WFS', '2.5D', 'box', 'pw', [ 0.5 1.0 0.0]; ... + 'WFS', '2.5D', 'box', 'ps', [ 2.0 2.0 0.0]; ... + 'WFS', '2.5D', 'box', 'fs', [ 0.5 0.5 0.0 -1.0 -1.0 0.0]; ... + 'WFS', '3D', 'sphere', 'ps', [ 0.0 0.0 2.5]; ... + 'WFS', '3D', 'sphere', 'ls', [ 0.0 0.0 2.5 0.0 1.0 1.0]; ... + 'WFS', '3D', 'sphere', 'pw', [ 0.0 0.0 -1.0]; ... + 'WFS', '3D', 'sphere', 'fs', [ 0.0 0.0 0.5 0.0 0.0 -1.0]; ... + 'HOA', '2.5D', 'circular', 'pw', [ 0.5 0.5 0.0]; ... + 'HOA', '3D', 'sphere', 'pw', [ 0.0 0.0 -1.0]; ... + 'HOA', '3D', 'sphere', 'pw', [-1.0 0.0 0.0]; ... + 'HOA', '2.5D', 'circular', 'ps', [ 0.0 2.5 0.0]; ... + 'HOA', '3D', 'sphere', 'ps', [ 0.0 0.0 2.5]; ... + 'HOA', '3D', 'sphere', 'ps', [ 2.5 0.0 0.0]; ... +}; + +% Start testing +for ii=1:size(scenarios) + + % get current dimension + conf.dimension = scenarios{ii,2}; + + % get listening area + switch scenarios{ii,3} + case 'linear' + X = [-2 2]; + Y = [-3 0.15]; + Z = 0; + conf.xref = [0 -1.5 0]; + conf.secondary_sources.number = 20; + case 'circular' + X = [-2 2]; + Y = [-2 2]; + Z = 0; + conf.xref = [0 0 0]; + conf.secondary_sources.number = 56; + case 'box' + X = [-2 2]; + Y = [-2 2]; + Z = 0; + conf.xref = [0 0 0]; + conf.secondary_sources.number = 80; + case 'sphere' + X = [-2 2]; + Y = 0; + Z = [-2 2]; + conf.xref = [0 0 0]; + conf.secondary_sources.number = 900; + end + + conf.secondary_sources.geometry = scenarios{ii,3}; + t = scenarios{ii,5}; + src = scenarios{ii,4}; + xs = scenarios{ii,5}; + % Adjust time for different source types (t=0 corresponds to first activity + % of virtual source). + if strcmp('ps',src) || strcmp('ls',src) + t = 2/conf.c; % time for traveling 2 m + elseif strcmp('fs',src) + t = 0.5/conf.c; % time for traveling 0.5 m + else + t = 0; + end + + % ===== WFS ========================================================== + if strcmp('WFS',scenarios{ii,1}) + % spatio-temporal impulse response + try + [p,x,y,z,x0] = sound_field_imp_wfs(X,Y,Z,xs,src,t,conf); + if modus + conf.plot.normalisation = 'max'; + plot_sound_field(p,X,Y,Z,x0,conf); + title_str = sprintf('WFS %s %s array, %s, impulse response', ... + conf.dimension,conf.secondary_sources.geometry,src); + title(title_str); + end + catch + warning('%s: WFS impulse response %s array %s %s gives the following error message.', ... + upper(mfilename),conf.secondary_sources.geometry,conf.dimension,src); + lasterr + end + % ===== NFC-HOA ====================================================== + elseif strcmp('HOA',scenarios{ii,1}) + % spatio-temporal impulse response +% try + [p,x,y,z,x0] = sound_field_imp_nfchoa(X,Y,Z,xs,src,t,conf); + if modus + conf.plot.normalisation = 'max'; + plot_sound_field(p,X,Y,Z,x0,conf); + title_str = sprintf('NFC-HOA %s %s array, %s, impulse response', ... + conf.dimension,conf.secondary_sources.geometry,src); + title(title_str); + end +% catch +% warning('%s: NFC-HOA impulse response %s array %s %s gives the following error message.', ... +% upper(mfilename),conf.secondary_sources.geometry,conf.dimension,src); +% lasterr +% end + end +end + + +status = true; diff --git a/validation/test_exp_imp.m b/validation/test_exp_imp.m new file mode 100644 index 00000000..42c106fb --- /dev/null +++ b/validation/test_exp_imp.m @@ -0,0 +1,151 @@ +function status = test_exp_imp(modus) +%TEST_EXP_IMP tests the different expansions of sound fields in time-domain +% +% Usage: status = test_exp_imp(modus) +% +% Input parameters: +% modus - 0: numerical +% 1: visual +% +% Output parameters: +% status - true or false +% +% TEST_EXP_IMP(modus) checks, if the circular basis expansions for plane waves +% and point sources are working. The circular basis expansions are converted +% to plane wave decompositions. Additionally, modal weighting functions are +% tested. Optionally, sound field plots of the plane wave decompositions are +% used for verification. + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters =================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Configuration =================================================== +% Parameters +conf = SFS_config; +conf.plot.loudspeakers = 0; % do not plot loudspeakers +conf.plot.usedb = 1; % use decibel for sound field plot +conf.modal_window_parameter = 2.0; % parameter for kaiser window + +c = conf.c; % speed of sound + +% for sound field plots +X = [-2, 2]; +Y = [-2, 2]; +Z = 0; + +fhp = 1000; % high-pass filter corner-frequency for pwd of point source + +% plane waves with equi-angular distribution +Npw = 1024; +phi0 = (0:Npw-1).'*2*pi/Npw; +x0 = [cos(phi0) sin(phi0)]; +x0(:,3) = 0; +x0(:,4:6) = x0(:,1:3); +x0(:,7) = 1; + +% test scenarios +scenarios = { ... + 'pw', [ 0.0 -1.0 0.0], 5, 'rect' , [0.0 0.0 0.0] + 'pw', [ 0.0 -1.0 0.0], 15, 'rect' , [0.0 0.0 0.0] + 'pw', [ 0.0 -1.0 0.0], 15, 'kaiser' , [0.0 0.0 0.0] + 'pw', [ 0.0 -1.0 0.0], 5, 'rect' , [0.5 1.0 0.0] + 'pw', [ 0.0 -1.0 0.0], 15, 'rect' , [0.5 1.0 0.0] + 'pw', [ 0.0 -1.0 0.0], 15, 'kaiser' , [0.5 1.0 0.0] + 'ps', [ 0.0 2.5 0.0], 5, 'rect' , [0.0 0.0 0.0] + 'ps', [ 0.0 2.5 0.0], 15, 'rect' , [0.0 0.0 0.0] + 'ps', [ 0.0 2.5 0.0], 15, 'kaiser' , [0.0 0.0 0.0] + 'ps', [ 0.0 2.5 0.0], 5, 'rect' , [0.5 1.0 0.0] + 'ps', [ 0.0 2.5 0.0], 15, 'rect' , [0.5 1.0 0.0] + 'ps', [ 0.0 2.5 0.0], 15, 'kaiser' , [0.5 1.0 0.0] + }; + +%% ===== Main ============================================================ + +for ii=1:size(scenarios) + + src = scenarios{ii,1}; % source type + xs = scenarios{ii,2}; % source position / direction of plane wave + Nce = scenarios{ii,3}; % modal order + conf.modal_window = scenarios{ii,4}; % type of modal weighting function + xq = scenarios{ii,5}; % expansion centre + + % circular expansion coefficients + switch src + case 'pw' + [pm, delay_offset] = circexp_imp_pw(xs,Nce,xq,conf); + t = xq*xs.'./c; + case 'ps' + [pm, delay_offset] = circexp_imp_ps(xs,Nce,xq,fhp,conf); + t = norm(xq-xs)./c; + end + + % modal weighting of coefficients + wm = modal_weighting(Nce, conf); + pm = bsxfun(@times, pm, wm); + + % conversion to plane wave decomposition + ppwd = pwd_imp_circexp(pm, Npw); + + if modus + % delay plane waves according to expansion centre + delays = -xq*x0(:,1:3).'./c; + delay_offset = delay_offset - min(delays); + delays = delays - min(delays); + ppwd = delayline(ppwd,delays,1,conf); + + % sound field plot + sound_field_imp(X,Y,Z,x0,'pw',ppwd,t+delay_offset,conf); + + % title string + str = 'Plane wave decompostion of modally bandlimited'; + switch src + case 'pw' + str = sprintf('%s plane wave', str); + case 'ps' + str = sprintf('%s point source', str); + end + str = sprintf(['%s ([%1.1f %1.1f %1.1f]):\n%s-window (M=%d), ' ... + 'center of modal expansion at [%1.1f %1.1f %1.1f]'], ... + str, xs, conf.modal_window, Nce, xq); + title(str); + + end +end + +status = true; diff --git a/validation/test_exp_mono.m b/validation/test_exp_mono.m new file mode 100644 index 00000000..2e9df5b3 --- /dev/null +++ b/validation/test_exp_mono.m @@ -0,0 +1,145 @@ +function status = test_exp_mono(modus) +%TEST_EXP_MONO tests the different expansions of sound fields in frequency-domain +% +% Usage: status = test_exp_mono(modus) +% +% Input parameters: +% modus - 0: numerical +% 1: visual +% +% Output parameters: +% status - true or false +% +% TEST_EXP_MONO(modus) checks, if the circular basis expansions for plane +% waves and point sources are working. The circular basis expansions are +% converted to plane wave decompositions. Additionally, modal weighting +% functions are tested. Optionally, sound field plots of the plane wave +% decompositions are used for verification. + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters =================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Configuration =================================================== +% Parameters +conf = SFS_config; +conf.plot.loudspeakers = false; % do not plot loudspeakers +conf.modal_window_parameter = 2.0; % parameter for kaiser window + +c = conf.c; % speed of sound + +% For sound field plots +X = [-2, 2]; +Y = [-2, 2]; +Z = 0; + +f = 500; + +% Plane waves with equi-angular distribution +Npw = 1024; +phi0 = (0:Npw-1).'*2*pi/Npw; +x0 = [cos(phi0) sin(phi0)]; +x0(:,3) = 0; +x0(:,4:6) = x0(:,1:3); +x0(:,7) = 1; + +% Test scenarios +scenarios = { ... + 'pw', [ 0.0 -1.0 0.0], 5, 'rect' , [0.0 0.0 0.0] + 'pw', [ 0.0 -1.0 0.0], 15, 'rect' , [0.0 0.0 0.0] + 'pw', [ 0.0 -1.0 0.0], 15, 'kaiser' , [0.0 0.0 0.0] + 'pw', [ 0.0 -1.0 0.0], 5, 'rect' , [0.5 1.0 0.0] + 'pw', [ 0.0 -1.0 0.0], 15, 'rect' , [0.5 1.0 0.0] + 'pw', [ 0.0 -1.0 0.0], 15, 'kaiser' , [0.5 1.0 0.0] + 'ps', [ 0.0 2.5 0.0], 5, 'rect' , [0.0 0.0 0.0] + 'ps', [ 0.0 2.5 0.0], 15, 'rect' , [0.0 0.0 0.0] + 'ps', [ 0.0 2.5 0.0], 15, 'kaiser' , [0.0 0.0 0.0] + 'ps', [ 0.0 2.5 0.0], 5, 'rect' , [0.5 1.0 0.0] + 'ps', [ 0.0 2.5 0.0], 15, 'rect' , [0.5 1.0 0.0] + 'ps', [ 0.0 2.5 0.0], 15, 'kaiser' , [0.5 1.0 0.0] + }; + +%% ===== Main ============================================================ + +for ii=1:size(scenarios) + + src = scenarios{ii,1}; % source type + xs = scenarios{ii,2}; % source position / direction of plane wave + Nce = scenarios{ii,3}; % modal order + conf.modal_window = scenarios{ii,4}; % type of modal weighting function + xq = scenarios{ii,5}; % expansion centre + + % Circular expansion coefficients + switch src + case 'pw' + Pm = circexp_mono_pw(xs,Nce,f,xq,conf); + g = 1; + case 'ps' + Pm = circexp_mono_ps(xs,Nce,f,xq,conf); + g = 1./(4*pi*norm(xs-xq)); + end + + % Modal weighting of coefficients + wm = modal_weighting(Nce, conf); + Pm = bsxfun(@times, Pm, [wm(end:-1:2) wm]); + + % Conversion to plane wave decomposition + Ppwd = pwd_mono_circexp(Pm, Npw); + + if modus + % Sound field plot + P = sound_field_mono(X,Y,Z,x0,'pw',Ppwd,f,conf); + plot_sound_field(P.*g,X,Y,Z,[],conf); + + % Title string + str = 'Plane wave decompostion of modally bandlimited'; + switch src + case 'pw' + str = sprintf('%s plane wave', str); + case 'ps' + str = sprintf('%s point source', str); + end + str = sprintf(['%s ([%1.1f %1.1f %1.1f]):\n%s-window (M=%d), ' ... + 'center of modal expansion at [%1.1f %1.1f %1.1f]'], ... + str, xs, conf.modal_window, Nce, xq); + title(str); + end +end + + +status = true; diff --git a/validation/test_hrtf_extrapolation.m b/validation/test_hrtf_extrapolation.m index cb3a4926..128575fc 100644 --- a/validation/test_hrtf_extrapolation.m +++ b/validation/test_hrtf_extrapolation.m @@ -1,111 +1,103 @@ -function boolean = test_hrtf_extrapolation(hrtf_set) +function status = test_hrtf_extrapolation(modus,hrtf_set) %TEST_HRTF_EXTRAPOLATION tests the HRTF extrapolation functions % -% Usage: boolean = test_hrtf_extrapolation(hrtf_set) +% Usage: status = test_hrtf_extrapolation(modus,hrtf_set) % % Input parameters: +% modus - 0: numerical +% 1: visual % hrtf_set - HRTFs for testing extrapolation. Can be % 'QU_KEMAR' % 'FABIAN_3D' % % Output parameters: -% booelan - true or false -% -% TEST_HRTF_EXTRAPOLATION(HRTF_SET) checks if the HRTF exrapolation works -% correctly. +% status - true or false %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** + % TODO: add mode to save data as reference data +status = false; %% ===== Checking of input parameters =================================== -nargmin = 1; -nargmax = 1; +nargmin = 2; +nargmax = 2; narginchk(nargmin,nargmax); %% ===== Configuration =================================================== +conf = SFS_config; +conf.showprogress = true; if strcmp('QU_KEMAR',hrtf_set) % QU KEMAR horizontal HRTFs disp('Extrapolate QU KEMAR anechoic 3m ...'); - % extrapolation settings - conf.dimension = '2.5D'; - conf.N = 1024; - conf.c = 343; - conf.fs = 44100; - conf.xref = [0 0 0]; - conf.usetapwin = true; - conf.tapwinlen = 0.3; - conf.secondary_sources.geometry = 'circle'; - conf.wfs.usehpre = true; - conf.wfs.hpretype = 'FIR'; - conf.driving_functions = 'default'; - conf.usefracdelay = false; - conf.fracdelay_method = 'resample'; - conf.ir.useinterpolation = true; - conf.ir.useoriglength = false; - conf.showprogress = true; % check if HRTF data set is available, download otherwise basepath = get_sfs_path(); - hrtf_file = [basepath '/data/HRTFs/QU_KEMAR_anechoic_3m.mat']; + hrtf_file = [basepath '/data/HRTFs/QU_KEMAR_anechoic_3m.sofa']; if ~exist(hrtf_file,'file') - url = ['https://dev.qu.tu-berlin.de/projects/measurements/repository/', ... - 'raw/2010-11-kemar-anechoic/mat/QU_KEMAR_anechoic_3m.mat']; + url = ['https://raw.githubusercontent.com/sfstoolbox/data/master/', ... + 'HRTFs/QU_KEMAR_anechoic_3m.sofa']; download_file(url,hrtf_file); end % load HRTF data set - irs = read_irs(hrtf_file,conf); + sofa = SOFAload(hrtf_file); + x0 = SOFAcalculateAPV(sofa); % do the extrapolation - irs_pw = extrapolate_farfield_hrtfset(irs,conf); + sofa_pw = extrapolate_farfield_hrtfset(sofa,conf); % plot the original HRTF data set - figure; - imagesc(deg(irs.apparent_azimuth),1:size(irs.left,1),irs.left); - title('QU KEMAR anechoic 3m'); - xlabel('phi / deg'); - % plot the interplated HRTF data set - figure; - imagesc(deg(irs_pw.apparent_azimuth),1:size(irs_pw.left,1),irs_pw.left); - title('QU KEMAR anechoic extrapolated'); - xlabel('phi / deg'); + if modus + figure; + imagesc(x0(:,1),1:size(sofa.Data.IR,3),squeeze(sofa.Data.IR(:,1,:))'); + title('QU KEMAR anechoic 3m'); + xlabel('phi / deg'); + % plot the interplated HRTF data set + figure; + imagesc(x0(:,1),1:size(sofa_pw.Data.IR,3),squeeze(sofa_pw.Data.IR(:,1,:))'); + title('QU KEMAR anechoic extrapolated'); + xlabel('phi / deg'); + end % ILD of both HRTF sets - ild1 = interaural_level_difference(irs.left,irs.right); - ild2 = interaural_level_difference(irs_pw.left,irs_pw.right); - figure; - plot(deg(irs.apparent_azimuth),ild1,'-b', ... - deg(irs.apparent_azimuth),ild2,'-r'); - legend('original','extrapolated'); - title('Interaural Level Differences'); + ild1 = db(rms(squeeze(sofa.Data.IR(:,1,:))')) - ... + db(rms(squeeze(sofa.Data.IR(:,2,:))')); + ild2 = db(rms(squeeze(sofa_pw.Data.IR(:,1,:))')) - ... + db(rms(squeeze(sofa_pw.Data.IR(:,2,:))')); + if modus + figure; + plot(x0(:,1),ild1,'-b', ... + x0(:,1),ild2,'-r'); + legend('original','extrapolated'); + title('Interaural Level Differences'); + xlabel('phi / deg'); + ylabel('Amplitude difference / dB'); + end elseif strcmp('FABIAN_3D',hrtf_set) error(['%s: the FABIAN 3D data set is not publicly available at the ' ... 'moment.'],upper(mfilename)); @@ -113,44 +105,40 @@ disp('Extrapolate SEACEN FABIAN anechoic ...'); % extrapolation settings conf.dimension = '3D'; - conf.fs = 44100; - conf.c = 343; - conf.xref = [0 0 0]; conf.usetapwin = false; - conf.tapwinlen = 0.3; conf.secondary_sources.geometry = 'sphere'; - conf.N = 1024; - conf.wfs.usehpre = true; - conf.wfs.hpretype = 'FIR'; - conf.driving_functions = 'default'; - conf.usefracdelay = false; - conf.fracdelay_method = 'resample'; - conf.ir.useinterpolation = true; - conf.ir.useoriglength = false; - conf.showprogress = true; - addirspath(conf); - hrtf_file = 'FABIAN_3d_anechoic.mat'; - % load HRTF data set - irs = read_irs(hrtf_file,conf); + hrtf_file = 'FABIAN_3d_anechoic.sofa'; % do the extrapolation - irs_pw = extrapolate_farfield_hrtfset(irs,conf); - %save FABIAN_3D_extrapolated.mat irs_pw + irs_pw = extrapolate_farfield_hrtfset(hrtf_file,conf); + %save FABIAN_3D_extrapolated.sofa irs_pw % plot the original HRTF data set - figure; - imagesc(deg(irs.apparent_azimuth),1:size(irs.left,1),irs.left); - title('SEACEN FABIAN anechoic 1.7m'); - xlabel('phi / deg'); - % plot the interplated HRTF data set - figure; - imagesc(deg(irs_pw.apparent_azimuth),1:size(irs_pw.left,1),irs_pw.left); - title('SEACEN FABIAN anechoic extrapolated'); - xlabel('phi / deg'); + if modus + figure; + imagesc(x0(:,1),1:size(sofa.Data.IR,3),squeeze(sofa.Data.IR(:,1,:))'); + title('SEACEN FABIAN anechoic 1.7m'); + xlabel('phi / deg'); + % plot the interplated HRTF data set + figure; + imagesc(x0(:,1),1:size(sofa_pw.Data.IR,3),squeeze(sofa.Data_pw.IR(:,1,:))'); + title('SEACEN FABIAN anechoic extrapolated'); + xlabel('phi / deg'); + end + % ILD of both HRTF sets % ILD of both HRTF sets - ild1 = interaural_level_difference(irs.left,irs.right); - ild2 = interaural_level_difference(irs_pw.left,irs_pw.right); - figure; - plot(deg(irs.apparent_azimuth),ild1,'-b', ... - deg(irs.apparent_azimuth),ild2,'-r'); - legend('original','extrapolated'); - title('Interaural Level Differences'); + ild1 = db(rms(squeeze(sofa.Data.IR(:,1,:))')) - ... + db(rms(squeeze(sofa.Data.IR(:,2,:))')); + ild2 = db(rms(squeeze(sofa_pw.Data.IR(:,1,:))')) - ... + db(rms(squeeze(sofa_pw.Data.IR(:,2,:))')); + if modus + figure; + plot(x0(:,1),ild1,'-b', ... + x0(:,1),ild2,'-r'); + legend('original','extrapolated'); + title('Interaural Level Differences'); + xlabel('phi / deg'); + ylabel('Amplitude difference / dB'); + end end + + +status = true; diff --git a/validation/test_imp_25d.m b/validation/test_imp_25d.m new file mode 100644 index 00000000..3ce661cd --- /dev/null +++ b/validation/test_imp_25d.m @@ -0,0 +1,173 @@ +function status = test_imp_25d(modus) +%TEST_imp_25D tests behavior of 2.5D SFS techniques in time-domain +% +% Usage: status = test_imp_25d(modus) +% +% Input parameters: +% modus - 0: numerical +% 1: visual +% +% Output parameters: +% status - true or false + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters =================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Configuration =================================================== +% Parameters +conf = SFS_config; +conf.xref = [0,0,0]; +conf.dimension = '2.5D'; +conf.plot.useplot = false; +conf.plot.usedb = true; +conf.wfs.hpreflow = 20; +conf.wfs.hprefhigh = 20000; +conf.localwfs_vss.wfs = conf.wfs; +conf.localwfs_vss.geometry = 'circular'; +conf.localwfs_vss.number = 512; +conf.localwfs_vss.center = conf.xref; +conf.localwfs_vss.size = 0.6; +conf.localwfs_vss.consider_secondary_sources = false; +conf.localwfs_vss.consider_target_field = false; +conf.localwfs_sbl.order = 23; +conf.delayline.resamplingfactor = 8; +conf.delayline.resampling = 'pm'; +conf.delayline.filter = 'lagrange'; +conf.delayline.filterorder = 9; +conf.t0 = 'source'; + +X = [-2.05 2.05]; +Y = [-2.05 2.05]; +Z = 0; + +% test scenarios +scenarios = { ... + 'WFS', 'reference_point', 'linear', 'pw', [ 0.0 -1.0 0.0] + 'WFS', 'reference_point', 'linear', 'ps', [ 0.0 2.5 0.0] + 'WFS', 'reference_point', 'linear', 'fs', [ 0.0 0.75 0.0 0.0 -1.0 0.0] + 'WFS', 'reference_line' , 'linear', 'pw', [ 0.0 -1.0 0.0] + 'WFS', 'reference_line' , 'linear', 'ps', [ 0.0 2.5 0.0] + 'WFS', 'reference_line' , 'linear', 'fs', [ 0.0 0.75 0.0 0.0 -1.0 0.0] + 'HOA', 'default', 'circular', 'pw', [ 0.0 -1.0 0.0] + 'HOA', 'default', 'circular', 'ps', [ 0.0 2.5 0.0] + 'LWFS-VSS', 'default', 'circular', 'pw', [ 0.0 -1.0 0.0] + 'LWFS-VSS', 'default', 'circular', 'ps', [ 0.0 2.5 0.0] + 'LWFS-SBL', 'default', 'circular', 'pw', [ 0.0 -1.0 0.0] + 'LWFS-SBL', 'default', 'circular', 'ps', [ 0.0 2.5 0.0] + }; + +%% ===== Main ============================================================ + +sofa = dummy_irs(512,conf); +xt = conf.xref + [0.1, 0, 0]; + +for ii=1:size(scenarios) + + src = scenarios{ii,4}; % + xs = scenarios{ii,5}; % source position + switch src + case 'pw' + tau = xs*conf.xref.'./conf.c; + case {'ps', 'fs'} + tau = norm(xs(1:3) - conf.xref)./conf.c; + end + + % get listening area + conf.secondary_sources.geometry = scenarios{ii,3}; + switch scenarios{ii,3} + case 'linear' + conf.secondary_sources.size = 4; + conf.secondary_sources.number = 128; + conf.usetapwin = true; + conf.tapwinlen = 0.2; + conf.secondary_sources.center = [0, 1.5, 0]; + case 'circular' + conf.secondary_sources.size = 3; + conf.secondary_sources.number = 128; + conf.secondary_sources.center = [0, 0, 0]; + end + x0 = secondary_source_positions(conf); + + % compute driving signals + conf.driving_functions = scenarios{ii,2}; + switch scenarios{ii,1} + case 'WFS' + x0 = secondary_source_selection(x0,xs,src); + x0 = secondary_source_tapering(x0,conf); + [d,~,~,delay_offset] = driving_function_imp_wfs(x0,xs,src,conf); + case 'HOA' + [d,~,delay_offset] = driving_function_imp_nfchoa(x0,xs,src,conf); + case 'LWFS-VSS' + [d,x0,~,~,delay_offset] = ... + driving_function_imp_localwfs_vss(x0,xs,src,conf); + case 'LWFS-SBL' + [d,delay_offset] = driving_function_imp_localwfs_sbl(x0,xs,src,conf); + end + + % Spatio-temporal sound field + p = sound_field_imp(X,Y,Z,x0,'ps',d,tau+delay_offset,conf); + + % spectrum of reproduced sound field at reference position + ir_sfs = ir_generic(xt,0,x0,d,sofa,conf); + [IR_sfs,~,f_sfs] = spectrum_from_signal(ir_sfs(:,1),conf); + + % spectrum of ground truth sound field at reference position + if strcmp(src,'pw') + ir_gt = ir_point_source(xt,0,-xs./norm(xs),sofa,conf); + ir_gt = ir_gt*4*pi; + else + ir_gt = ir_point_source(xt,0,xs(1:3),sofa,conf); + end + [IR_gt,~,f_gt] = spectrum_from_signal(ir_gt(:,1),conf); + + if modus + plot_sound_field(p,X,Y,Z,x0,conf); + title(sprintf('%s %s %s',scenarios{ii,1},src, ... + conf.driving_functions),'Interpreter','none'); + figure; + semilogx(f_sfs,db(IR_sfs),'r',f_gt,db(IR_gt),'b--'); + xlabel('Frequency / Hz'); + ylabel('Magnitude / dB'); + title(sprintf('%s %s %s',scenarios{ii,1},src,conf.driving_functions), ... + 'Interpreter','none'); + legend('reproduced','ground truth','Location','northwest'); + end +end + +status = true; diff --git a/validation/test_impulse_responses.m b/validation/test_impulse_responses.m deleted file mode 100644 index 0192e9ac..00000000 --- a/validation/test_impulse_responses.m +++ /dev/null @@ -1,99 +0,0 @@ -function boolean = test_impulse_responses() -%TEST_IMPULSE_RESPONSES tests time behavior of WFS and local WFS -% -% Usage: boolean = test_impulse_responses() -% -% Output parameters: -% booelan - true or false -% -% TEST_IMPULSE_RESPONSES() compares the time-frequency response of -% WFS and local WFS by calculating impulse responses, their frequency -% spectrum, and spatial-temporal sound field. - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Configuration =================================================== -boolean = false; -%% Parameters -conf = SFS_config_example; -conf.showprogress = true; -conf.resolution = 400; -conf.plot.useplot = true; -conf.plot.loudspeakers = true; -conf.plot.realloudspeakers = false; -conf.plot.usedb = true; -conf.tapwinlen = 1.0; -% config for virtual array -conf.localsfs.method = 'wfs'; -conf.localsfs.wfs = conf.wfs; -conf.localsfs.usetapwin = true; -conf.localsfs.tapwinlen = 0.3; -conf.localsfs.vss.size = 1.0; -conf.localsfs.vss.center = [0, 0.5, 0]; -conf.localsfs.vss.geometry = 'linear'; -conf.localsfs.vss.number = 56; -conf.localsfs.vss.consider_target_field = true; -conf.localsfs.vss.consider_secondary_sources = true; -% config for real array -conf.dimension = '2.5D'; -conf.secondary_sources.geometry = 'linear'; -conf.secondary_sources.number = 56; -conf.secondary_sources.size = 3; -conf.secondary_sources.center = [0, 1.5, 0]; -conf.driving_functions = 'default'; -conf.xref = conf.localsfs.vss.center; -% impulse response -conf.ir.usehcomp = false; -% listening area, virtual source -xs = [0.0, -1.0, 0]; % propagation direction of plane wave -src = 'pw'; -X = [-1.5 1.5]; -Y = [-1, 1.55]; -Z = 0; - - -%% ===== Computation ===================================================== -%% temporal impulse responses -irs = dummy_irs; -% calculate impulse response for WFS and local WFS -s_lwfs = ir_localwfs(conf.xref,pi/2,xs,src,irs,conf); -s_wfs = ir_wfs(conf.xref,pi/2,xs,src,irs,conf); -% plot frequency response -[S_lwfs, ~, f_lwfs] = easyfft(s_lwfs(:,1)./max(abs(s_lwfs(:,1))), conf); -[S_wfs, ~, f_wfs] = easyfft(s_wfs(:,1)./max(abs(s_wfs(:,1))), conf); -% plot spatio-temporal sound field -sound_field_imp_localwfs(X,Y,Z, xs, src, 400, conf); -sound_field_imp_wfs(X,Y,Z, xs, src, 190, conf); - -boolean = true; diff --git a/validation/test_interpolation_methods.m b/validation/test_interpolation_methods.m new file mode 100644 index 00000000..43f6cb15 --- /dev/null +++ b/validation/test_interpolation_methods.m @@ -0,0 +1,256 @@ +function status = test_interpolation_methods(modus) +%TEST_INTERPOLATION_METHODS demonstrates the difference between interpolation +%methods +% +% Usage: status = test_interpolation_methods(modus) +% +% Input parameters: +% modus - 0: numerical (not available) +% 1: visual +% +% Output parameters: +% status - true or false + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters ==================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); +if ~modus + warning('%s: numerical modus not available.',upper(mfilename)); + status = true; + return; +end + + +%% ===== Settings ======================================================== +conf = struct; +conf.ir.useinterpolation = true; + + +%% ===== Main ============================================================ +% Check if HRTF data set with low frequency correction is available, +% download otherwise +basepath = get_sfs_path(); +hrtf = 'KEMAR_HRTFs_lfcorr.sofa'; +hrtf_file = [basepath '/data/HRTFs/' hrtf]; +if ~exist(hrtf_file,'file') + disp('Download'); + url = ['https://github.com/spatialaudio/lf-corrected-kemar-hrtfs/', ... + 'blob/master/' hrtf '?raw=true']; + download_file(url,hrtf_file); +end +% Load HRTF data set +hrtf = SOFAload(hrtf_file); + + +%% ===== Interpolate shifted Dirac impulses ============================== +% interpolation points +x0 = [1 3; 0 0; 0 0]/180*pi; +% weights (for target point: xs = [2; 0; 0]/180*pi ) +weights = [.5; .5]; +N = 50; %length impulse responses + +% 1. Interpolate between Dirac impulses with one sample in between +h1 = zeros(1,N); +h1(3) = 1; +h2 = zeros(1,N); +h2(5) = 1; + +irs1(1,1,:) = h1; +irs1(2,1,:) = h2; +irs1(:,2,:) = irs1(:,1,:); %redundant second channel + +conf.ir.interpolationmethod = 'simple'; +h_int1_simple = interpolate_ir(irs1,weights,conf); +conf.ir.interpolationmethod = 'freqdomain'; +h_int1_fd = interpolate_ir(irs1,weights,conf); +conf.ir.interpolationmethod = 'timedomain'; +h_int1_td = interpolate_ir(irs1,weights,conf); + +% 2. Interpolate between neighbouring Dirac impulses at impulse reponse start +h1 = zeros(1,N); +h1(3) = 1; +h3 = zeros(1,N); +h3(4) = 1; + +irs2(1,1,:) = h1; +irs2(2,1,:) = h3; +irs2(:,2,:) = irs2(:,1,:); %redundant second channel + +conf.ir.interpolationmethod = 'simple'; +h_int2_simple = interpolate_ir(irs2,weights,conf); +conf.ir.interpolationmethod = 'freqdomain'; +h_int2_fd = interpolate_ir(irs2,weights,conf); +conf.ir.interpolationmethod = 'timedomain'; +h_int2_td = interpolate_ir(irs2,weights,conf); + +% 3. Interpolate between neighbouring Dirac impulses in middle of impulse response +h4 = zeros(1,N); +h4(25) = 1; +h5 = zeros(1,N); +h5(26) = 1; + +irs3(1,1,:) = h4; +irs3(2,1,:) = h5; +irs3(:,2,:) = irs3(:,1,:); + +conf.ir.interpolationmethod = 'simple'; +h_int3_simple = interpolate_ir(irs3,weights,conf); +conf.ir.interpolationmethod = 'freqdomain'; +h_int3_fd = interpolate_ir(irs3,weights,conf); +conf.ir.interpolationmethod = 'timedomain'; +h_int3_td = interpolate_ir(irs3,weights,conf); + +% Plots +% impulse responses +ir_list = { + irs1(1,1,:) , irs2(1,1,:) , irs3(1,1,:) + irs1(2,1,:) , irs2(2,1,:) , irs3(2,1,:) + h_int1_simple(1,1,:), h_int2_simple(1,1,:) , h_int3_simple(1,1,:) + h_int1_fd(1,1,:) , h_int2_fd(1,1,:) , h_int3_fd(1,1,:) + h_int1_td(1,1,:) , h_int2_td(1,1,:) , h_int3_td(1,1,:) + }; % list of IRs + +col = {'k' 'b' 'r' 'm' 'c'}; + +titlelabels = { + 'Interpolation between Dirac impulses with one sample in between' + 'Interpolation of neighbouring Dirac impulses at impulse response start' + 'Interpolation of neighbouring Dirac impulses in middle of impulse response' + }; + +t = 0:N-1; % time-axis in samples + +for cdx=1:size(ir_list,2) + figure + for rdx=1:size(ir_list,1) + plot(t,squeeze(ir_list{rdx, cdx}), col{rdx}) + hold on + end + hold off + grid + xlabel('samples') + ylabel('amplitude') + legend('h_1','h_2','simple interp','freqdomain interp','timedomain interp') + title(titlelabels{cdx}) +end + +%% ===== Interpolate HRIRs =============================================== +% 1. Interpolate between close HRIRs +idx0 = 181; %index for 0° azimuth +idx1 = 182; %index for 1° azimuth +idx2 = 183; %index for 2° azimuth +x0_close = [hrtf.SourcePosition(idx0,:).' hrtf.SourcePosition(idx2,:).']/180*pi; +% weights (for target point: xs_close = hrtf.SourcePosition(idx1,:).'/180*pi ) +weights_close = [.5; .5]; +hrir_close = [hrtf.Data.IR(idx0,:,:); hrtf.Data.IR(idx2,:,:)]; +hrir_close_ref = hrtf.Data.IR(idx1,:,:); + +conf.ir.interpolationmethod = 'simple'; +hrir_close_simple = interpolate_ir(hrir_close,weights_close,conf); +conf.ir.interpolationmethod = 'freqdomain'; +hrir_close_fd = interpolate_ir(hrir_close,weights_close,conf); +conf.ir.interpolationmethod = 'timedomain'; +hrir_close_td = interpolate_ir(hrir_close,weights_close,conf); + +% 2. Interpolate between distant HRIRs +idx0 = 181; %index for 0° azimuth +idx30 = 211; %index for 30° azimuth +idx60 = 241; %index for 60° azimuth +x0_dist = [hrtf.SourcePosition(idx0,:).' hrtf.SourcePosition(idx60,:).']/180*pi; +% weights (for target point: xs_dist = hrtf.SourcePosition(idx30,:).'/180*pi ) +weights_dist = [.5; .5]; +hrir_dist = [hrtf.Data.IR(idx0,:,:); hrtf.Data.IR(idx60,:,:)]; +hrir_dist_ref = hrtf.Data.IR(idx30,:,:); + +conf.ir.interpolationmethod = 'simple'; +hrir_dist_simple = interpolate_ir(hrir_dist,weights_dist,conf); +conf.ir.interpolationmethod = 'freqdomain'; +hrir_dist_fd = interpolate_ir(hrir_dist,weights_dist,conf); +conf.ir.interpolationmethod = 'timedomain'; +hrir_dist_td = interpolate_ir(hrir_dist,weights_dist,conf); + +% Plots +hrir_list = { + hrir_close(1,1,:) , hrir_dist(1,1,:) + hrir_close(2,1,:) , hrir_dist(2,1,:) + hrir_close_ref(1,1,:) , hrir_dist_ref(1,1,:) + hrir_close_simple(1,1,:), hrir_dist_simple(1,1,:) + hrir_close_fd(1,1,:) , hrir_dist_fd(1,1,:) + hrir_close_td(1,1,:) , hrir_dist_td(1,1,:) + }; % list of HRIRs + +col = {'k' 'b' 'g' 'r' 'm' 'c'}; +titlelabels = {'close', 'distant'}; +legendpos = {'northeast', 'southwest'}; + +t = 0:hrtf.API.N-1; % time-axis in samples +f = (0:hrtf.API.N-1)/hrtf.API.N*hrtf.Data.SamplingRate; % frequency axis + +for pdx=1:2 % impulse responses or magnitude spectrum + for cdx=1:size(hrir_list,2) + figure + for rdx=1:size(hrir_list,1) + if pdx == 1 + % impulse responses + plot(t,squeeze(hrir_list{rdx, cdx}),col{rdx}) + else + % magnitude spectra + mag_spectrum = db(abs(fft(squeeze(hrir_list{rdx, cdx})))); + semilogx(f(2:end), mag_spectrum(2:end), col{rdx}); + end + hold on + end + hold off + + if pdx == 1 + % impulse responses + xlabel('samples') + ylabel('amplitude') + axis([0 160 -0.6 0.6]) + else + % magnitude spectra + xlabel('frequency in Hz') + ylabel('amplitude in dB') + axis([f(2) hrtf.Data.SamplingRate/2 -60 20]) + end + legend('hrir_1','hrir_2','hrir_{ref}','simple interp', ... + 'freqdomain interp', 'timedomain interp','Location', legendpos{pdx}) + title(['Interpolation of ' titlelabels{cdx} ' HRIRs']) + end +end + +status = true; diff --git a/validation/test_interpolation_point_selection.m b/validation/test_interpolation_point_selection.m new file mode 100644 index 00000000..ceb2b4ba --- /dev/null +++ b/validation/test_interpolation_point_selection.m @@ -0,0 +1,371 @@ +function status = test_interpolation_point_selection(modus) +%TEST_INTERPOLATION_POINT_SELECTION tests the correctness of the methods +%findconvexcone() and findvoronoi() for interpolation in 3D grids +% +% Usage: status = test_interpolation_point_selection(modus) +% +% Input parameters: +% modus - 0: numerical (quiet) +% 1: visual +% +% Output parameters: +% status - true or false + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters =================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Secondary source grids ========================================== +[X,Y,Z] = sph2cart((0:pi/4:7/4*pi).',pi/4*ones(8,1),ones(8,1)); +x0_upper_ring = [X,Y,Z]; +[X,Y,Z] = sph2cart((0:pi/12:23/12*pi).',zeros(24,1),ones(24,1)); +x0_center_ring = [X,Y,Z]; + +x0_linear = [linspace(-1,1,10).',zeros(10,2)]; +x0_linear_shifted = [linspace(-1,1,10).',ones(10,1),zeros(10,1)]; +south_pole = [0,0,-1]; + +x0_regular_3d = [x0_upper_ring; x0_center_ring; south_pole]; +x0_regular_2d = x0_center_ring*rotation_matrix(pi/100,1); + +x0_arc_2d = x0_regular_2d(1:14,:); + + +%% ===== Definition of test cases ======================================== +% NaN as reference is used as DON'T CARE and is not checked against the real +% value. +% +% --- Regular tests, should not return an error --- +regular_testcases{1} = { + '3D grid, regular case: 3 points selected.', ... % description + 'findconvexcone', ... % method + x0_regular_3d, ... % grid + [2,0.1,0.1], ... % desired point + [9; 10; 1], ... % reference indices + [NaN; NaN; NaN] % reference weights + }; +regular_testcases{2} = { + '3D grid, regular case: 4 points selected, 1 has low weight.', ... + 'findvoronoi' ... + x0_regular_3d, ... + [2,0.1,0.1], ... + [9; 10; 1; 32], ... + [NaN; NaN; NaN; NaN] + }; + +regular_testcases{3} = { + '3D grid, xs coplanar with 2 points: 3 points selected, 1 has zero weight.', ... + 'findconvexcone', ... + x0_regular_3d, ... + [2,0.1,0], ... + [9; 10; NaN], ... + [NaN; NaN; 0] + }; +regular_testcases{4} = { + '3D grid, xs coplanar with 2 points: 4 points selected, 2 have low weight', ... + 'findvoronoi' ... + x0_regular_3d, ... + [2,0.1,0], ... + [9; 10; 1; 33], ... + [NaN; NaN; NaN; NaN] + }; + +regular_testcases{5} = { + '3D grid, xs colinear with 1 point: 3 points selected, 2 have zero weight.', ... + 'findconvexcone', ... + x0_regular_3d, ... + [2,0,0], ... + [9; NaN; NaN], ... + [NaN; 0; 0] + }; +regular_testcases{6} = { + '3D grid, xs colinear with 1 point: 1 point selected.', ... + 'findvoronoi' ... + x0_regular_3d, ... + [2,0,0], ... + [9], ... + [1] + }; + +regular_testcases{7} = { + '2D grid, regular case: 2 points selected.', ... + 'findconvexcone', ... + x0_regular_2d, ... + [2,0.1,0], ... + [1; 2], ... + [NaN; NaN] + }; +regular_testcases{8} = { + '2D grid, regular case: all points selected.', ... + 'findvoronoi' ... + x0_regular_2d, ... + [2,0.1,0], ... + NaN(24,1), ... + NaN(24,1) + }; + +regular_testcases{9} = { + '2D grid, regular case 2: 2 points selected.', ... + 'findconvexcone', ... + x0_regular_2d, ... + [2,0.1,1], ... + [1; 2], ... + [NaN; NaN] + }; +regular_testcases{10} = { + '2D grid, regular case 2: all points selected.', ... + 'findvoronoi' ... + x0_regular_2d, ... + [2,0.1,1], ... + NaN(24,1), ... + NaN(24,1) + }; + +regular_testcases{11} = { + '2D grid, xs colinear with 1 point: 2 points selected, 1 has zero weight.', ... + 'findconvexcone', ... + x0_regular_2d, ... + [2,0,0], ... + [1; 24], ... + [NaN; 0] + }; +regular_testcases{12} = { + '2D grid, xs colinear with 1 point: 1 point selected.', ... + 'findvoronoi' ... + x0_regular_2d, ... + [2,0,0], ... + [1], ... + [1] + }; + +regular_testcases{13} = { + '2D grid, xs coplanar', ... + 'findconvexcone' ... + x0_center_ring, ... + [1,0.2,0], ... + [2; 1], ... + [NaN; NaN] + }; +regular_testcases{14} = { + '2D grid, xs coplanar. ', ... + 'findvoronoi' ... + x0_center_ring, ... + [1,0.2,0], ... + [NaN; NaN], ... + [NaN; NaN] + }; + +regular_testcases{15} = { + '2D grid, arc with gap smaller than 180 deg: 2 points selected.', ... + 'findconvexcone', ... + x0_arc_2d, ... + [2,-2,0], ... + [1; 14], ... + [NaN; NaN] + }; +regular_testcases{16} = { + '2D grid, arc with gap smaller than 180 deg: 2 points selected.', ... + 'findvoronoi' ... + x0_arc_2d, ... + [2,-2,0], ... + NaN(14,1), ... + NaN(14,1) + }; + +regular_testcases{17} = { + 'Partial grid: 3 points selected, 1 has zero weight.', ... + 'findconvexcone', ... + x0_upper_ring, ... + [0,0,1], ... + [NaN; NaN; NaN], ... + [NaN; NaN; NaN] + }; +regular_testcases{18} = { + 'Partial grid: all points selected with equal weigths.', ... + 'findvoronoi' ... + x0_upper_ring, ... + [0,0,1], ... + [NaN; NaN; NaN; NaN; NaN; NaN; NaN; NaN], ... + [NaN; NaN; NaN; NaN; NaN; NaN; NaN; NaN] + }; + +regular_testcases{19} = { + 'Partial grid, requested xs lies outside. Warning is issued.', ... + 'findconvexcone', ... + x0_upper_ring, ... + [1,0,0], ... + [NaN; NaN], ... + [NaN; NaN] + }; +regular_testcases{20} = { + 'Partial grid, requested xs lies outside: all points selected.', ... + 'findvoronoi' ... + x0_upper_ring, ... + [1,0,0], ... + [NaN; NaN; NaN; NaN; NaN; NaN; NaN; NaN], ... + [NaN; NaN; NaN; NaN; NaN; NaN; NaN; NaN] + }; + +regular_testcases{21} = { + 'Grid is not a sphere. Warning is issued.', ... + 'findconvexcone', ... + x0_linear_shifted, ... + [1,1,0], ... + [NaN; NaN], ... + [NaN; NaN] + }; +regular_testcases{22} = { + 'Grid is not a sphere. Warning is issued', ... + 'findvoronoi' ... + x0_linear_shifted, ... + [1,1,0], ... + [10], ... + [1] + }; + +regular_testcases{23} = { + 'Grid and xs are colinear.', ... + 'findvoronoi', ... + x0_linear, ... + [0.1,0,0], ... + [NaN; NaN; NaN; NaN; NaN], ... + [NaN; NaN; NaN; NaN; NaN] + }; + +% --- Erroneous tests, should return an error --- +erroneous_testcases{1} = { + 'Grid and xs are colinear. convhulln raises error', ... + 'findconvexcone', ... + x0_linear, ... + [0.1,0,0] + }; + + +%% ===== Run tests ======================================================= +for testcase_tmp = regular_testcases + testcase = testcase_tmp{1}; + desc_str = testcase{1}; + method = testcase{2}; + x0 = testcase{3}; + xs = testcase{4}; + x0_indices_ref = testcase{5}; + x0_weights_ref = testcase{6}; + if modus + disp(['method: ', method, ', test case: ', desc_str]); + end + + if strcmp('findvoronoi',method) + [indices,weights] = findvoronoi(x0,xs); + elseif strcmp('findconvexcone',method) + [indices,weights] = findconvexcone(x0,xs); + end + + if modus + plot_point_selection(x0,xs,indices,weights,desc_str,method); + end + if any(weights < 0) + error('%s: In %s: negative weights. ', ... + upper(mfilename),desc_str); + end + if ~(all(indices == x0_indices_ref | isnan(x0_indices_ref))) + error('%s: In %s: wrong indices ', ... + upper(mfilename),desc_str); + end + if ~(all(weights == x0_weights_ref| isnan(x0_weights_ref))) + error('%s: In %s: wrong weights ', ... + upper(mfilename),desc_str); + end +end + +for testcase_tmp = erroneous_testcases + testcase = testcase_tmp{1}; + desc_str = testcase{1}; + method = testcase{2}; + x0 = testcase{3}; + xs = testcase{4}; + if modus + plot_point_selection(x0,xs,[],[],desc_str,method); + disp(['method: ', method, ', test case: ' , desc_str]); + end + + if strcmp('findvoronoi',method) + try + findvoronoi(x0,xs) + catch + continue + end + elseif strcmp('findconvexcone',method) + try + findconvexcone(x0,xs) + catch + continue + end + end +end + + +status = true; + + +end + + +%% ===== Functions ======================================================= +function plot_point_selection(x0,xs,indices,weights,desc_str,method) + if isoctave + point_size = 12; + selected_point_size = weights*20 + 1; + else + point_size = 100; + selected_point_size = weights*100 + 1; + end + figure + scatter3(x0(:,1),x0(:,2),x0(:,3),point_size,'b','.'); + hold on + quiver3(0,0,0,xs(1),xs(2),xs(3),'k'); + scatter3(x0(indices,1),x0(indices,2),x0(indices,3),selected_point_size,'r'); + scatter3(x0(indices,1),x0(indices,2),x0(indices,3),point_size,'r','x'); + scatter3(0,0,0,point_size,'k','.'); + hold off + axis equal + xlabel('x'); + ylabel('y'); + zlabel('z'); + legend('x0','xs','weights','selected points','center' ); + title({desc_str; ['Method: ', method]},'interpreter','none'); +end diff --git a/validation/test_linkwitz_riley.m b/validation/test_linkwitz_riley.m new file mode 100644 index 00000000..6f8e7ad2 --- /dev/null +++ b/validation/test_linkwitz_riley.m @@ -0,0 +1,131 @@ +function status = test_linkwitz_riley(modus) +%TEST_LINKWITZ_RILEY tests the design of the Linkwitz-Riley Filters +% +% Usage: status = test_linkwitz_riley(modus) +% +% Input parameters: +% modus - 0: numerical +% 1: visual +% +% Output parameters: +% status - true or false + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + +status = false; + +%% ===== Checking of input parameters =================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + +%% ===== Main ============================================================ +fs = 44100; % sampling frequency in Hz +fc = 1000; % crossover frequency in Hz +f = logspace(-3,log10(fs/2),10000); % frequeny-axis in Hz +omega = 2*pi*f; % angular frequency + +ftype = {'low' 'high' 'all'}; % filter types +Hs = zeros(3,length(f)); % s-domain frequency spectra +Hz = Hs; % z-domain frequency spectra + +for Nlr = [2 4 12] % filter orders + + for tdx = 1:3 + % Laplace-Domain + [zs,ps,ks] = linkwitz_riley(Nlr,2*pi*fc,ftype{tdx},'s'); + [soss,gs] = zp2sos(zs,ps,ks,'down','none'); + + s = [-omega.^2; 1i*omega]; + s(3,:) = 1; + + if isoctave && strcmp(ftype{tdx}, 'low') + % WORKAROUND for Octave bug (https://savannah.gnu.org/bugs/?51936) + Hs(tdx,:) = gs.*prod( (soss(:,3:-1:1)*s)./(soss(:,4:6)*s),1); + else + Hs(tdx,:) = gs.*prod( (soss(:,1:3)*s)./(soss(:,4:6)*s),1); + end + + % z-Domain + [zz,pz,kz] = linkwitz_riley(Nlr,fc./fs*2,ftype{tdx},'z'); + [sosz,gz] = zp2sos(zz,pz,kz,'down','none'); + + z = [exp(0.*omega./fs); exp(-1j.*omega./fs); exp(-2j.*omega./fs)]; + Hz(tdx,:) = gz.*prod( (sosz(:,1:3)*z)./(sosz(:,4:6)*z),1); + end + + % plotting + if modus + figure; + subplot(2,2,1); + plot_amp(f, Hs); + title(sprintf('Amplitude Spectrum, s-Domain, order=%d', Nlr)); + subplot(2,2,2); + plot_phase(f, Hs); + title(sprintf('Phase Spectrum, s-Domain, order=%d', Nlr)); + subplot(2,2,3); + plot_amp(f, Hz); + title(sprintf('Amplitude Spectrum, z-Domain, order=%d', Nlr)); + subplot(2,2,4); + plot_phase(f, Hz); + title(sprintf('Phase Spectrum, z-Domain, order=%d', Nlr)); + end +end + +status = true; + +end + +function plot_amp(f, H) +semilogx( ... + f, db(H(1,:)), 'b', ... + f, db(H(2,:)), 'r', ... + f, db(H(1,:)+H(2,:)), 'g.', ... + f, db(H(3,:)), 'k--' ... + ); +legend('Lowpass', 'Highpass', 'Lowpass + Highpass', 'Allpass', 'Location', 'southwest'); +xlabel('f / Hz'); +ylabel('20 lg |H| / dB') +xlim([f(1), f(end)]); +ylim([-90, 10]); +end + +function plot_phase(f, H) +semilogx( ... + f, unwrap(angle(H(1,:))), 'b', ... + f, unwrap(angle(H(2,:))), 'r', ... + f, unwrap(angle(H(1,:)+H(2,:))), 'g.', ... + f, unwrap(angle(H(3,:))), 'k--' ... + ); +legend('Lowpass', 'Highpass', 'Lowpass + Highpass', 'Allpass', 'Location', 'southwest'); +xlabel('f / Hz'); +ylabel('angle(H) / rad') +xlim([f(1), f(end)]); +end diff --git a/validation/test_localwfs.m b/validation/test_localwfs.m deleted file mode 100644 index 3e52687e..00000000 --- a/validation/test_localwfs.m +++ /dev/null @@ -1,205 +0,0 @@ -function boolean = test_localwfs() -%TEST_LOCALWFS tests the local WFS driving functions -% -% Usage: boolean = test_localwfs() -% -% -% Output parameters: -% booelan - true or false -% -% TEST_LOCALWFS() checks if the local WFS driving functions for the -% monochromatic case are working. Different sound fields are calculated and -% plotted for visual inspection. - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Configuration =================================================== -boolean = false; -% Parameters -conf = SFS_config_example; -conf.plot.useplot = false; -conf.showprogress = true; -conf.resolution = 1000; -conf.plot.loudspeakers = true; -conf.plot.realloudspeakers = false; -conf.usetapwin = true; - - -%% ===== Circular secondary sources ====================================== -% config for real loudspeaker array -conf.dimension = '2D'; -conf.secondary_sources.geometry = 'circular'; -conf.secondary_sources.number = 56; -conf.secondary_sources.size = 2; -conf.secondary_sources.center = [0, 0, 0]; -conf.driving_functions = 'default'; -conf.xref = conf.secondary_sources.center; -% listening area -X = [0 0 0]; -xs = [1.0, -1.0, 0]; % propagation direction of plane wave -src = 'pw'; -xrange = [-1, 1]; -yrange = [-1, 1]; -zrange = 0; -f = 7000; -% --- Circular virtual secondary sources --- -conf.localsfs.method = 'wfs'; -conf.localsfs.usetapwin = false; -conf.localsfs.vss.size = 0.4; -conf.localsfs.vss.center = [0, 0, 0]; -conf.localsfs.vss.geometry = 'circular'; -conf.localsfs.vss.number = 56; -conf.localsfs.vss.consider_target_field = true; -conf.localsfs.vss.consider_secondary_sources = true; -sound_field_mono_localwfs(xrange, yrange, zrange,xs,src,f,conf) -% --- Linear virtual secondary sources --- -conf.localsfs.method = 'wfs'; -conf.localsfs.usetapwin = false; -conf.localsfs.vss.size = 0.4; -conf.localsfs.vss.center = [0, 0.2, 0]; -conf.localsfs.vss.geometry = 'linear'; -conf.localsfs.vss.number = 56; -conf.localsfs.vss.consider_target_field = true; -conf.localsfs.vss.consider_secondary_sources = true; -sound_field_mono_localwfs(xrange, yrange, zrange,xs,src,f,conf) -% --- Box shaped virtual secondary sources --- -conf.localsfs.method = 'wfs'; -conf.localsfs.usetapwin = false; -conf.localsfs.vss.size = 0.4; -conf.localsfs.vss.center = [0, 0, 0]; -conf.localsfs.vss.geometry = 'box'; -conf.localsfs.vss.number = 4*56; -conf.localsfs.vss.consider_target_field = true; -conf.localsfs.vss.consider_secondary_sources = true; -sound_field_mono_localwfs(xrange, yrange, zrange,xs,src,f,conf) - - -%% ===== Linear secondary sources ======================================= -% config for real loudspeaker array -conf.dimension = '2D'; -conf.secondary_sources.geometry = 'linear'; -conf.secondary_sources.number = 56; -conf.secondary_sources.size = 2; -conf.secondary_sources.center = [0, 1, 0]; -conf.driving_functions = 'default'; -% listening area -X = [0 0 0]; -conf.xref = X; -xs = [1.0, -1.0, 0]; % propagation direction of plane wave -src = 'pw'; -xrange = [-1, 1]; -yrange = [-1, 1]; -zrange = 0; -f = 7000; -% --- Circular virtual secondary sources --- -conf.localsfs.method = 'wfs'; -conf.localsfs.usetapwin = false; -conf.localsfs.vss.size = 0.4; -conf.localsfs.vss.center = [0, 0, 0]; -conf.localsfs.vss.geometry = 'circular'; -conf.localsfs.vss.number = 56; -conf.localsfs.vss.consider_target_field = true; -conf.localsfs.vss.consider_secondary_sources = true; -sound_field_mono_localwfs(xrange, yrange, zrange,xs,src,f,conf) -% --- Linear virtual secondary sources --- -conf.localsfs.method = 'wfs'; -conf.localsfs.usetapwin = false; -conf.localsfs.vss.size = 0.4; -conf.localsfs.vss.center = [0, 0.2, 0]; -conf.localsfs.vss.geometry = 'linear'; -conf.localsfs.vss.number = 56; -conf.localsfs.vss.consider_target_field = true; -conf.localsfs.vss.consider_secondary_sources = true; -sound_field_mono_localwfs(xrange, yrange, zrange,xs,src,f,conf) -% --- Box shaped virtual secondary sources --- -conf.localsfs.method = 'wfs'; -conf.localsfs.usetapwin = false; -conf.localsfs.vss.size = 0.4; -conf.localsfs.vss.center = [0, 0, 0]; -conf.localsfs.vss.geometry = 'box'; -conf.localsfs.vss.number = 4*56; -conf.localsfs.vss.consider_target_field = true; -conf.localsfs.vss.consider_secondary_sources = true; -sound_field_mono_localwfs(xrange, yrange, zrange,xs,src,f,conf) - - -%% ===== Box shaped secondary sources =================================== -% config for real loudspeaker array -conf.dimension = '2D'; -conf.secondary_sources.geometry = 'box'; -conf.secondary_sources.number = 4*56; -conf.secondary_sources.size = 2; -conf.secondary_sources.center = [0, 0, 0]; -conf.driving_functions = 'default'; -% listening area -X = [0 0 0]; -conf.xref = X; -xs = [1.0, -1.0, 0]; % propagation direction of plane wave -src = 'pw'; -xrange = [-1, 1]; -yrange = [-1, 1]; -zrange = 0; -f = 7000; -% --- Circular virtual secondary sources --- -conf.localsfs.method = 'wfs'; -conf.localsfs.usetapwin = false; -conf.localsfs.vss.size = 0.4; -conf.localsfs.vss.center = [0, 0, 0]; -conf.localsfs.vss.geometry = 'circular'; -conf.localsfs.vss.number = 56; -conf.localsfs.vss.consider_target_field = true; -conf.localsfs.vss.consider_secondary_sources = true; -sound_field_mono_localwfs(xrange, yrange, zrange,xs,src,f,conf) -% --- Linear virtual secondary sources --- -conf.localsfs.method = 'wfs'; -conf.localsfs.usetapwin = false; -conf.localsfs.vss.size = 0.4; -conf.localsfs.vss.center = [0, 0.2, 0]; -conf.localsfs.vss.geometry = 'linear'; -conf.localsfs.vss.number = 56; -conf.localsfs.vss.consider_target_field = true; -conf.localsfs.vss.consider_secondary_sources = true; -sound_field_mono_localwfs(xrange, yrange, zrange,xs,src,f,conf) -% --- Box shaped virtual secondary sources --- -conf.localsfs.method = 'wfs'; -conf.localsfs.usetapwin = false; -conf.localsfs.vss.size = 0.4; -conf.localsfs.vss.center = [0, 0, 0]; -conf.localsfs.vss.geometry = 'box'; -conf.localsfs.vss.number = 4*56; -conf.localsfs.vss.consider_target_field = true; -conf.localsfs.vss.consider_secondary_sources = true; -sound_field_mono_localwfs(xrange, yrange, zrange,xs,src,f,conf) - -boolean = true; diff --git a/validation/test_localwfs_sbl.m b/validation/test_localwfs_sbl.m new file mode 100644 index 00000000..d1d594eb --- /dev/null +++ b/validation/test_localwfs_sbl.m @@ -0,0 +1,179 @@ +function status = test_localwfs_sbl(modus) +%TEST_LOCALWFS_SBL tests the LWFS-SBL driving functions +% +% Usage: status = test_localwfs_sbl(modus) +% +% Input parameters: +% modus - 0: numerical +% 1: visual +% +% Output parameters: +% status - true or false + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters =================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Configuration =================================================== +% Parameters +conf = SFS_config; + +conf.plot.useplot = modus; +conf.plot.normalisation = 'center'; +conf.plot.loudspeakers = true; +conf.plot.realloudspeakers = false; +conf.resolution = 500; +conf.t0 = 'source'; + +% Default setting for WFS +conf.usetapwin = true; +conf.tapwinlen = 0.3; +% Default settings for LWFS-SBL +conf.localwfs_sbl.fc = 1200; +conf.localwfs_sbl.Npw = 1024; + +% Range for sound field computation +X = [-1 1]; +Y = [-1 1]; +Z = 0; + +f = 4000; + +conf.xref = [0,0,0]; + +% Test scenarios +scenarios = { ... + '2.5D', 'circular', 10, 'pw', [1 -1.0 0], 'mono' + '2.5D', 'circular', 20, 'pw', [1 -1.0 0], 'mono' + '2.5D', 'circular', 30, 'pw', [1 -1.0 0], 'mono' + '2.5D', 'linear', 10, 'pw', [1 -1.0 0], 'mono' + '2.5D', 'linear', 20, 'pw', [1 -1.0 0], 'mono' + '2.5D', 'linear', 30, 'pw', [1 -1.0 0], 'mono' + '2.5D', 'box', 10, 'pw', [1 -1.0 0], 'mono' + '2.5D', 'box', 20, 'pw', [1 -1.0 0], 'mono' + '2.5D', 'box', 30, 'pw', [1 -1.0 0], 'mono' + '2.5D', 'circular', 10, 'ps', [1 2.5 0], 'mono' + '2.5D', 'circular', 20, 'ps', [1 2.5 0], 'mono' + '2.5D', 'circular', 30, 'ps', [1 2.5 0], 'mono' + '2.5D', 'linear', 10, 'ps', [1 2.5 0], 'mono' + '2.5D', 'linear', 20, 'ps', [1 2.5 0], 'mono' + '2.5D', 'linear', 30, 'ps', [1 2.5 0], 'mono' + '2.5D', 'box', 10, 'ps', [1 2.5 0], 'mono' + '2.5D', 'box', 20, 'ps', [1 2.5 0], 'mono' + '2.5D', 'box', 30, 'ps', [1 2.5 0], 'mono' + '2.5D', 'circular', 10, 'pw', [1 -1.0 0], 'imp' + '2.5D', 'circular', 20, 'pw', [1 -1.0 0], 'imp' + '2.5D', 'circular', 30, 'pw', [1 -1.0 0], 'imp' + '2.5D', 'linear', 10, 'pw', [1 -1.0 0], 'imp' + '2.5D', 'linear', 20, 'pw', [1 -1.0 0], 'imp' + '2.5D', 'linear', 30, 'pw', [1 -1.0 0], 'imp' + '2.5D', 'box', 10, 'pw', [1 -1.0 0], 'imp' + '2.5D', 'box', 20, 'pw', [1 -1.0 0], 'imp' + '2.5D', 'box', 30, 'pw', [1 -1.0 0], 'imp' + '2.5D', 'circular', 10, 'ps', [1 2.5 0], 'imp' + '2.5D', 'circular', 20, 'ps', [1 2.5 0], 'imp' + '2.5D', 'circular', 30, 'ps', [1 2.5 0], 'imp' + '2.5D', 'linear', 10, 'ps', [1 2.5 0], 'imp' + '2.5D', 'linear', 20, 'ps', [1 2.5 0], 'imp' + '2.5D', 'linear', 30, 'ps', [1 2.5 0], 'imp' + '2.5D', 'box', 10, 'ps', [1 2.5 0], 'imp' + '2.5D', 'box', 20, 'ps', [1 2.5 0], 'imp' + '2.5D', 'box', 30, 'ps', [1 2.5 0], 'imp' + }; + +% Start testing +for ii=1:size(scenarios,1) + + conf.dimension = scenarios{ii,1}; + + % Set loudspeaker array + switch scenarios{ii,2} + case 'linear' + conf.secondary_sources.geometry = 'linear'; + conf.secondary_sources.number = 56; + conf.secondary_sources.size = 2; + conf.secondary_sources.center = [0 1 0]; + case 'circular' + conf.secondary_sources.geometry = 'circular'; + conf.secondary_sources.number = 56; + conf.secondary_sources.size = 2; + conf.secondary_sources.center = [0 0 0]; + case 'box' + conf.secondary_sources.geometry = 'box'; + conf.secondary_sources.number = 56*4; + conf.secondary_sources.size = 2; + conf.secondary_sources.center = [0 0 0]; + end + + conf.localwfs_sbl.order = scenarios{ii,3}; + + % Set desired sound field + src = scenarios{ii,4}; + xs = scenarios{ii,5}; + + % Set domain (monochromatic or time) + switch scenarios{ii,6} + case 'mono' + conf.plot.usedb = false; + [~] = sound_field_mono_localwfs_sbl(X,Y,Z,xs,src,f,conf); + case 'imp' + % Set t for time-shapshot + switch src + case {'ps', 'ls', 'fs'} + t = norm(xs - conf.xref)/conf.c; + case {'pw'} + t = 0; + otherwise + error('unknown source type'); + end + conf.plot.usedb = true; + [~] = sound_field_imp_localwfs_sbl(X,Y,Z,xs,src,t,conf); + end + + progress_bar(ii,size(scenarios,1)); + + % Title of plot + if modus + title(sprintf(['LWFS-SBL (%s,%s): %s SSD, order: %d, %s' ... + ' (%02.02f, %02.02f, %02.02f)'], scenarios{ii,1}, scenarios{ii,6}... + , scenarios{ii,2}, scenarios{ii,3}, src, xs)); + end +end + + +status = true; diff --git a/validation/test_localwfs_vss.m b/validation/test_localwfs_vss.m new file mode 100644 index 00000000..7dc4673a --- /dev/null +++ b/validation/test_localwfs_vss.m @@ -0,0 +1,199 @@ +function status = test_localwfs_vss(modus) +%TEST_LOCALWFS_VSS tests the LWFS-VSS driving functions +% +% Usage: status = test_localwfs(modus) +% +% Input parameters: +% modus - 0: numerical +% 1: visual +% +% Output parameters: +% status - true or false + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters =================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Configuration =================================================== +% Parameters +conf = SFS_config; + +conf.showprogress = true; + +conf.plot.useplot = modus; +conf.plot.normalisation = 'center'; +conf.plot.loudspeakers = true; +conf.plot.realloudspeakers = false; +conf.resolution = 500; +conf.t0 = 'source'; + +% default setting for WFS +conf.usetapwin = true; +conf.tapwinlen = 0.3; + +% default settings for LWFS-VSS +conf.localwfs_vss.method = 'wfs'; +conf.localwfs_vss.usetapwin = true; +conf.localsfstapwinlen = 0.3; +conf.localwfs_vss.consider_target_field = true; +conf.localwfs_vss.consider_secondary_sources = true; + +% range for sound field computation +X = [-1 1]; +Y = [-1 1]; +Z = 0; + +f = 7000; + +conf.xref = [0,0,0]; + +% test scenarios +scenarios = { ... + '2.5D', 'circular', 'circular', 'pw', [1 -1.0 0], 'mono' + '2.5D', 'circular', 'linear', 'pw', [1 -1.0 0], 'mono' + '2.5D', 'circular', 'box', 'pw', [1 -1.0 0], 'mono' + '2.5D', 'linear', 'circular', 'pw', [1 -1.0 0], 'mono' + '2.5D', 'linear', 'linear', 'pw', [1 -1.0 0], 'mono' + '2.5D', 'linear', 'box', 'pw', [1 -1.0 0], 'mono' + '2.5D', 'box', 'circular', 'pw', [1 -1.0 0], 'mono' + '2.5D', 'box', 'linear', 'pw', [1 -1.0 0], 'mono' + '2.5D', 'box', 'box', 'pw', [1 -1.0 0], 'mono' + '2.5D', 'circular', 'circular', 'ps', [1 2.5 0], 'mono' + '2.5D', 'circular', 'linear', 'ps', [1 2.5 0], 'mono' + '2.5D', 'circular', 'box', 'ps', [1 2.5 0], 'mono' + '2.5D', 'linear', 'circular', 'ps', [1 2.5 0], 'mono' + '2.5D', 'linear', 'linear', 'ps', [1 2.5 0], 'mono' + '2.5D', 'linear', 'box', 'ps', [1 2.5 0], 'mono' + '2.5D', 'box', 'circular', 'ps', [1 2.5 0], 'mono' + '2.5D', 'box', 'linear', 'ps', [1 2.5 0], 'mono' + '2.5D', 'box', 'box', 'ps', [1 2.5 0], 'mono' + '2.5D', 'circular', 'circular', 'pw', [1 -1.0 0], 'imp' + '2.5D', 'circular', 'linear', 'pw', [1 -1.0 0], 'imp' + '2.5D', 'circular', 'box', 'pw', [1 -1.0 0], 'imp' + '2.5D', 'linear', 'circular', 'pw', [1 -1.0 0], 'imp' + '2.5D', 'linear', 'linear', 'pw', [1 -1.0 0], 'imp' + '2.5D', 'linear', 'box', 'pw', [1 -1.0 0], 'imp' + '2.5D', 'box', 'circular', 'pw', [1 -1.0 0], 'imp' + '2.5D', 'box', 'linear', 'pw', [1 -1.0 0], 'imp' + '2.5D', 'box', 'box', 'pw', [1 -1.0 0], 'imp' + '2.5D', 'circular', 'circular', 'ps', [1 2.5 0], 'imp' + '2.5D', 'circular', 'linear', 'ps', [1 2.5 0], 'imp' + '2.5D', 'circular', 'box', 'ps', [1 2.5 0], 'imp' + '2.5D', 'linear', 'circular', 'ps', [1 2.5 0], 'imp' + '2.5D', 'linear', 'linear', 'ps', [1 2.5 0], 'imp' + '2.5D', 'linear', 'box', 'ps', [1 2.5 0], 'imp' + '2.5D', 'box', 'circular', 'ps', [1 2.5 0], 'imp' + '2.5D', 'box', 'linear', 'ps', [1 2.5 0], 'imp' + '2.5D', 'box', 'box', 'ps', [1 2.5 0], 'imp' + }; + +% Start testing +for ii=1:size(scenarios) + + conf.dimension = scenarios{ii,1}; + + % set loudspeaker array + switch scenarios{ii,2} + case 'linear' + conf.secondary_sources.geometry = 'linear'; + conf.secondary_sources.number = 56; + conf.secondary_sources.size = 2; + conf.secondary_sources.center = [0 1 0]; + case 'circular' + conf.secondary_sources.geometry = 'circular'; + conf.secondary_sources.number = 56; + conf.secondary_sources.size = 2; + conf.secondary_sources.center = [0 0 0]; + case 'box' + conf.secondary_sources.geometry = 'box'; + conf.secondary_sources.number = 56*4; + conf.secondary_sources.size = 2; + conf.secondary_sources.center = [0 0 0]; + end + + % set virtual source distribution + switch scenarios{ii,3} + case 'linear' + conf.localwfs_vss.size = 0.4; + conf.localwfs_vss.center = [0 0.2 0]; + conf.localwfs_vss.geometry = 'linear'; + conf.localwfs_vss.number = 56; + case 'circular' + conf.localwfs_vss.size = 0.4; + conf.localwfs_vss.center = [0 0 0]; + conf.localwfs_vss.geometry = 'circular'; + conf.localwfs_vss.number = 56; + case 'box' + conf.localwfs_vss.size = 0.4; + conf.localwfs_vss.center = [0 0 0]; + conf.localwfs_vss.geometry = 'box'; + conf.localwfs_vss.number = 4*56; + end + + % set desired sound field + src = scenarios{ii,4}; + xs = scenarios{ii,5}; + + % set domain (monochromatic or time) + switch scenarios{ii,6} + case 'mono' + conf.plot.usedb = false; + [~] = sound_field_mono_localwfs_vss(X,Y,Z,xs,src,f,conf); + case 'imp' + % set t for time-shapshot + switch src + case {'ps', 'ls', 'fs'} + t = norm(xs - conf.xref)/conf.c; + case {'pw'} + t = 0; + otherwise + error('unknown source type'); + end + conf.plot.usedb = true; + [~] = sound_field_imp_localwfs_vss(X,Y,Z,xs,src,t,conf); + end + + % title of plot + if modus + title(sprintf(['LWFS-VSS (%s,%s): %s SSD, %s virtual SSD, %s' ... + ' (%02.02f, %02.02f, %02.02f)'], scenarios{ii,1}, scenarios{ii,6}... + , scenarios{ii,2}, scenarios{ii,3}, src, xs)); + end +end + +status = true; diff --git a/validation/test_modal_weighting.m b/validation/test_modal_weighting.m new file mode 100644 index 00000000..f66d706e --- /dev/null +++ b/validation/test_modal_weighting.m @@ -0,0 +1,296 @@ +function status = test_modal_weighting(modus) +%TEST_MODAL_WEIGHTING evaluates the modal weighting implementation +% +% Usage: status = test_modal_weighting(modus) +% +% Input parameters: +% modus - 0: numerical +% 1: visual +% +% Output parameters: +% status - true or false +% +% TEST_MODAL_WEIGHTING(modus) tests the implementation of the modal weighting +% window for different local sound field synthesis techniques. + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters ==================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Configuration ================================================== +window_type = {... + 'rect'; ... + 'max-rE'; ... + 'kaiser'; ... + 'tukey'; ... + }; +% For plotting +conf = SFS_config; +conf.dimension = '2.5D'; +conf.secondary_sources.number = 16; +conf.secondary_sources.geometry = 'circular'; +conf.secondary_sources.size = 3; +conf.resolution = 300; +conf.plot.usedb = true; +conf.t0 = 'source'; +X = [-2 2]; +Y = [-2 2]; +Z = 0; +src = 'pw'; + + +%% ===== Computation and Plotting ======================================== +if modus % graphical mode + for window = window_type' + conf.modal_window = window{:}; + update_title = false; + base_title = ['Window: ' window{:}]; + switch conf.modal_window + case {'rect', 'max-rE'} + parameter = 1; + otherwise + parameter = [0 0.5 1]; + update_title = true; + end + for pp = 1:length(parameter) + conf.modal_window_parameter = parameter(pp); + sound_field_imp_nfchoa(X,Y,Z,[0 -1 0],'pw',0,conf); + if update_title + figure_title = [base_title ... + ', Parameter: ' ... + num2str(parameter(pp))]; + else + figure_title = base_title; + end + title(figure_title); + end + end +else % numerical mode + for window = window_type' + conf.modal_window = window{:}; + conf.modal_window_parameter = 0.5; + for order = [1 2] + for ndtft = [2*order+1 3*order+1] + [win,Win,Phi] = ... + modal_weighting(order,ndtft,conf); + [win_ref,Win_ref,Phi_ref] = ... + ref_modal_weighting(order,ndtft,conf); + if any([abs(win-win_ref) ... + abs(Win-Win_ref) ... + abs(Phi-Phi_ref)])>1e14 + return + end + end + end + end +end + + +status = true; + +end + + +function [win,Win,Phi] = ref_modal_weighting(order,ndtft,conf) + % Returns reference values for some orders as calculated by the Matlab + % implementation of commit ... + switch conf.modal_window + case 'rect' + if order==1 && ndtft==2*order+1 + win = [1 1]; + Win = [1 0 0]; + Phi = [0 2.094395102393196 4.188790204786391]; + elseif order==1 && ndtft==3*order+1 + win = [1 1]; + Win = [0.75 0.25 -0.25 0.25]; + Phi = [0 1.570796326794897 3.141592653589793 4.712388980384690]; + elseif order==2 && ndtft==2*order+1 + win = [1 1 1]; + Win = [1 0 0 0 0]; + Phi = [0 ... + 1.256637061435917 ... + 2.513274122871834 ... + 3.769911184307752 ... + 5.026548245743669]; + elseif order==2 && ndtft==3*order+1 + win = [1 1 1]; + Win = [0.714285714285714 ... + 0.257419676543548 ... + -0.178139943388210 ... + 0.063577409701804 ... + 0.063577409701804 ... + -0.178139943388210 ... + 0.257419676543548]; + Phi = [0 ... + 0.897597901025655 ... + 1.795195802051310 ... + 2.692793703076966 ... + 3.590391604102621 ... + 4.487989505128276 ... + 5.385587406153931]; + end + case 'max-rE' + if order==1 && ndtft==2*order+1 + win = [1 0.707106781186548]; + Win = [0.804737854124365 0.097631072937817 0.097631072937817]; + Phi = [0 2.094395102393196 4.188790204786391]; + elseif order==1 && ndtft==3*order+1 + win = [1 0.707106781186548]; + Win = [0.603553390593274 ... + 0.250000000000000 ... + -0.103553390593274 ... + 0.250000000000000]; + Phi = [0 ... + 1.570796326794897 ... + 3.141592653589793 ... + 4.712388980384690]; + elseif order==2 && ndtft==2*order+1 + win = [1 0.866025403784439 0.500000000000000]; + Win = [0.746410161513775 ... + 0.145243228056937 ... + -0.018448308813825 ... + -0.018448308813825 ... + 0.145243228056937]; + Phi = [0 ... + 1.256637061435917 ... + 2.513274122871834 ... + 3.769911184307752 ... + 5.026548245743669]; + elseif order==2 && ndtft==3*order+1 + win = [1 0.866025403784439 0.500000000000000]; + Win = [0.533150115366983 ... + 0.265342154409152 ... + -0.040912347323205 ... + 0.008995135230562 ... + 0.008995135230562 ... + -0.040912347323205 ... + 0.265342154409152]; + Phi = [0 ... + 0.897597901025655 ... + 1.795195802051310 ... + 2.692793703076966 ... + 3.590391604102621 ... + 4.487989505128276 ... + 5.385587406153931]; + end + case {'kaiser', 'kaiser-bessel'} + % conf.modal_window_parameter == 0.5 + if order==1 && ndtft==2*order+1 + win = [1 0.581816879161903]; + Win = [0.721211252774602 0.139394373612699 0.139394373612699]; + Phi = [0 2.094395102393196 4.188790204786391]; + elseif order==1 && ndtft==3*order+1 + win = [1 0.581816879161903]; + Win = [0.540908439580952 ... + 0.250000000000000 ... + -0.040908439580952 ... + 0.250000000000000]; + Phi = [0 ... + 1.570796326794897 ... + 3.141592653589793 ... + 4.712388980384690]; + elseif order==2 && ndtft==2*order+1 + win = [1 0.883766863470753 0.581816879161903]; + Win = [0.786233497053062 ... + 0.120959694808693 ... + -0.014076443335224 ... + -0.014076443335224 ... + 0.120959694808693]; + Phi = [0 ... + 1.256637061435917 ... + 2.513274122871834 ... + 3.769911184307752 ... + 5.026548245743669]; + elseif order==2 && ndtft==3*order+1 + win = [1 0.883766863470753 0.581816879161903]; + Win = [0.561595355037902 ... + 0.263300911786297 ... + -0.063101577944049 ... + 0.019002988638802 ... + 0.019002988638802 ... + -0.063101577944049 ... + 0.263300911786297]; + Phi = [0 ... + 0.897597901025655 ... + 1.795195802051310 ... + 2.692793703076966 ... + 3.590391604102621 ... + 4.487989505128276 ... + 5.385587406153931]; + end + case 'tukey' + % conf.modal_window_parameter == 0.5 + if order==1 && ndtft==2*order+1 + win = [1 0.75]; + Win = [0.833333333333333 0.083333333333333 0.083333333333333]; + Phi = [0 2.094395102393196 4.188790204786391]; + elseif order==1 && ndtft==3*order+1 + win = [1 0.75]; + Win = [0.625 0.250 -0.125 0.250]; + Phi = [0 1.570796326794897 3.141592653589793 4.712388980384690]; + elseif order==2 && ndtft==2*order+1 + win = [1 1 0.5]; + Win = [0.800000000000000 ... + 0.161803398874989 ... + -0.061803398874989 ... + -0.061803398874989 ... + 0.161803398874989]; + Phi = [0 ... + 1.256637061435917 ... + 2.513274122871834 ... + 3.769911184307752 ... + 5.026548245743669]; + elseif order==2 && ndtft==3*order+1 + win = [1 1 0.5]; + Win = [0.571428571428571 ... + 0.289208381394450 ... + -0.049430105116435 ... + -0.025492561992301 ... + -0.025492561992301 ... + -0.049430105116435 ... + 0.289208381394450]; + Phi = [0 ... + 0.897597901025655 ... + 1.795195802051310 ... + 2.692793703076966 ... + 3.590391604102621 ... + 4.487989505128276 ... + 5.385587406153931]; + end + end +end diff --git a/validation/test_non_regular_grid.m b/validation/test_non_regular_grid.m new file mode 100644 index 00000000..fa7cd8db --- /dev/null +++ b/validation/test_non_regular_grid.m @@ -0,0 +1,109 @@ +function status = test_non_regular_grid(modus) +%TEST_IMPULSE_RESPONSES tests time behavior of WFS and local WFS +% +% Usage: status = test_impulse_responses(modus) +% +% Input parameters: +% modus - 0: numerical +% 1: visual +% +% Output parameters: +% status - true or false +% +% TEST_IMPULSE_RESPONSES(modus) compares the time-frequency response of +% WFS and local WFS by calculating impulse responses, their frequency +% spectrum, and spatial-temporal sound field. + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters =================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Configuration =================================================== +%% Parameters +conf = SFS_config; +conf.showprogress = true; +conf.resolution = 400; +if modus + conf.plot.useplot = true; + conf.plot.loudspeakers = true; + conf.plot.realloudspeakers = false; + conf.plot.usedb = false; +end +conf.tapwinlen = 0.3; +% config for array +conf.dimension = '2.5D'; +conf.secondary_sources.geometry = 'circular'; +conf.secondary_sources.number = 56; +conf.secondary_sources.size = 3; +conf.secondary_sources.center = [0, 0, 0]; +conf.driving_functions = 'default'; +conf.xref = [0,0,0]; +% listening area, virtual source +xs = [0.0, 2.5, 0]; % propagation direction of plane wave +src = 'ps'; +f = 1000; +t = 190/conf.fs; + +conf.usenormalisation = true; + +%% ===== Computation ===================================================== +% regular grid +Xreg = [-1.5 1.5]; +Yreg = [-1, 1.55]; +Zreg = 0; + +% non regular grid +alpha = 2*pi / 360 * (0:360-1); +r = linspace(0,conf.secondary_sources.size/2,50); +[alpha,r] = ndgrid(alpha,r); + +Xnon = r.*cos(alpha); +Ynon = r.*sin(alpha); +Znon = 0; + +% sound fields +conf.plot.normalisation = 'center'; +[~] = sound_field_mono_wfs(Xreg,Yreg,Zreg,xs,src,f,conf); +[~] = sound_field_mono_wfs(Xnon,Ynon,Znon,xs,src,f,conf); + +conf.plot.normalisation = 'max'; +[~] = sound_field_imp_wfs(Xreg,Yreg,Zreg,xs,src,t,conf); +[~] = sound_field_imp_wfs(Xnon,Ynon,Znon,xs,src,t,conf); + + +status = true; diff --git a/validation/test_plotting.m b/validation/test_plotting.m new file mode 100644 index 00000000..f63f93bc --- /dev/null +++ b/validation/test_plotting.m @@ -0,0 +1,200 @@ +function status = test_plotting(modus) +%TEST_PLOTTING tests the correctness of plot_sound_field() +% +% Usage: status = test_plot(modus) +% +% Input parameters: +% modus - 0: numerical (not available) +% 1: visual +% +% Output parameters: +% status - true or false + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters ==================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); +if ~modus + warning('%s: numerical modus not available.',upper(mfilename)); + status = true; + return; +end + + +%% ===== Configuration =================================================== +conf = SFS_config; +xs = [0 -1 0]; +src = 'pw'; +f = 1000; +t = 300/conf.fs; + + +%% ===== Monochromatic plots ============================================= +conf.plot.normalisation = 'center'; +% 3-D plots +tmp = conf.resolution; +conf.resolution = 50; +sound_field_mono_wfs([-2 2],[-2 2],[-2 2],xs,src,f,conf) +title('3D monochromatic sound field') +conf.resolution = tmp; +% 2-D plots +sound_field_mono_wfs([-2 2],[-2 2],0,xs,src,f,conf) +title('2D monochromatic sound field, xy-axes') +sound_field_mono_wfs([-2 2],0,[-2 2],xs,src,f,conf) +title('2D monochromatic sound field, xz-axes') +sound_field_mono_wfs(0,[-2 2],[-2 2],xs,src,f,conf) +title('2D monochromatic sound field, yz-axes') +% 1-D plots +sound_field_mono_wfs([-2 2],0,0,xs,src,f,conf) +title('1D monochromatic sound field, x-axis') +sound_field_mono_wfs(0,[-2 2],0,xs,src,f,conf) +title('1D monochromatic sound field, y-axis') +sound_field_mono_wfs(0,0,[-2 2],xs,src,f,conf) +title('1D monochromatic sound field, z-axis') +% === Custom grid === +x1 = randi([-2000 2000],125000,1)/1000; +x2 = randi([-2000 2000],125000,1)/1000; +x3 = randi([-2000 2000],125000,1)/1000; +% 3-D plots +sound_field_mono_wfs(x1,x2,x3,xs,src,f,conf) +title('3D monochromatic sound field, custom grid') +% 2-D plots +sound_field_mono_wfs(x1,x2,0,xs,src,f,conf) +title('2D monochromatic sound field, xy-axes, custom grid') +sound_field_mono_wfs(x1,0,x2,xs,src,f,conf) +title('2D monochromatic sound field, xz-axes, custom grid') +sound_field_mono_wfs(0,x1,x2,xs,src,f,conf) +title('2D monochromatic sound field, yz-axes, custom grid') +% 1-D plots +sound_field_mono_wfs(x1,0,0,xs,src,f,conf) +title('1D monochromatic sound field, x-axis, custom grid') +sound_field_mono_wfs(0,x2,0,xs,src,f,conf) +title('1D monochromatic sound field, y-axis, custom grid') +sound_field_mono_wfs(0,0,x3,xs,src,f,conf) +title('1D monochromatic sound field, z-axis, custom grid') + + +%% ===== Time-domain plots =============================================== +conf.plot.normalisation = 'max'; +% 3-D plots +tmp = conf.resolution; +conf.resolution = 50; +sound_field_imp_wfs([-2 2],[-2 2],[-2 2],xs,src,t,conf) +title('3D time-domain sound field') +conf.resolution = tmp; +% 2-D plots +sound_field_imp_wfs([-2 2],[-2 2],0,xs,src,t,conf) +title('2D time-domain sound field, xy-axes') +sound_field_imp_wfs([-2 2],0,[-2 2],xs,src,t,conf) +title('2D time-domain sound field, xz-axes') +sound_field_imp_wfs(0,[-2 2],[-2 2],xs,src,t,conf) +title('2D time-domain sound field, yz-axes') +% 1-D plots +sound_field_imp_wfs([-2 2],0,0,xs,src,t,conf) +title('1D time-domain sound field, x-axis') +sound_field_imp_wfs(0,[-2 2],0,xs,src,t,conf) +title('1D time-domain sound field, y-axis') +sound_field_imp_wfs(0,0,[-2 2],xs,src,t,conf) +title('1D time-domain sound field, z-axis') +% === Custom grid === +x1 = randi([-2000 2000],125000,1)/1000; +x2 = randi([-2000 2000],125000,1)/1000; +x3 = randi([-2000 2000],125000,1)/1000; +% 3-D plots +sound_field_imp_wfs(x1,x2,x3,xs,src,t,conf) +title('3D time-domain sound field, custom grid') +% 2-D plots +sound_field_imp_wfs(x1,x2,0,xs,src,t,conf) +title('2D time-domain sound field, xy-axes, custom grid') +sound_field_imp_wfs(x1,0,x2,xs,src,t,conf) +title('2D time-domain sound field, xz-axes, custom grid') +sound_field_imp_wfs(0,x1,x2,xs,src,t,conf) +title('2D time-domain sound field, yz-axes, custom grid') +% 1-D plots +sound_field_imp_wfs(x1,0,0,xs,src,t,conf) +title('1D time-domain sound field, x-axis, custom grid') +sound_field_imp_wfs(0,x2,0,xs,src,t,conf) +title('1D time-domain sound field, y-axis, custom grid') +sound_field_imp_wfs(0,0,x3,xs,src,t,conf) +title('1D time-domain sound field, z-axis, custom grid') + + +%% ===== Time-domain plots in dB ========================================= +conf.plot.usedb = true; +% 3-D plots +tmp = conf.resolution; +conf.resolution = 50; +sound_field_imp_wfs([-2 2],[-2 2],[-2 2],xs,src,t,conf) +title('3D time-domain sound field') +conf.resolution = tmp; +% 2-D plots +sound_field_imp_wfs([-2 2],[-2 2],0,xs,src,t,conf) +title('2D time-domain sound field, xy-axes') +sound_field_imp_wfs([-2 2],0,[-2 2],xs,src,t,conf) +title('2D time-domain sound field, xz-axes') +sound_field_imp_wfs(0,[-2 2],[-2 2],xs,src,t,conf) +title('2D time-domain sound field, yz-axes') +% 1-D plots +sound_field_imp_wfs([-2 2],0,0,xs,src,t,conf) +title('1D time-domain sound field, x-axis') +sound_field_imp_wfs(0,[-2 2],0,xs,src,t,conf) +title('1D time-domain sound field, y-axis') +sound_field_imp_wfs(0,0,[-2 2],xs,src,t,conf) +title('1D time-domain sound field, z-axis') +% === Custom grid === +x1 = randi([-2000 2000],125000,1)/1000; +x2 = randi([-2000 2000],125000,1)/1000; +x3 = randi([-2000 2000],125000,1)/1000; +% 3-D plots +sound_field_imp_wfs(x1,x2,x3,xs,src,t,conf) +title('3D time-domain sound field, custom grid') +% 2-D plots +sound_field_imp_wfs(x1,x2,0,xs,src,t,conf) +title('2D time-domain sound field, xy-axes, custom grid') +sound_field_imp_wfs(x1,0,x2,xs,src,t,conf) +title('2D time-domain sound field, xz-axes, custom grid') +sound_field_imp_wfs(0,x1,x2,xs,src,t,conf) +title('2D time-domain sound field, yz-axes, custom grid') +% 1-D plots +sound_field_imp_wfs(x1,0,0,xs,src,t,conf) +title('1D time-domain sound field, x-axis, custom grid') +sound_field_imp_wfs(0,x2,0,xs,src,t,conf) +title('1D time-domain sound field, y-axis, custom grid') +sound_field_imp_wfs(0,0,x3,xs,src,t,conf) +title('1D time-domain sound field, z-axis, custom grid') + + +status = true; diff --git a/validation/test_secondary_source_diameter.m b/validation/test_secondary_source_diameter.m new file mode 100644 index 00000000..3fd79591 --- /dev/null +++ b/validation/test_secondary_source_diameter.m @@ -0,0 +1,281 @@ +function status = test_secondary_source_diameter(modus) +%TEST_SECONDARY_SOURCE_DIAMETER tests the correctness of the function +%secondary_source_diameter() +% +% Usage: status = test_secondary_source_diameter(modus) +% +% Input parameters: +% modus - 0: numerical +% 1: visual (not available) +% 2: numerical verbose +% +% Output parameters: +% status - true or false + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters =================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Main ============================================================ +% reference values +diam_linear_ref = 4; +center_linear_ref = 0; +x0_linear = [ + -2.0000 0 0 0 -1.0000 0 0.2 + -1.8000 0 0 0 -1.0000 0 0.2 + -1.6000 0 0 0 -1.0000 0 0.2 + -1.4000 0 0 0 -1.0000 0 0.2 + -1.2000 0 0 0 -1.0000 0 0.2 + -1.0000 0 0 0 -1.0000 0 0.2 + -0.8000 0 0 0 -1.0000 0 0.2 + -0.6000 0 0 0 -1.0000 0 0.2 + -0.4000 0 0 0 -1.0000 0 0.2 + -0.2000 0 0 0 -1.0000 0 0.2 + 0 0 0 0 -1.0000 0 0.2 + 0.2000 0 0 0 -1.0000 0 0.2 + 0.4000 0 0 0 -1.0000 0 0.2 + 0.6000 0 0 0 -1.0000 0 0.2 + 0.8000 0 0 0 -1.0000 0 0.2 + 1.0000 0 0 0 -1.0000 0 0.2 + 1.2000 0 0 0 -1.0000 0 0.2 + 1.4000 0 0 0 -1.0000 0 0.2 + 1.6000 0 0 0 -1.0000 0 0.2 + 1.8000 0 0 0 -1.0000 0 0.2 + 2.0000 0 0 0 -1.0000 0 0.2 + ]; +diam_circle_ref = 3.99876557777522; +center_circle_ref = [-0.0488700000000000 0.0098799999999999 0.0000000000000000]; +x0_circle = [ + 2.00000 0.00000 0.00000 -1.00000 0.00000 0.00000 0.1995 + 1.99006 0.19914 0.00000 -0.99503 -0.09957 0.00000 0.1995 + 1.96034 0.39629 0.00000 -0.98017 -0.19815 0.00000 0.1995 + 1.91115 0.58951 0.00000 -0.95557 -0.29476 0.00000 0.1995 + 1.84295 0.77687 0.00000 -0.92148 -0.38843 0.00000 0.1995 + 1.75644 0.95651 0.00000 -0.87822 -0.47825 0.00000 0.1995 + 1.65248 1.12664 0.00000 -0.82624 -0.56332 0.00000 0.1995 + 1.53209 1.28558 0.00000 -0.76604 -0.64279 0.00000 0.1995 + 1.39647 1.43173 0.00000 -0.69824 -0.71587 0.00000 0.1995 + 1.24698 1.56366 0.00000 -0.62349 -0.78183 0.00000 0.1995 + 1.08509 1.68005 0.00000 -0.54255 -0.84003 0.00000 0.1995 + 0.91242 1.77974 0.00000 -0.45621 -0.88987 0.00000 0.1995 + 0.73068 1.86175 0.00000 -0.36534 -0.93087 0.00000 0.1995 + 0.54168 1.92525 0.00000 -0.27084 -0.96262 0.00000 0.1995 + 0.34730 1.96962 0.00000 -0.17365 -0.98481 0.00000 0.1995 + 0.14946 1.99441 0.00000 -0.07473 -0.99720 0.00000 0.1995 + -0.04986 1.99938 0.00000 0.02493 -0.99969 0.00000 0.1995 + -0.24869 1.98448 0.00000 0.12434 -0.99224 0.00000 0.1995 + -0.44504 1.94986 0.00000 0.22252 -0.97493 0.00000 0.1995 + -0.63697 1.89585 0.00000 0.31849 -0.94793 0.00000 0.1995 + -0.82257 1.82301 0.00000 0.41129 -0.91151 0.00000 0.1995 + -1.00000 1.73205 0.00000 0.50000 -0.86603 0.00000 0.1995 + -1.16749 1.62388 0.00000 0.58374 -0.81194 0.00000 0.1995 + -1.32337 1.49956 0.00000 0.66169 -0.74978 0.00000 0.1995 + -1.46610 1.36035 0.00000 0.73305 -0.68017 0.00000 0.1995 + -1.59427 1.20761 0.00000 0.79713 -0.60380 0.00000 0.1995 + -1.70658 1.04287 0.00000 0.85329 -0.52144 0.00000 0.1995 + -1.80194 0.86777 0.00000 0.90097 -0.43388 0.00000 0.1995 + -1.87939 0.68404 0.00000 0.93969 -0.34202 0.00000 0.1995 + -1.93815 0.49351 0.00000 0.96908 -0.24676 0.00000 0.1995 + -1.97766 0.29808 0.00000 0.98883 -0.14904 0.00000 0.1995 + -1.99751 0.09969 0.00000 0.99876 -0.04985 0.00000 0.1995 + -1.99751 -0.09969 0.00000 0.99876 0.04985 0.00000 0.1995 + -1.97766 -0.29808 0.00000 0.98883 0.14904 0.00000 0.1995 + -1.93815 -0.49351 0.00000 0.96908 0.24676 0.00000 0.1995 + -1.87939 -0.68404 0.00000 0.93969 0.34202 0.00000 0.1995 + -1.80194 -0.86777 0.00000 0.90097 0.43388 0.00000 0.1995 + -1.70658 -1.04287 0.00000 0.85329 0.52144 0.00000 0.1995 + -1.59427 -1.20761 0.00000 0.79713 0.60380 0.00000 0.1995 + -1.46610 -1.36035 0.00000 0.73305 0.68017 0.00000 0.1995 + -1.32337 -1.49956 0.00000 0.66169 0.74978 0.00000 0.1995 + -1.16749 -1.62388 0.00000 0.58374 0.81194 0.00000 0.1995 + -1.00000 -1.73205 0.00000 0.50000 0.86603 0.00000 0.1995 + -0.82257 -1.82301 0.00000 0.41129 0.91151 0.00000 0.1995 + -0.63697 -1.89585 0.00000 0.31849 0.94793 0.00000 0.1995 + -0.44504 -1.94986 0.00000 0.22252 0.97493 0.00000 0.1995 + -0.24869 -1.98448 0.00000 0.12434 0.99224 0.00000 0.1995 + -0.04986 -1.99938 0.00000 0.02493 0.99969 0.00000 0.1995 + 0.14946 -1.99441 0.00000 -0.07473 0.99720 0.00000 0.1995 + 0.34730 -1.96962 0.00000 -0.17365 0.98481 0.00000 0.1995 + 0.54168 -1.92525 0.00000 -0.27084 0.96262 0.00000 0.1995 + 0.73068 -1.86175 0.00000 -0.36534 0.93087 0.00000 0.1995 + 0.91242 -1.77974 0.00000 -0.45621 0.88987 0.00000 0.1995 + 1.08509 -1.68005 0.00000 -0.54255 0.84003 0.00000 0.1995 + 1.24698 -1.56366 0.00000 -0.62349 0.78183 0.00000 0.1995 + 1.39647 -1.43173 0.00000 -0.69824 0.71587 0.00000 0.1995 + 1.53209 -1.28558 0.00000 -0.76604 0.64279 0.00000 0.1995 + 1.65248 -1.12664 0.00000 -0.82624 0.56332 0.00000 0.1995 + 1.75644 -0.95651 0.00000 -0.87822 0.47825 0.00000 0.1995 + 1.84295 -0.77687 0.00000 -0.92148 0.38843 0.00000 0.1995 + 1.91115 -0.58951 0.00000 -0.95557 0.29476 0.00000 0.1995 + 1.96034 -0.39629 0.00000 -0.98017 0.19815 0.00000 0.1995 + 1.99006 -0.19914 0.00000 -0.99503 0.09957 0.00000 0.1995 + ]; +diam_box_ref = 5.946427498927402; +center_box_ref = 0; +x0_box = [ + 2.2000 -2.0000 0 -1.0000 0 0 0.2414 + 2.2000 -1.8000 0 -1.0000 0 0 0.2000 + 2.2000 -1.6000 0 -1.0000 0 0 0.2000 + 2.2000 -1.4000 0 -1.0000 0 0 0.2000 + 2.2000 -1.2000 0 -1.0000 0 0 0.2000 + 2.2000 -1.0000 0 -1.0000 0 0 0.2000 + 2.2000 -0.8000 0 -1.0000 0 0 0.2000 + 2.2000 -0.6000 0 -1.0000 0 0 0.2000 + 2.2000 -0.4000 0 -1.0000 0 0 0.2000 + 2.2000 -0.2000 0 -1.0000 0 0 0.2000 + 2.2000 0 0 -1.0000 0 0 0.2000 + 2.2000 0.2000 0 -1.0000 0 0 0.2000 + 2.2000 0.4000 0 -1.0000 0 0 0.2000 + 2.2000 0.6000 0 -1.0000 0 0 0.2000 + 2.2000 0.8000 0 -1.0000 0 0 0.2000 + 2.2000 1.0000 0 -1.0000 0 0 0.2000 + 2.2000 1.2000 0 -1.0000 0 0 0.2000 + 2.2000 1.4000 0 -1.0000 0 0 0.2000 + 2.2000 1.6000 0 -1.0000 0 0 0.2000 + 2.2000 1.8000 0 -1.0000 0 0 0.2000 + 2.2000 2.0000 0 -1.0000 0 0 0.2414 + 2.0000 2.2000 0 0 -1.0000 0 0.2414 + 1.8000 2.2000 0 0 -1.0000 0 0.2000 + 1.6000 2.2000 0 0 -1.0000 0 0.2000 + 1.4000 2.2000 0 0 -1.0000 0 0.2000 + 1.2000 2.2000 0 0 -1.0000 0 0.2000 + 1.0000 2.2000 0 0 -1.0000 0 0.2000 + 0.8000 2.2000 0 0 -1.0000 0 0.2000 + 0.6000 2.2000 0 0 -1.0000 0 0.2000 + 0.4000 2.2000 0 0 -1.0000 0 0.2000 + 0.2000 2.2000 0 0 -1.0000 0 0.2000 + 0 2.2000 0 0 -1.0000 0 0.2000 + -0.2000 2.2000 0 0 -1.0000 0 0.2000 + -0.4000 2.2000 0 0 -1.0000 0 0.2000 + -0.6000 2.2000 0 0 -1.0000 0 0.2000 + -0.8000 2.2000 0 0 -1.0000 0 0.2000 + -1.0000 2.2000 0 0 -1.0000 0 0.2000 + -1.2000 2.2000 0 0 -1.0000 0 0.2000 + -1.4000 2.2000 0 0 -1.0000 0 0.2000 + -1.6000 2.2000 0 0 -1.0000 0 0.2000 + -1.8000 2.2000 0 0 -1.0000 0 0.2000 + -2.0000 2.2000 0 0 -1.0000 0 0.2414 + -2.2000 2.0000 0 1.0000 0 0 0.2414 + -2.2000 1.8000 0 1.0000 0 0 0.2000 + -2.2000 1.6000 0 1.0000 0 0 0.2000 + -2.2000 1.4000 0 1.0000 0 0 0.2000 + -2.2000 1.2000 0 1.0000 0 0 0.2000 + -2.2000 1.0000 0 1.0000 0 0 0.2000 + -2.2000 0.8000 0 1.0000 0 0 0.2000 + -2.2000 0.6000 0 1.0000 0 0 0.2000 + -2.2000 0.4000 0 1.0000 0 0 0.2000 + -2.2000 0.2000 0 1.0000 0 0 0.2000 + -2.2000 0 0 1.0000 0 0 0.2000 + -2.2000 -0.2000 0 1.0000 0 0 0.2000 + -2.2000 -0.4000 0 1.0000 0 0 0.2000 + -2.2000 -0.6000 0 1.0000 0 0 0.2000 + -2.2000 -0.8000 0 1.0000 0 0 0.2000 + -2.2000 -1.0000 0 1.0000 0 0 0.2000 + -2.2000 -1.2000 0 1.0000 0 0 0.2000 + -2.2000 -1.4000 0 1.0000 0 0 0.2000 + -2.2000 -1.6000 0 1.0000 0 0 0.2000 + -2.2000 -1.8000 0 1.0000 0 0 0.2000 + -2.2000 -2.0000 0 1.0000 0 0 0.2414 + -2.0000 -2.2000 0 0 1.0000 0 0.2414 + -1.8000 -2.2000 0 0 1.0000 0 0.2000 + -1.6000 -2.2000 0 0 1.0000 0 0.2000 + -1.4000 -2.2000 0 0 1.0000 0 0.2000 + -1.2000 -2.2000 0 0 1.0000 0 0.2000 + -1.0000 -2.2000 0 0 1.0000 0 0.2000 + -0.8000 -2.2000 0 0 1.0000 0 0.2000 + -0.6000 -2.2000 0 0 1.0000 0 0.2000 + -0.4000 -2.2000 0 0 1.0000 0 0.2000 + -0.2000 -2.2000 0 0 1.0000 0 0.2000 + 0 -2.2000 0 0 1.0000 0 0.2000 + 0.2000 -2.2000 0 0 1.0000 0 0.2000 + 0.4000 -2.2000 0 0 1.0000 0 0.2000 + 0.6000 -2.2000 0 0 1.0000 0 0.2000 + 0.8000 -2.2000 0 0 1.0000 0 0.2000 + 1.0000 -2.2000 0 0 1.0000 0 0.2000 + 1.2000 -2.2000 0 0 1.0000 0 0.2000 + 1.4000 -2.2000 0 0 1.0000 0 0.2000 + 1.6000 -2.2000 0 0 1.0000 0 0.2000 + 1.8000 -2.2000 0 0 1.0000 0 0.2000 + 2.0000 -2.2000 0 0 1.0000 0 0.2414 + ]; + + +%% ===== Test secondary_source_diamter() ================================= +% Calculate current values +% Linear array +conf.secondary_sources.geometry = 'custom'; +conf.secondary_sources.x0 = x0_linear; +[diam_linear,center_linear] = secondary_source_diameter(conf); +% Circular array +conf.secondary_sources.x0 = x0_circle; +[diam_circle,center_circle] = secondary_source_diameter(conf); +% Box form array +conf.secondary_sources.x0 = x0_box; +[diam_box,center_box] = secondary_source_diameter(conf); + +if modus==0 + % Numerical mode (quiet) + if abs(diam_linear-diam_linear_ref)>eps || ... + abs(diam_circle-diam_circle_ref)>10e-12 || ... + abs(diam_box-diam_box_ref)>10e-12 || ... + norm(center_linear-center_linear_ref)>eps || ... + norm(center_circle-center_circle_ref)>eps || ... + norm(center_box-center_box_ref)>eps + return; + end +elseif modus==2 + if abs(diam_linear-diam_linear_ref)>eps + error('%s: wrong diameter for linear array.',upper(mfilename)); + elseif norm(center_linear-center_linear_ref)>eps + error('%s: wrong center for linear array.',upper(mfilename)); + elseif abs(diam_circle-diam_circle_ref)>10e-12 + error('%s: wrong diameter for circular array.',upper(mfilename)); + elseif norm(center_circle-center_circle_ref)>eps + error('%s: wrong center for circular array.',upper(mfilename)); + elseif abs(diam_box-diam_box_ref)>10e-12 + error('%s: wrong diameter for box shaped array.',upper(mfilename)); + elseif norm(center_box-center_box_ref)>eps + error('%s: wrong center for box shaped array.',upper(mfilename)); + end +else + error('%s: modus has to be 0 (numerical quiet) or 1 (numerical).', ... + upper(mfilename)); +end + + +status = true; diff --git a/validation/test_secondary_source_positions.m b/validation/test_secondary_source_positions.m new file mode 100644 index 00000000..3224f50d --- /dev/null +++ b/validation/test_secondary_source_positions.m @@ -0,0 +1,297 @@ +function status = test_secondary_source_positions(modus) +%TEST_SECONDARY_SOURCE_POSITIONS tests the correctness of the function +%secondary_source_positions() +% +% Usage: status = test_secondary_source_positions(modus) +% +% Input parameters: +% modus - 0: numerical +% 1: visual +% 2: numerical verbose +% +% Output parameters: +% status - true or false + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters =================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Main ============================================================ +conf = SFS_config; +% reference values +x0_linear_ref = [ + -2.0000 0 0 0 -1.0000 0 0.2 + -1.8000 0 0 0 -1.0000 0 0.2 + -1.6000 0 0 0 -1.0000 0 0.2 + -1.4000 0 0 0 -1.0000 0 0.2 + -1.2000 0 0 0 -1.0000 0 0.2 + -1.0000 0 0 0 -1.0000 0 0.2 + -0.8000 0 0 0 -1.0000 0 0.2 + -0.6000 0 0 0 -1.0000 0 0.2 + -0.4000 0 0 0 -1.0000 0 0.2 + -0.2000 0 0 0 -1.0000 0 0.2 + 0 0 0 0 -1.0000 0 0.2 + 0.2000 0 0 0 -1.0000 0 0.2 + 0.4000 0 0 0 -1.0000 0 0.2 + 0.6000 0 0 0 -1.0000 0 0.2 + 0.8000 0 0 0 -1.0000 0 0.2 + 1.0000 0 0 0 -1.0000 0 0.2 + 1.2000 0 0 0 -1.0000 0 0.2 + 1.4000 0 0 0 -1.0000 0 0.2 + 1.6000 0 0 0 -1.0000 0 0.2 + 1.8000 0 0 0 -1.0000 0 0.2 + 2.0000 0 0 0 -1.0000 0 0.2 + ]; +x0_linear_log_pos_ref = [ + -7.0000 0 0 0 -1.0000 0 8*log(2) + -3.0000 0 0 0 -1.0000 0 4*log(2) + -1.0000 0 0 0 -1.0000 0 2*log(2) + 0 0 0 0 -1.0000 0 1*log(2) + 1.0000 0 0 0 -1.0000 0 2*log(2) + 3.0000 0 0 0 -1.0000 0 4*log(2) + 7.0000 0 0 0 -1.0000 0 8*log(2) + ]; +x0_linear_log_neg_ref = [ + -7.0000 0 0 0 -1.0000 0 1*log(2) + -6.0000 0 0 0 -1.0000 0 2*log(2) + -4.0000 0 0 0 -1.0000 0 4*log(2) + 0 0 0 0 -1.0000 0 8*log(2) + 4.0000 0 0 0 -1.0000 0 4*log(2) + 6.0000 0 0 0 -1.0000 0 2*log(2) + 7.0000 0 0 0 -1.0000 0 1*log(2) + ]; +x0_circle_ref = [ + 2.00000 0.00000 0.00000 -1.00000 0.00000 0.00000 0.1995 + 1.99006 0.19914 0.00000 -0.99503 -0.09957 0.00000 0.1995 + 1.96034 0.39629 0.00000 -0.98017 -0.19815 0.00000 0.1995 + 1.91115 0.58951 0.00000 -0.95557 -0.29476 0.00000 0.1995 + 1.84295 0.77687 0.00000 -0.92148 -0.38843 0.00000 0.1995 + 1.75644 0.95651 0.00000 -0.87822 -0.47825 0.00000 0.1995 + 1.65248 1.12664 0.00000 -0.82624 -0.56332 0.00000 0.1995 + 1.53209 1.28558 0.00000 -0.76604 -0.64279 0.00000 0.1995 + 1.39647 1.43173 0.00000 -0.69824 -0.71587 0.00000 0.1995 + 1.24698 1.56366 0.00000 -0.62349 -0.78183 0.00000 0.1995 + 1.08509 1.68005 0.00000 -0.54255 -0.84003 0.00000 0.1995 + 0.91242 1.77974 0.00000 -0.45621 -0.88987 0.00000 0.1995 + 0.73068 1.86175 0.00000 -0.36534 -0.93087 0.00000 0.1995 + 0.54168 1.92525 0.00000 -0.27084 -0.96262 0.00000 0.1995 + 0.34730 1.96962 0.00000 -0.17365 -0.98481 0.00000 0.1995 + 0.14946 1.99441 0.00000 -0.07473 -0.99720 0.00000 0.1995 + -0.04986 1.99938 0.00000 0.02493 -0.99969 0.00000 0.1995 + -0.24869 1.98448 0.00000 0.12434 -0.99224 0.00000 0.1995 + -0.44504 1.94986 0.00000 0.22252 -0.97493 0.00000 0.1995 + -0.63697 1.89585 0.00000 0.31849 -0.94793 0.00000 0.1995 + -0.82257 1.82301 0.00000 0.41129 -0.91151 0.00000 0.1995 + -1.00000 1.73205 0.00000 0.50000 -0.86603 0.00000 0.1995 + -1.16749 1.62388 0.00000 0.58374 -0.81194 0.00000 0.1995 + -1.32337 1.49956 0.00000 0.66169 -0.74978 0.00000 0.1995 + -1.46610 1.36035 0.00000 0.73305 -0.68017 0.00000 0.1995 + -1.59427 1.20761 0.00000 0.79713 -0.60380 0.00000 0.1995 + -1.70658 1.04287 0.00000 0.85329 -0.52144 0.00000 0.1995 + -1.80194 0.86777 0.00000 0.90097 -0.43388 0.00000 0.1995 + -1.87939 0.68404 0.00000 0.93969 -0.34202 0.00000 0.1995 + -1.93815 0.49351 0.00000 0.96908 -0.24676 0.00000 0.1995 + -1.97766 0.29808 0.00000 0.98883 -0.14904 0.00000 0.1995 + -1.99751 0.09969 0.00000 0.99876 -0.04985 0.00000 0.1995 + -1.99751 -0.09969 0.00000 0.99876 0.04985 0.00000 0.1995 + -1.97766 -0.29808 0.00000 0.98883 0.14904 0.00000 0.1995 + -1.93815 -0.49351 0.00000 0.96908 0.24676 0.00000 0.1995 + -1.87939 -0.68404 0.00000 0.93969 0.34202 0.00000 0.1995 + -1.80194 -0.86777 0.00000 0.90097 0.43388 0.00000 0.1995 + -1.70658 -1.04287 0.00000 0.85329 0.52144 0.00000 0.1995 + -1.59427 -1.20761 0.00000 0.79713 0.60380 0.00000 0.1995 + -1.46610 -1.36035 0.00000 0.73305 0.68017 0.00000 0.1995 + -1.32337 -1.49956 0.00000 0.66169 0.74978 0.00000 0.1995 + -1.16749 -1.62388 0.00000 0.58374 0.81194 0.00000 0.1995 + -1.00000 -1.73205 0.00000 0.50000 0.86603 0.00000 0.1995 + -0.82257 -1.82301 0.00000 0.41129 0.91151 0.00000 0.1995 + -0.63697 -1.89585 0.00000 0.31849 0.94793 0.00000 0.1995 + -0.44504 -1.94986 0.00000 0.22252 0.97493 0.00000 0.1995 + -0.24869 -1.98448 0.00000 0.12434 0.99224 0.00000 0.1995 + -0.04986 -1.99938 0.00000 0.02493 0.99969 0.00000 0.1995 + 0.14946 -1.99441 0.00000 -0.07473 0.99720 0.00000 0.1995 + 0.34730 -1.96962 0.00000 -0.17365 0.98481 0.00000 0.1995 + 0.54168 -1.92525 0.00000 -0.27084 0.96262 0.00000 0.1995 + 0.73068 -1.86175 0.00000 -0.36534 0.93087 0.00000 0.1995 + 0.91242 -1.77974 0.00000 -0.45621 0.88987 0.00000 0.1995 + 1.08509 -1.68005 0.00000 -0.54255 0.84003 0.00000 0.1995 + 1.24698 -1.56366 0.00000 -0.62349 0.78183 0.00000 0.1995 + 1.39647 -1.43173 0.00000 -0.69824 0.71587 0.00000 0.1995 + 1.53209 -1.28558 0.00000 -0.76604 0.64279 0.00000 0.1995 + 1.65248 -1.12664 0.00000 -0.82624 0.56332 0.00000 0.1995 + 1.75644 -0.95651 0.00000 -0.87822 0.47825 0.00000 0.1995 + 1.84295 -0.77687 0.00000 -0.92148 0.38843 0.00000 0.1995 + 1.91115 -0.58951 0.00000 -0.95557 0.29476 0.00000 0.1995 + 1.96034 -0.39629 0.00000 -0.98017 0.19815 0.00000 0.1995 + 1.99006 -0.19914 0.00000 -0.99503 0.09957 0.00000 0.1995 + ]; +x0_box_ref = [ + 2.2000 -2.0000 0 -1.0000 0 0 0.2414 + 2.2000 -1.8000 0 -1.0000 0 0 0.2000 + 2.2000 -1.6000 0 -1.0000 0 0 0.2000 + 2.2000 -1.4000 0 -1.0000 0 0 0.2000 + 2.2000 -1.2000 0 -1.0000 0 0 0.2000 + 2.2000 -1.0000 0 -1.0000 0 0 0.2000 + 2.2000 -0.8000 0 -1.0000 0 0 0.2000 + 2.2000 -0.6000 0 -1.0000 0 0 0.2000 + 2.2000 -0.4000 0 -1.0000 0 0 0.2000 + 2.2000 -0.2000 0 -1.0000 0 0 0.2000 + 2.2000 0 0 -1.0000 0 0 0.2000 + 2.2000 0.2000 0 -1.0000 0 0 0.2000 + 2.2000 0.4000 0 -1.0000 0 0 0.2000 + 2.2000 0.6000 0 -1.0000 0 0 0.2000 + 2.2000 0.8000 0 -1.0000 0 0 0.2000 + 2.2000 1.0000 0 -1.0000 0 0 0.2000 + 2.2000 1.2000 0 -1.0000 0 0 0.2000 + 2.2000 1.4000 0 -1.0000 0 0 0.2000 + 2.2000 1.6000 0 -1.0000 0 0 0.2000 + 2.2000 1.8000 0 -1.0000 0 0 0.2000 + 2.2000 2.0000 0 -1.0000 0 0 0.2414 + 2.0000 2.2000 0 0 -1.0000 0 0.2414 + 1.8000 2.2000 0 0 -1.0000 0 0.2000 + 1.6000 2.2000 0 0 -1.0000 0 0.2000 + 1.4000 2.2000 0 0 -1.0000 0 0.2000 + 1.2000 2.2000 0 0 -1.0000 0 0.2000 + 1.0000 2.2000 0 0 -1.0000 0 0.2000 + 0.8000 2.2000 0 0 -1.0000 0 0.2000 + 0.6000 2.2000 0 0 -1.0000 0 0.2000 + 0.4000 2.2000 0 0 -1.0000 0 0.2000 + 0.2000 2.2000 0 0 -1.0000 0 0.2000 + 0 2.2000 0 0 -1.0000 0 0.2000 + -0.2000 2.2000 0 0 -1.0000 0 0.2000 + -0.4000 2.2000 0 0 -1.0000 0 0.2000 + -0.6000 2.2000 0 0 -1.0000 0 0.2000 + -0.8000 2.2000 0 0 -1.0000 0 0.2000 + -1.0000 2.2000 0 0 -1.0000 0 0.2000 + -1.2000 2.2000 0 0 -1.0000 0 0.2000 + -1.4000 2.2000 0 0 -1.0000 0 0.2000 + -1.6000 2.2000 0 0 -1.0000 0 0.2000 + -1.8000 2.2000 0 0 -1.0000 0 0.2000 + -2.0000 2.2000 0 0 -1.0000 0 0.2414 + -2.2000 2.0000 0 1.0000 0 0 0.2414 + -2.2000 1.8000 0 1.0000 0 0 0.2000 + -2.2000 1.6000 0 1.0000 0 0 0.2000 + -2.2000 1.4000 0 1.0000 0 0 0.2000 + -2.2000 1.2000 0 1.0000 0 0 0.2000 + -2.2000 1.0000 0 1.0000 0 0 0.2000 + -2.2000 0.8000 0 1.0000 0 0 0.2000 + -2.2000 0.6000 0 1.0000 0 0 0.2000 + -2.2000 0.4000 0 1.0000 0 0 0.2000 + -2.2000 0.2000 0 1.0000 0 0 0.2000 + -2.2000 0 0 1.0000 0 0 0.2000 + -2.2000 -0.2000 0 1.0000 0 0 0.2000 + -2.2000 -0.4000 0 1.0000 0 0 0.2000 + -2.2000 -0.6000 0 1.0000 0 0 0.2000 + -2.2000 -0.8000 0 1.0000 0 0 0.2000 + -2.2000 -1.0000 0 1.0000 0 0 0.2000 + -2.2000 -1.2000 0 1.0000 0 0 0.2000 + -2.2000 -1.4000 0 1.0000 0 0 0.2000 + -2.2000 -1.6000 0 1.0000 0 0 0.2000 + -2.2000 -1.8000 0 1.0000 0 0 0.2000 + -2.2000 -2.0000 0 1.0000 0 0 0.2414 + -2.0000 -2.2000 0 0 1.0000 0 0.2414 + -1.8000 -2.2000 0 0 1.0000 0 0.2000 + -1.6000 -2.2000 0 0 1.0000 0 0.2000 + -1.4000 -2.2000 0 0 1.0000 0 0.2000 + -1.2000 -2.2000 0 0 1.0000 0 0.2000 + -1.0000 -2.2000 0 0 1.0000 0 0.2000 + -0.8000 -2.2000 0 0 1.0000 0 0.2000 + -0.6000 -2.2000 0 0 1.0000 0 0.2000 + -0.4000 -2.2000 0 0 1.0000 0 0.2000 + -0.2000 -2.2000 0 0 1.0000 0 0.2000 + 0 -2.2000 0 0 1.0000 0 0.2000 + 0.2000 -2.2000 0 0 1.0000 0 0.2000 + 0.4000 -2.2000 0 0 1.0000 0 0.2000 + 0.6000 -2.2000 0 0 1.0000 0 0.2000 + 0.8000 -2.2000 0 0 1.0000 0 0.2000 + 1.0000 -2.2000 0 0 1.0000 0 0.2000 + 1.2000 -2.2000 0 0 1.0000 0 0.2000 + 1.4000 -2.2000 0 0 1.0000 0 0.2000 + 1.6000 -2.2000 0 0 1.0000 0 0.2000 + 1.8000 -2.2000 0 0 1.0000 0 0.2000 + 2.0000 -2.2000 0 0 1.0000 0 0.2414 + ]; + +% test scenarios +scenarios = { + 'Equi-distant linear loudspeaker array' 'linear' 21 4.0 1.0 x0_linear_ref + 'Logarithmic linear loudspeaker array' 'linear' 7 14.0 4.0 x0_linear_log_pos_ref + 'Logarithmic linear loudspeaker array' 'linear' 7 14.0 0.25 x0_linear_log_neg_ref + 'Circular loudspeaker array' 'circle' 63 4.0 NaN x0_circle_ref + 'Box shaped loudspeaker array' 'box' 84 4.0 NaN x0_box_ref + }; + +%% ===== Test secondary source positions ================================= +% Start testing +for ii=1:size(scenarios) + + conf.secondary_sources.geometry = scenarios{ii,2}; + conf.secondary_sources.number = scenarios{ii,3}; + conf.secondary_sources.size = scenarios{ii,4}; + conf.secondary_sources.logspread = scenarios{ii,5}; + x0_ref = scenarios{ii,6}; + + x0 = secondary_source_positions(conf); + switch modus + case 0 + % Numerical mode (quiet) + if ~all(eq(size(x0),size(x0_ref))) || ~all(abs(x0(:)-x0_ref(:))<1e-4) + return; + end + case 1 + % Graphical mode + figure + draw_loudspeakers(x0,[1 1 0],conf); + title(scenarios{ii,1}); + xlabel('x / m') + ylabel('y / m') + case 2 + % Numerical mode (verbose) + if ~all(eq(size(x0),size(x0_ref))) + error('%s: wrong size of %s.',upper(mfilename), scenarios{ii,1}); + elseif ~all(abs(x0(:)-x0_ref(:))<1e-4) + error('%s: wrong value at %s.',upper(mfilename), scenarios{ii,1}); + end + otherwise + + error(['%s: modus has to be 0 (numerical quiet), 1 (graphical), ', ... + 'or 2 (numerical).'],upper(mfilename)); + end +end + +status = true; diff --git a/validation/test_secondary_source_selection.m b/validation/test_secondary_source_selection.m new file mode 100644 index 00000000..7dc0c354 --- /dev/null +++ b/validation/test_secondary_source_selection.m @@ -0,0 +1,150 @@ +function status = test_secondary_source_selection(modus) +%TEST_SECONDARY_SOURCE_SELECTION tests the correctness of +%secondary_source_selection() +% +% Usage: status = test_secondary_source_selection(modus) +% +% Input parameters: +% modus - 0: numerical (quiet) +% 1: visual (not available) +% 2: numerical verbose +% +% Output parameters: +% status - true or false + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters =================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Main ============================================================ +conf = SFS_config; +conf.secondary_sources.number = 16; +% reference values +ref_selection_circular_pw = ... + [0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0]'; +ref_selection_circular_ps = ... + [0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0]'; +ref_selection_circular_fs = ... + [1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0]'; +ref_selection_linear_pw = ... + [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]'; +ref_selection_linear_ps = ... + [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]'; +ref_selection_linear_fs = ... + [0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1]'; +ref_selection_box_pw = ... + [0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0]'; +ref_selection_box_ps = ... + [0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0]'; +ref_selection_box_fs = ... + [0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0]'; +% Calculate current values +% circular array +conf.secondary_source.geometry = 'circular'; +x0 = secondary_source_positions(conf); +[~,selection_circular_pw] = secondary_source_selection(x0,[0 -1 0],'pw'); +[~,selection_circular_ps] = secondary_source_selection(x0,[0 2.5 0],'ps'); +[~,selection_circular_fs] = secondary_source_selection(x0,[0.5 0.5 0 -1 -1 0],'fs'); +% linear array +conf.secondary_sources.geometry = 'linear'; +x0 = secondary_source_positions(conf); +[~,selection_linear_pw] = secondary_source_selection(x0,[0 -1 0],'pw'); +[~,selection_linear_ps] = secondary_source_selection(x0,[0 1 0],'ps'); +[~,selection_linear_fs] = secondary_source_selection(x0,[0.5 -0.5 0 -1 -1 0],'fs'); +% box form array +conf.secondary_sources.geometry = 'box'; +x0 = secondary_source_positions(conf); +[~,selection_box_pw] = secondary_source_selection(x0,[0 -1 0],'pw'); +[~,selection_box_ps] = secondary_source_selection(x0,[0 3.5 0],'ps'); +[~,selection_box_fs] = secondary_source_selection(x0,[0.5 0.5 0 -1 -1 0],'fs'); + +if modus==0 + % Numerical mode (quiet) + if ~all(eq(ref_selection_circular_pw,selection_circular_pw)) || ... + ~all(eq(ref_selection_circular_ps,selection_circular_ps)) || ... + ~all(eq(ref_selection_circular_fs,selection_circular_fs)) || ... + ~all(eq(ref_selection_linear_pw,selection_linear_pw)) || ... + ~all(eq(ref_selection_linear_ps,selection_linear_ps)) || ... + ~all(eq(ref_selection_linear_fs,selection_linear_fs)) || ... + ~all(eq(ref_selection_box_pw,selection_box_pw)) || ... + ~all(eq(ref_selection_box_ps,selection_box_ps)) || ... + ~all(eq(ref_selection_box_fs,selection_box_fs)) + return; + end +elseif modus==2 + message = 'wrong secondary source selection for a'; + if ~all(eq(ref_selection_circular_pw,selection_circular_pw)) + error('%s: %s circular array and a plane wave.', ... + upper(mfilename),message); + end + if ~all(eq(ref_selection_circular_ps,selection_circular_ps)) + error('%s: %s circular array and a point source.', ... + upper(mfilename),message); + end + if ~all(eq(ref_selection_circular_fs,selection_circular_fs)) + error('%s: %s circular array and a focused source.', ... + upper(mfilename),message); + end + if ~all(eq(ref_selection_linear_pw,selection_linear_pw)) + error('%s: %s linear array and a plane wave.', ... + upper(mfilename),message); + end + if ~all(eq(ref_selection_linear_ps,selection_linear_ps)) + error('%s: %s linear array and a point source.', ... + upper(mfilename),message); + end + if ~all(eq(ref_selection_linear_fs,selection_linear_fs)) + error('%s: %s linear array anda focused source.', ... + upper(mfilename),message); + end + if ~all(eq(ref_selection_box_pw,selection_box_pw)) + error('%s: %s box shaped array and a plane wave.', ... + upper(mfilename),message); + end + if ~all(eq(ref_selection_box_ps,selection_box_ps)) + error('%s: %s box shaped array and a point source.', ... + upper(mfilename),message); + end + if ~all(eq(ref_selection_box_fs,selection_box_fs)) + error('%s: %s box shaped array and a focused source.', ... + upper(mfilename),message); + end +end + + +status = true; diff --git a/validation/test_secondary_sources.m b/validation/test_secondary_sources.m deleted file mode 100644 index e98be3c5..00000000 --- a/validation/test_secondary_sources.m +++ /dev/null @@ -1,294 +0,0 @@ -function boolean = test_secondary_sources(modus) -%TEST_SECONDARY_SOURCES tests the correctness of the secondary source -%functions -% -% Usage: boolean = test_secondary_sources(modus) -% -% Input parameters: -% modus - 0: numerical (quiet) -% 1: numerical (verbose) -% 2: visual -% -% Output parameters: -% booelan - true or false -% -% TEST_SECONDARY_SOURCES(modus) checks if the functions, that calculates -% the secondary source positions and directions are working correctly. - -%***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * -% * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * -% * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * -% * -% The SFS 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, see . * -% * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * -% * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * -%***************************************************************************** - - -%% ===== Checking of input parameters =================================== -nargmin = 1; -nargmax = 1; -narginchk(nargmin,nargmax); - - -%% ===== Main ============================================================ -conf = SFS_config_example; -conf.secondary_sources.size = 4; -boolean = true; -% reference values -x0_linear_ref = [ - -2.0000 0 0 0 -1.0000 0 1 - -1.8000 0 0 0 -1.0000 0 1 - -1.6000 0 0 0 -1.0000 0 1 - -1.4000 0 0 0 -1.0000 0 1 - -1.2000 0 0 0 -1.0000 0 1 - -1.0000 0 0 0 -1.0000 0 1 - -0.8000 0 0 0 -1.0000 0 1 - -0.6000 0 0 0 -1.0000 0 1 - -0.4000 0 0 0 -1.0000 0 1 - -0.2000 0 0 0 -1.0000 0 1 - 0 0 0 0 -1.0000 0 1 - 0.2000 0 0 0 -1.0000 0 1 - 0.4000 0 0 0 -1.0000 0 1 - 0.6000 0 0 0 -1.0000 0 1 - 0.8000 0 0 0 -1.0000 0 1 - 1.0000 0 0 0 -1.0000 0 1 - 1.2000 0 0 0 -1.0000 0 1 - 1.4000 0 0 0 -1.0000 0 1 - 1.6000 0 0 0 -1.0000 0 1 - 1.8000 0 0 0 -1.0000 0 1 - 2.0000 0 0 0 -1.0000 0 1 - ]; -x0_circle_ref = [ - 2.00000 0.00000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 1.99006 0.19914 0.00000 -0.99503 -0.09957 0.00000 1.00000 - 1.96034 0.39629 0.00000 -0.98017 -0.19815 0.00000 1.00000 - 1.91115 0.58951 0.00000 -0.95557 -0.29476 0.00000 1.00000 - 1.84295 0.77687 0.00000 -0.92148 -0.38843 0.00000 1.00000 - 1.75644 0.95651 0.00000 -0.87822 -0.47825 0.00000 1.00000 - 1.65248 1.12664 0.00000 -0.82624 -0.56332 0.00000 1.00000 - 1.53209 1.28558 0.00000 -0.76604 -0.64279 0.00000 1.00000 - 1.39647 1.43173 0.00000 -0.69824 -0.71587 0.00000 1.00000 - 1.24698 1.56366 0.00000 -0.62349 -0.78183 0.00000 1.00000 - 1.08509 1.68005 0.00000 -0.54255 -0.84003 0.00000 1.00000 - 0.91242 1.77974 0.00000 -0.45621 -0.88987 0.00000 1.00000 - 0.73068 1.86175 0.00000 -0.36534 -0.93087 0.00000 1.00000 - 0.54168 1.92525 0.00000 -0.27084 -0.96262 0.00000 1.00000 - 0.34730 1.96962 0.00000 -0.17365 -0.98481 0.00000 1.00000 - 0.14946 1.99441 0.00000 -0.07473 -0.99720 0.00000 1.00000 - -0.04986 1.99938 0.00000 0.02493 -0.99969 0.00000 1.00000 - -0.24869 1.98448 0.00000 0.12434 -0.99224 0.00000 1.00000 - -0.44504 1.94986 0.00000 0.22252 -0.97493 0.00000 1.00000 - -0.63697 1.89585 0.00000 0.31849 -0.94793 0.00000 1.00000 - -0.82257 1.82301 0.00000 0.41129 -0.91151 0.00000 1.00000 - -1.00000 1.73205 0.00000 0.50000 -0.86603 0.00000 1.00000 - -1.16749 1.62388 0.00000 0.58374 -0.81194 0.00000 1.00000 - -1.32337 1.49956 0.00000 0.66169 -0.74978 0.00000 1.00000 - -1.46610 1.36035 0.00000 0.73305 -0.68017 0.00000 1.00000 - -1.59427 1.20761 0.00000 0.79713 -0.60380 0.00000 1.00000 - -1.70658 1.04287 0.00000 0.85329 -0.52144 0.00000 1.00000 - -1.80194 0.86777 0.00000 0.90097 -0.43388 0.00000 1.00000 - -1.87939 0.68404 0.00000 0.93969 -0.34202 0.00000 1.00000 - -1.93815 0.49351 0.00000 0.96908 -0.24676 0.00000 1.00000 - -1.97766 0.29808 0.00000 0.98883 -0.14904 0.00000 1.00000 - -1.99751 0.09969 0.00000 0.99876 -0.04985 0.00000 1.00000 - -1.99751 -0.09969 0.00000 0.99876 0.04985 0.00000 1.00000 - -1.97766 -0.29808 0.00000 0.98883 0.14904 0.00000 1.00000 - -1.93815 -0.49351 0.00000 0.96908 0.24676 0.00000 1.00000 - -1.87939 -0.68404 0.00000 0.93969 0.34202 0.00000 1.00000 - -1.80194 -0.86777 0.00000 0.90097 0.43388 0.00000 1.00000 - -1.70658 -1.04287 0.00000 0.85329 0.52144 0.00000 1.00000 - -1.59427 -1.20761 0.00000 0.79713 0.60380 0.00000 1.00000 - -1.46610 -1.36035 0.00000 0.73305 0.68017 0.00000 1.00000 - -1.32337 -1.49956 0.00000 0.66169 0.74978 0.00000 1.00000 - -1.16749 -1.62388 0.00000 0.58374 0.81194 0.00000 1.00000 - -1.00000 -1.73205 0.00000 0.50000 0.86603 0.00000 1.00000 - -0.82257 -1.82301 0.00000 0.41129 0.91151 0.00000 1.00000 - -0.63697 -1.89585 0.00000 0.31849 0.94793 0.00000 1.00000 - -0.44504 -1.94986 0.00000 0.22252 0.97493 0.00000 1.00000 - -0.24869 -1.98448 0.00000 0.12434 0.99224 0.00000 1.00000 - -0.04986 -1.99938 0.00000 0.02493 0.99969 0.00000 1.00000 - 0.14946 -1.99441 0.00000 -0.07473 0.99720 0.00000 1.00000 - 0.34730 -1.96962 0.00000 -0.17365 0.98481 0.00000 1.00000 - 0.54168 -1.92525 0.00000 -0.27084 0.96262 0.00000 1.00000 - 0.73068 -1.86175 0.00000 -0.36534 0.93087 0.00000 1.00000 - 0.91242 -1.77974 0.00000 -0.45621 0.88987 0.00000 1.00000 - 1.08509 -1.68005 0.00000 -0.54255 0.84003 0.00000 1.00000 - 1.24698 -1.56366 0.00000 -0.62349 0.78183 0.00000 1.00000 - 1.39647 -1.43173 0.00000 -0.69824 0.71587 0.00000 1.00000 - 1.53209 -1.28558 0.00000 -0.76604 0.64279 0.00000 1.00000 - 1.65248 -1.12664 0.00000 -0.82624 0.56332 0.00000 1.00000 - 1.75644 -0.95651 0.00000 -0.87822 0.47825 0.00000 1.00000 - 1.84295 -0.77687 0.00000 -0.92148 0.38843 0.00000 1.00000 - 1.91115 -0.58951 0.00000 -0.95557 0.29476 0.00000 1.00000 - 1.96034 -0.39629 0.00000 -0.98017 0.19815 0.00000 1.00000 - 1.99006 -0.19914 0.00000 -0.99503 0.09957 0.00000 1.00000 - ]; -x0_box_ref = [ - -2.00000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - -1.80000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - -1.60000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - -1.40000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - -1.20000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - -1.00000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - -0.80000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - -0.60000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - -0.40000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - -0.20000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - 0.00000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - 0.20000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - 0.40000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - 0.60000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - 0.80000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - 1.00000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - 1.20000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - 1.40000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - 1.60000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - 1.80000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - 2.00000 2.20000 0.00000 0.00000 -1.00000 0.00000 1.00000 - 2.20000 2.00000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 1.80000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 1.60000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 1.40000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 1.20000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 1.00000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 0.80000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 0.60000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 0.40000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 0.20000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 0.00000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 -0.20000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 -0.40000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 -0.60000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 -0.80000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 -1.00000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 -1.20000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 -1.40000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 -1.60000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 -1.80000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.20000 -2.00000 0.00000 -1.00000 0.00000 0.00000 1.00000 - 2.00000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - 1.80000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - 1.60000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - 1.40000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - 1.20000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - 1.00000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - 0.80000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - 0.60000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - 0.40000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - 0.20000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - 0.00000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - -0.20000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - -0.40000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - -0.60000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - -0.80000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - -1.00000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - -1.20000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - -1.40000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - -1.60000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - -1.80000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - -2.00000 -2.20000 0.00000 0.00000 1.00000 0.00000 1.00000 - -2.20000 -2.00000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 -1.80000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 -1.60000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 -1.40000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 -1.20000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 -1.00000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 -0.80000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 -0.60000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 -0.40000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 -0.20000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 0.00000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 0.20000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 0.40000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 0.60000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 0.80000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 1.00000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 1.20000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 1.40000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 1.60000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 1.80000 0.00000 1.00000 0.00000 0.00000 1.00000 - -2.20000 2.00000 0.00000 1.00000 0.00000 0.00000 1.00000 - ]; - - -% Calculate current values -% linear array -conf.secondary_sources.geometry = 'linear'; -conf.secondary_sources.number = 21; -x0_linear = secondary_source_positions(conf); -% circular array -conf.secondary_sources.geometry = 'circle'; -conf.secondary_sources.number = 63; -x0_circle = secondary_source_positions(conf); -% box form array -conf.secondary_sources.geometry = 'box'; -conf.secondary_sources.number = 84; -x0_box = secondary_source_positions(conf); - -if modus==0 - % Numerical mode (quiet) - if ~all(eq(size(x0_linear),size(x0_linear_ref))) || ... - ~all(eq(size(x0_circle),size(x0_circle_ref))) || ... - ~all(eq(size(x0_box),size(x0_box_ref))) || ... - ~all(abs(x0_linear(:)-x0_linear_ref(:))<1e-4) || ... - ~all(abs(x0_circle(:)-x0_circle_ref(:))<1e-4) || ... - ~all(abs(x0_box(:)-x0_box_ref(:))<1e-4) - boolean = false; - end -elseif modus==1 - if ~all(eq(size(x0_linear),size(x0_linear_ref))) - error('%s: wrong size of linear array.',upper(mfilename)); - elseif ~all(abs(x0_linear(:)-x0_linear_ref(:))<1e-4) - error('%s: wrong value at linear array.',upper(mfilename)); - end - if ~all(eq(size(x0_circle),size(x0_circle_ref))) - error('%s: wrong size of circular array.',upper(mfilename)); - elseif ~all(abs(x0_circle(:)-x0_circle_ref(:))<1e-4) - error('%s: wrong value at circular array.',upper(mfilename)); - end - if ~all(eq(size(x0_box),size(x0_box_ref))) - error('%s: wrong size of box shaped array.',upper(mfilename)); - elseif ~all(abs(x0_box(:)-x0_box_ref(:))<1e-4) - error('%s: wrong value at box shaped array.',upper(mfilename)); - end -elseif modus==2 - % Graphical mode - close all; - % draw results - figure - title('Linear loudspeaker array'); - draw_loudspeakers(x0_linear,[1 1 0],conf); - figure - title('Circular loudspeaker array'); - draw_loudspeakers(x0_circle,[1 1 0],conf); - figure - title('Box shape loudspeaker array'); - draw_loudspeakers(x0_box,[1 1 0],conf); -else - error(['%s: modus has to be 0 (numerical quiet), 1 (numerical), ', ... - 'or 2 (graphical).'],upper(mfilename)); -end diff --git a/validation/test_spectrum_signal_conversion.m b/validation/test_spectrum_signal_conversion.m new file mode 100644 index 00000000..61d0d90e --- /dev/null +++ b/validation/test_spectrum_signal_conversion.m @@ -0,0 +1,97 @@ +function status = test_spectrum_signal_conversion(modus) +%TEST_SPECTRUM_SIGNAL_CONVERSION tests the spectrum to and from signal +%conversions +% +% Usage: status = test_spectrum_signal_conversion(modus) +% +% Input parameters: +% modus - 0: numerical +% 1: visual +% +% Output parameters: +% status - true or false + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters =================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Configuration =================================================== +conf = SFS_config; +fs = conf.fs; +%% Create defined signal +t = 0 : 1/fs : 1 - 1/fs; % 1 s +sin1 = sin(2*pi*50 * t); +sin2 = sin(2*pi*300 * t); +sin3 = sin(2*pi*1000 * t); +sin_sig = (sin1 + sin2 + sin3)'; + +even_sig = ones(8, 1); +odd_sig = ones(7, 1); +alias_sig = repmat([1; -1], fs/2, 1); + +%% FFT +[sin_ampl, sin_phase, sin_f] = spectrum_from_signal(sin_sig, conf); +[even_ampl, even_phase, even_f] = spectrum_from_signal(even_sig, conf); +[odd_ampl, odd_phase, odd_f] = spectrum_from_signal(odd_sig, conf); +[alias_ampl, alias_phase, alias_f] = spectrum_from_signal(alias_sig, conf); + +%% Check frequency bins +if modus +figure; semilogx(sin_f,20*log10(sin_ampl)); title('Sinus Mix') +figure; scatter(even_f, even_ampl); title('Even signal (f=0) FFT'); +figure; scatter(odd_f, odd_ampl);title('Odd signal (f=0) FFT'); +figure; scatter(alias_f, alias_ampl);title('Signal with f=fs/2 FFT'); +end +%% IFFT +sin_outsig = signal_from_spectrum(sin_ampl, sin_phase, sin_f,conf); +even_outsig = signal_from_spectrum(even_ampl, even_phase, even_f,conf); +odd_outsig = signal_from_spectrum(odd_ampl, odd_phase, odd_f,conf); +alias_outsig = signal_from_spectrum(alias_ampl, alias_phase, alias_f,conf); + +%% Check Output +sin_diff = sum(abs(sin_sig - sin_outsig)); +even_diff = sum(abs(even_sig - even_outsig)); +odd_diff = sum(abs(odd_sig - odd_outsig)); +alias_diff = sum(abs(alias_sig - alias_outsig)); + +if sum(sin_diff + even_diff + odd_diff + alias_diff) < 10^(-8) + status = true; +end + +end + diff --git a/validation/test_sphbesselh_zeros.m b/validation/test_sphbesselh_zeros.m new file mode 100644 index 00000000..a4d93112 --- /dev/null +++ b/validation/test_sphbesselh_zeros.m @@ -0,0 +1,180 @@ +function status = test_sphbesselh_zeros(modus) +%TEST_SPHBESSELH_ZEROS tests the computation of the roots for spherical Bessel +%functions +% +% Usage: status = test_sphbesselh_zeros(modus) +% +% Input parameters: +% modus - 0: numerical +% 1: visual +% +% Output parameters: +% status - true or false + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subiect to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + +status = false; + +%% ===== Checking of input parameters =================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Main ============================================================ +markers = {'.', '^', '*', 'o'}; +linecolors = [ + 0 0.4470 0.7410 + 0.8500 0.3250 0.0980 + 0.9290 0.6940 0.1250 + 0.4940 0.1840 0.5560 + 0.4660 0.6740 0.1880 + 0.3010 0.7450 0.9330 + 0.6350 0.0780 0.1840 +]; +subplotdims = [2,3]; + +Nsym = length(markers); +Nsubplots = prod(subplotdims); +Ncolors = size(linecolors,1); +step = 2; + +% Check for warnings and plot zeros +if modus + figure; + for order=1:step:300 + % Some indices + gdx = (order-1)./step; % graph index + sdx = mod(gdx,Nsubplots)+1; % subfig index + mdx = mod(floor(gdx./(Nsubplots*Ncolors)), Nsym)+1; % marker index + cdx = mod(floor(gdx./Nsubplots), Ncolors)+1; % color index + % Plotting + [z,~] = sphbesselh_zeros(order); + subplot(subplotdims(1),subplotdims(2),sdx); + hold on; + plot(real(z), imag(z), ... + 'Color', linecolors(cdx,:), ... + 'Marker', markers{mdx}, ... + 'DisplayName', sprintf('%d',order)); + hold off; + end + % Add titles, legends, etc. + for sdx=1:Nsubplots + subplot(subplotdims(1),subplotdims(2),sdx); + xlim([min(real(z)),0]); + ylim([min(imag(z)),max(imag(z))]); + title_str = sprintf(['Zeros of spherical Bessel functions of ', ... + 'orders %i:12:%i'],2*sdx-1,2*sdx-1+288); + title(title_str); + end +else + for order=[1 10 100] + z = sphbesselh_zeros(order); + z_ref = ref_sphbesselh_zeros(order); + if any(abs(z-z_ref)>1e8) + return + end + end +end + +status = true; + +end + +function z = ref_sphbesselh_zeros(N) + % Return reference values for some orders as calculated by + % the following Python code: + % + % from scipy import signal + % for N in [1, 10, 100]: + % r = signal.filter_design._bessel_zeros(N) + % print(1/r) + switch N + case 1 + z = [-1-0i]; + case 10 + z = [-3.10891623+8.23269946i; -4.88621957+6.22498548i; ... + -5.96752833+4.38494719i; -6.61529097+2.61156792i; ... + -6.92204491+0.8676652i; -6.92204491-0.8676652i; ... + -6.61529097-2.61156792i; -5.96752833-4.38494719i; ... + -4.88621957-6.22498548i; -3.10891623-8.23269946i]; + case 100 + z = [ -7.27958017+96.07487622i; -16.56840794+89.69305883i; ... + -12.47552337+92.61711308i; -20.06460298+87.0388997i; ... + -23.16077972+84.55529001i; -25.95970766+82.1917017i; ... + -28.52378431+79.91820025i; -30.89456430+77.71529775i; ... + -33.10152255+75.5694611i; -35.16654671+73.47083873i; ... + -37.10646671+71.41199594i; -38.93458277+69.38715996i; ... + -40.66164008+67.39174367i; -43.84648113+63.47496561i; ... + -46.71605927+59.63895796i; -45.31789403+61.54799302i; ... + -48.04558910+57.74602015i; -49.31049835+55.86759414i; ... + -50.51430689+54.00230256i; -51.66011999+52.14893987i; ... + -42.29647848+65.42203167i; -52.75069221+50.30644364i; ... + -53.78847888+48.47387175i; -54.77567785+46.65038396i; ... + -55.71426383+44.83522681i; -56.60601678+43.02772133i; ... + -57.45254558+41.22725279i; -58.25530796+39.43326208i; ... + -59.01562729+37.64523857i; -59.73470691+35.86271397i; ... + -60.41364233+34.08525709i; -61.05343172+32.31246944i; ... + -61.65498500+30.54398132i; -62.21913160+28.77944847i; ... + -62.74662735+27.01854918i; -63.23816028+25.26098169i; ... + -63.69435590+23.50646194i; -64.11578160+21.75472159i; ... + -64.50295064+20.00550618i; -64.85632558+18.25857355i; ... + -65.17632127+16.5136924i; -65.46330747+14.77064097i; ... + -65.71761112+13.0292058i; -65.93951828+11.28918071i; ... + -66.12927583+9.5503657i; -66.28709289+7.81256601i; ... + -66.41314197+6.07559126i; -66.50755997+4.33925457i; ... + -66.57044891+2.60337173i; -66.60187650+0.86776044i; ... + -66.60187650-0.86776044i; -66.57044891-2.60337173i; ... + -66.50755997-4.33925457i; -66.41314197-6.07559126i; ... + -66.28709289-7.81256601i; -66.12927583-9.5503657i; ... + -65.93951828-11.28918071i; -65.71761112-13.0292058i; ... + -65.46330747-14.77064097i; -65.17632127-16.5136924i; ... + -64.85632558-18.25857355i; -64.50295064-20.00550618i; ... + -64.11578160-21.75472159i; -63.69435590-23.50646194i; ... + -63.23816028-25.26098169i; -62.74662735-27.01854918i; ... + -62.21913160-28.77944847i; -61.65498500-30.54398132i; ... + -61.05343172-32.31246944i; -60.41364233-34.08525709i; ... + -59.73470691-35.86271397i; -59.01562729-37.64523857i; ... + -58.25530796-39.43326208i; -57.45254558-41.22725279i; ... + -56.60601678-43.02772133i; -55.71426383-44.83522681i; ... + -54.77567785-46.65038396i; -53.78847888-48.47387175i; ... + -52.75069221-50.30644364i; -42.29647848-65.42203167i; ... + -51.66011999-52.14893987i; -50.51430689-54.00230256i; ... + -49.31049835-55.86759414i; -48.04558910-57.74602015i; ... + -45.31789403-61.54799302i; -46.71605927-59.63895796i; ... + -43.84648113-63.47496561i; -40.66164008-67.39174367i; ... + -38.93458277-69.38715996i; -37.10646671-71.41199594i; ... + -35.16654671-73.47083873i; -33.10152255-75.5694611i; ... + -30.89456430-77.71529775i; -28.52378431-79.91820025i; ... + -25.95970766-82.1917017i; -23.16077972-84.55529001i; ... + -20.06460298-87.0388997i; -12.47552337-92.61711308i; ... + -16.56840794-89.69305883i; -7.27958017-96.07487622i]; + end +end diff --git a/validation/test_tapering_window.m b/validation/test_tapering_window.m new file mode 100644 index 00000000..025746f6 --- /dev/null +++ b/validation/test_tapering_window.m @@ -0,0 +1,147 @@ +function status = test_tapering_window(modus) +%TEST_TAPERING_WINDOW tests the tapering_window() function for applying tapering +%to the secondary sources in Wave Field Synthesis +% +% Usage: status = test_tapering_window(modus) +% +% Input parameters: +% modus - 0: numerical (quiet) +% 1: visual (not available) +% 2: numerical verbose +% +% Output parameters: +% status - true or false + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters =================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Main ============================================================ +conf = SFS_config; +conf.secondary_sources.number = 16; +% reference values +ref_win_linear = [ + 0.25000 + 1.00000 + 1.00000 + 1.00000 + 1.00000 + 1.00000 + 1.00000 + 1.00000 + 1.00000 + 1.00000 + 1.00000 + 1.00000 + 1.00000 + 1.00000 + 1.00000 + 0.25000 +]; +ref_win_box = [ + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 +]; +ref_win_circular1 = [ + 1 + 1 + 1 + 1 + 1 +]; +ref_win_circular2 = [ + 1 + 1 + 1 + 1 + 1 +]; +% Calculate current values +% linear secondary sources +conf.secondary_sources.geometry = 'linear'; +x0 = secondary_source_positions(conf); +win_linear = tapering_window(x0,conf); +% box shaped secondary sources +conf.secondary_sources.geometry = 'box'; +x0 = secondary_source_positions(conf); +x0 = secondary_source_selection(x0,[-1 -1 0],'pw'); +win_box = tapering_window(x0,conf); +% circular secondary sources +conf.secondary_sources.geometry = 'circular'; +x0 = secondary_source_positions(conf); +x01 = secondary_source_selection(x0,[0 2.5 0],'ps'); +win_circular1 = tapering_window(x01,conf); +x02 = secondary_source_selection(x0,[2.5 0 0],'ps'); +win_circular2 = tapering_window(x02,conf); + +if modus==0 + % Numerical mode (quiet) + if sum(abs(ref_win_circular1-win_circular1))>eps || ... + sum(abs(ref_win_circular2-win_circular2))>eps || ... + sum(abs(ref_win_linear-win_linear))>eps || ... + sum(abs(ref_win_box-win_box))>eps + return; + end +elseif modus==2 + message = 'wrong tapering window for'; + if sum(abs(ref_win_circular1-win_circular1))>eps || ... + sum(abs(ref_win_circular2-win_circular2))>eps + error('%s: %s circular secondary sources.', ... + upper(mfilename),message); + end + if sum(abs(ref_win_linear-win_linear))>eps + error('%s: %s linear secondary sources.', ... + upper(mfilename),message); + end + if sum(abs(ref_win_box-win_box))>eps + error('%s: %s box shaped secondary sources.', ... + upper(mfilename),message); + end +else + error('%s: modus has to be 0 (numerical quiet), 1 (numerical), ', ... + upper(mfilename)); +end + + +status = true; diff --git a/validation/test_wfs_25d.m b/validation/test_wfs_25d.m new file mode 100644 index 00000000..232adc54 --- /dev/null +++ b/validation/test_wfs_25d.m @@ -0,0 +1,116 @@ +function status = test_wfs_25d(modus) +%TEST_WFS_25D tests behavior of 2.5D WFS +% +% Usage: status = test_wfs_25d(modus) +% +% Input parameters: +% modus - 0: numerical +% 1: visual +% +% Output parameters: +% status - true or false + +%***************************************************************************** +% The MIT License (MIT) * +% * +% Copyright (c) 2010-2019 SFS Toolbox Developers * +% * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * +% * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * +% * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * +% * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * +% * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * +%***************************************************************************** + + +status = false; + + +%% ===== Checking of input parameters =================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + + +%% ===== Configuration =================================================== +% Parameters +conf = SFS_config; +conf.secondary_sources.geometry = 'linear'; +conf.secondary_sources.size = 20; +conf.secondary_sources.number = 512; +conf.secondary_sources.center = [0,6,0]; +conf.xref = [0,0,0]; +conf.usetapwin = true; +conf.tapwinlen = 0.2; + +% +f = 2000; % temporal frequency +positions = { [0,9,0], [0,-1,0], [0,3,0,0,-1,0] }; % source positions +sources = {'ps', 'pw', 'fs'}; +gtsources = {'ps', 'pw', 'ps'}; +X = [-2,2]; +Y = [-2,2]; +Z = 0; + + +%% ===== Main ============================================================ +for idx=1:length(positions) + xs = positions{idx}; + src = sources{idx}; + gt = gtsources{idx}; + + if modus + figure; + ddx = 0; + end + + for driving_functions = {'reference_point', 'reference_line'} + + conf.driving_functions = driving_functions{:}; + Pgt = sound_field_mono(X,Y,Z,[xs(1:3),0,-1,0,1],gt,1,f,conf); + Pwfs = sound_field_mono_wfs(X,Y,Z,xs,src,f,conf); + + if modus + subplot(2,2,2*ddx+1); + imagesc(Y,X,real(Pwfs)); + title(sprintf('%s %s',src,driving_functions{:}),'Interpreter','none'); + set(gca,'YDir','normal'); + colorbar; + + subplot(2,2,2*ddx+2); + imagesc(Y,X,real(db(1 - Pwfs./Pgt))); + title(sprintf('%s %s',src,driving_functions{:}),'Interpreter','none'); + set(gca,'YDir','normal'); + colorbar; + hold on; + if strcmp('reference_point',conf.driving_functions) + plot(conf.xref(1),conf.xref(2),'gx'); + else + plot(conf.xref(1)+X,conf.xref([2,2]),'g--'); + end + hold off; + + ddx= ddx+1; + end + end +end + + +status = true; diff --git a/validation/test_wfs_iir_prefilter.m b/validation/test_wfs_iir_prefilter.m index b55d7425..50cfc20c 100644 --- a/validation/test_wfs_iir_prefilter.m +++ b/validation/test_wfs_iir_prefilter.m @@ -1,52 +1,60 @@ -function boolean = test_wfs_iir_prefilter() +function status = test_wfs_iir_prefilter(modus) %TEST_WFS_IIR_PREFILTER tests the IIR WFS pre-equalization filter % -% Usage: boolean = test_wfs_iir_prefilter() +% Usage: status = test_wfs_iir_prefilter(modus) +% +% Input parameters: +% modus - 0: numerical +% 1: visual (not available) % % Output parameters: -% booelan - true or false +% status - true or false % -% TEST_WFS_IIR_PREFILTER() test the WFS pre-euqalization IIR filter +% TEST_WFS_IIR_PREFILTER(modus) test the WFS pre-euqalization IIR filter % design. This works only in Matlab as the Signal Processing Toolbox is used. % See wfs_iir_prefilter.m for details %***************************************************************************** -% Copyright (c) 2010-2015 Quality & Usability Lab, together with * -% Assessment of IP-based Applications * -% Telekom Innovation Laboratories, TU Berlin * -% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * -% * -% Copyright (c) 2013-2015 Institut fuer Nachrichtentechnik * -% Universitaet Rostock * -% Richard-Wagner-Strasse 31, 18119 Rostock * +% The MIT License (MIT) * % * -% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% Copyright (c) 2010-2019 SFS Toolbox Developers * % * -% The SFS 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 3 of the License, or (at your option) * -% any later version. * +% Permission is hereby granted, free of charge, to any person obtaining a * +% copy of this software and associated documentation files (the "Software"), * +% to deal in the Software without restriction, including without limitation * +% the rights to use, copy, modify, merge, publish, distribute, sublicense, * +% and/or sell copies of the Software, and to permit persons to whom the * +% Software is furnished to do so, subject to the following conditions: * % * -% The SFS 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. * +% The above copyright notice and this permission notice shall be included in * +% all copies or substantial portions of the Software. * % * -% You should have received a copy of the GNU General Public License along * -% with this program. If not, see . * +% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * +% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * +% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * +% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * +% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * +% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * +% DEALINGS IN THE SOFTWARE. * % * -% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * -% field synthesis methods like wave field synthesis or higher order * -% ambisonics. * +% The SFS Toolbox allows to simulate and investigate sound field synthesis * +% methods like wave field synthesis or higher order ambisonics. * % * -% http://github.com/sfstoolbox/sfs sfstoolbox@gmail.com * +% https://sfs.readthedocs.io sfstoolbox@gmail.com * %***************************************************************************** +status = false; + + +%% ===== Checking of input parameters ==================================== +nargmin = 1; +nargmax = 1; +narginchk(nargmin,nargmax); + %% ===== Configuration =================================================== -boolean = false; -conf = SFS_config_example; +conf = SFS_config; %% ===== Calculation ===================================================== @@ -58,4 +66,6 @@ conf.hpreBandwidth_in_Oct = 2; conf.hpreIIRorder = 4; hpre2 = wfs_iir_prefilter(conf) -boolean = true; + + +status = true;